본문으로 건너뛰기

Vim 삭제 명령이 OS 클립보드를 덮어쓰는 문제 해결하기

 · reading-time-plural

Vim에서 삭제는 잘라내기로 동작한다. OS에서 복사한 값을 붙여넣기 전 텍스트를 정리하며 제거된 값이 OS에서 복사한 값을 지워버린다. 왜냐면 잘라내기로 동작하기 때문이다. 이 불편함을 어떻게 해결할 수 있을까?

Vim 클립보드 내용을 검색하면 다들 OS 클립보드 연동하는 방법만 있지 Vim에서 삭제 시 OS 클립보드 값을 지키는 내용은 없더라. 나만 불편한 것인가...?

문제 원인

보통 set clipboard=unnamedplus 설정하여 OS ↔ Vim 클립보드를 동기화 한다.

OS ↔ Vim 클립보드와 연결만 하면 복사, 붙여넣기 시 매번 "+y , "+p 같이 + , * 레지스터 지정해야 해서 불편하다.

set clipboard=unnamedplus 문제는 OS에서 복사한 값이 dd , x 같이 Vim 제거 동작 시 사라진다는 것이다.

상황에 따라 다르지만 보통 복사 후 붙여넣기 전까지 입력도 하고 삭제도 하며 텍스트 가공이 이루어지는데 삭제를 해버리면 OS 클립보드 값이 사라져서 곤란하다.

Vim0 번 레지스터는 삭제가 이루어져도 유지되는 것과 다르다. 이유는 OS ↔ Vim 클립보드를 동기화했기 때문에 삭제하는 것도 OS에 동기화하면서 발생한다.

문제 해결을 위해선 OS의 값을 붙여넣기 전까지 블랙홀 레지스터로 OS에서 복사한 값을 잘 유지해야 한다.

해결 방법

손쉽게 블랙홀 레지스터로 보내기

블랙홀 레지스터 단축키 입력이 생각보다 많이 불편하다.

그래서 처음에는 블랙홀 레지스터를 손쉽게 보내도록 키 맵핑을 했다.

" 블랙홀 레지스터 쉽게 호출할 수 있도록 맵핑
nnoremap <Space>x "_x
vnoremap <Space>x "_x

nnoremap <Space>X "_X
vnoremap <Space>X "_X

nnoremap <Space>s "_s
vnoremap <Space>s "_s

nnoremap <Space>S "_S
vnoremap <Space>S "_S

nnoremap <Space>c "_c
vnoremap <Space>c "_c

nnoremap <Space>C "_C
vnoremap <Space>C "_C

nnoremap <Space>d "_d
vnoremap <Space>d "_d

nnoremap <Space>D "_D
vnoremap <Space>D "_D

nnoremap <Space>dd "_dd
vnoremap <Space>dd "_dd

삭제와 잘라내기 동작 구분

하지만 이것 또한 귀찮다.

근본적으로 Vim의 레지스터 동작이 보편적으로 사용되는 OS과 달라서 생긴 문제라고 생각이 들었다. 삭제 != 잘라내기 인데 Vim은 삭제 = 잘라내기 동작을 하니 말이다. 그래서 잘라내기만 동작하도록 명시적으로 키 맵핑을 지정해서 해결했다.

--
--
-- 명시적인 호출 시에만 삭제 레지스터로 이동
-- 삭제를 하더라도 OS 클립보드 값을 보호하기 위함
-- 기본적으로 삭제는 블랙홀 레지스터 사용
vim.keymap.set("n", "d", '"_d')
vim.keymap.set("v", "d", '"_d')

vim.keymap.set("n", "D", '"_D')
vim.keymap.set("v", "D", '"_D')

vim.keymap.set("n", "dd", '"_dd')
vim.keymap.set("v", "dd", '"_dd')

vim.keymap.set("n", "x", '"_x')
vim.keymap.set("v", "x", '"_x')

vim.keymap.set("n", "X", '"_X')
vim.keymap.set("v", "X", '"_X')

vim.keymap.set("n", "s", '"_s')
vim.keymap.set("v", "s", '"_s')

vim.keymap.set("n", "S", '"_S')
vim.keymap.set("v", "S", '"_S')

vim.keymap.set("n", "c", '"_c')
vim.keymap.set("v", "c", '"_c')

vim.keymap.set("n", "C", '"_C')
vim.keymap.set("v", "C", '"_C')

-- Space + 삭제 입력 시 원래 동작(클립보드 사용) 유지: 잘라내기 동작
vim.keymap.set("n", "<Space>d", "d")
vim.keymap.set("v", "<Space>d", "d")

vim.keymap.set("n", "<Space>D", "D")
vim.keymap.set("v", "<Space>D", "D")

vim.keymap.set("n", "<Space>dd", "dd")
vim.keymap.set("v", "<Space>dd", "dd")

vim.keymap.set("n", "<Space>x", "x")
vim.keymap.set("v", "<Space>x", "x")

vim.keymap.set("n", "<Space>X", "X")
vim.keymap.set("v", "<Space>X", "X")

vim.keymap.set("n", "<Space>s", "s")
vim.keymap.set("v", "<Space>s", "s")

vim.keymap.set("n", "<Space>S", "S")
vim.keymap.set("v", "<Space>S", "S")

vim.keymap.set("n", "<Space>c", "c")
vim.keymap.set("v", "<Space>c", "c")

vim.keymap.set("n", "<Space>C", "C")
vim.keymap.set("v", "<Space>C", "C")

이렇게 하면 아래의 장/단점을 가지게 된다.

  • 장점
    • 보편적인 OS에서 사용하는 것과 동일하게 클립보드 관리 가능
    • 복사한 것은 다른 복사가 오거나 잘라내기 전까지 유지된다.
    • 삭제는 삭제다.
    • 잘라내기 시 해당 값으로 복사 값이 변경된다.
  • 단점
    • Vim에서 삭제 시 "1 ~ "9 으로 저장되는 삭제 히스토리를 사용하지 못함
    • 개인적으로는 "1 ~ "9 을 사용한 적이 거의 없다. 코딩하면서 삭제는 워낙에 빈번하게 일어나기에 기억도 안난다. 설령 제거한 적을 저장하고 싶다면 명시적으로 레지스터를 할당에서 저장하는 것이 관리도 기억도 잘 될 것이라고 생각한다.
    • macOS의 경우 RayCast를 통해서 클립보드 히스토리 관리가 가능하기 때문에 기능 보안도 가능하다.

마무리

삭제와 잘라내기 동작을 구분하도록 키 맵핑 후 한동안 삭제 후 왜 삭제 레지스터에 값이 들어가지 않았지? 하고 해매고 있다.

적응이 되면 편해질 것 같지만 꼭 이렇게 Vim 동작을 바꿔야하나 생각이 든다.


parkgang
태그 🏷