Vim – 레지스터에 관해

vim에서 문자열을 복사하는 것을 매뉴얼에서는 copy가 아니라 yank로 설명한다. 이는 전통적인 이유가 있긴한데, 어쨌든 보통의 응용프로그램에서의 ‘복사’는 클립보드에 콘텐츠를 써 넣는 것을 의미한다. 하지만 vim은 항상 클립보드를 사용할 수 있는 것은 아니다. 대신에 ‘레지스터’라는 별도의 메모리 공간을 사용해서 텍스트를 따로 보관했다가 나중에 사용한다. 이는 sed의 홀드 영역과 비슷하다고 할 수 있다. 대신에 vim은 단순히 하나의 저장 영역을 사용하는 것이 아니라 매우 다양하고 많은 레지스터를 사용한다.

레지스터 사용방법

레지스터는 각각의 이름이 있고, 각 이름은 모두 키 하나에 맵핑되어 있다. 레지스터는 기본적으로 편집 명령을 통해서 쓰거나 읽을 수 있다. 복사(y)는 물론 삭제(d, x) 및 교체 (r, s)시에도 제거되는 내용은 즉시 폐기된다기 보다는 특정한 레지스터에 복사할 수 있다. 특정 레지스터에 복사된 내용을 p 등으로 붙여넣는 경우에 레지스터를 사용할 수 있다.

노멀모드에서 레지스터를 명시하는 방법은 명령 앞에 "a와 같은 식으로 따옴표 기호를 입력한다. "aY는 레지스터 a 에 현재 라인을 복사한다는 의미이다. 그리고 "ap를 쓰면 레지스터 a의 내용을 현재 위치에 붙여넣는다는 뜻이다.

입력모드에서 입력 중 특정 레지스터의 내용을 삽입할 수 있다. 입력 모드에서 CTRL-R을 누르면 커서 위치에 "이 표시되는데, 이 때 레지스터의 이름에 해당하는 키를 누르면 그 레지스터의 내용이 삽입된다.

Ex 모드에서도 Ctrl-R을 눌러서 레지스터를 사용할 수 있다. 예를 들어 어떤 파일의 경로가 버퍼에 있고, 이 파일을 편집하려면 파일 경로를 복사한 후 :e 까지 타이핑하고 Ctrl-R0 을 누르면 (0은 가장 최근에 복사한 내용) 해당 파일 경로가 붙여진다.


vim 매뉴얼에서는 레지스터에 10가지 타입을 소개하고 있다. 많아 보이지만 알아두면 도움은 될 것 같다. 특히 이름 없는 레지스터와 0, 1, – 레지스터는 숙지해두면 좋다.

  • 이름없는 레지스터 : ""
  • 10개의 번호 레지스터 : "0
  • 삭제 레지스터 : "-
  • 26개의 이름이 있는 레지스터 az : 대소문자를 구분하지는 않음
  • 세 종류의 읽기 전용 레지스터 : ":, "., "%
  • 대체 버퍼 레지스터 : "#
  • 표현식 레지스터 : "=
  • 선택/드롭 레지스터 : "*, "+, "~
  • 최근 검색 패턴 레지스터 : "/

이름이 없는 레지스터

사실상 부지불식간에 가장 많이 사용하는 레지스터이며, ‘이름이 없는(unnamed)’이 사실 이름인 레지스터이다. 마지막으로 복사하거나 제거된 텍스트가 이 레지스터에 들어간다. 또한 특별한 레지스터 지정 없이 복사, 제거가 발생했을 때 자동으로 지정되기 때문에 ‘이름이 없는’으로 이름이 붙여졌다. 즉 dd, Y와 같이 아무런 레지스터 지정을 하지 않은채로 편집하였을 때 이 레지스터에 내용이 기록된다. 참고로 p, P 명령에서도 레지스터 지정을 하지 않으면 이 레지스터가 사용된다.

이름없는 레지스터는 다른 레지스터를 지정한 액션에 대해서도 동일하게 동작할 수 있다. "add는 한줄을 삭제하고 그 내용을 레지스터 a에 보관한다. 그 직후 p 명령을 쓴다면 방금 삭제한 내용이 붙여지는데, 이는 이름 없는 레지스터는 편집 동작에서 레지스터의 지정 여부에 상관없이 항상 방금 전 편집 내용을 보관한다는 의미이다. 이 동작에서는 단 한가지 예외가 있는데, "_dd 와 같이 _ 레지스터를 사용한 경우에는 이름 없는 레지스터에 삭제 내용이 남지 않는다.

이름 없는 레지스터에 직접 쓰는 것도 가능하다. 이 경우 0 레지스터에 내용이 기록된다.


숫자 레지스터 ( 0 ~ 9 )

0~9 까지의 10개의 숫자로 참조되는 레지스터이다. 먼저 1~9는 가장 최근에 제거/삭제된 텍스트가 순서대로 쌓이는 곳이라 생각하면 된다. 특정한 레지스터를 지정하지 않고 1줄 이상의 내용이 삭제되면 레지스터 1에 들어간다. 만약 레지스터 1에 기존 내용이 있었다면 그 내용은 2로 옮겨지는 식으로 최근에 삭제된 내용들이 숫자 레지스터에 쌓인다. 0 레지스터는 나머지 숫자와 달리 가장 최근에 복사된 내용이 보관된다. 이름 없는 레지스터와 달리 다른 레지스터에 직접 복사했다면 그 내용은 보관되지 않는다.

삭제 레지스터

작은 삭제 레지스터는 -로 참조하는데, 1줄보다 작은 내용이 삭제될 때 레지스터가 명시되지 않았다면 그 내용이 여기 보관된다. 만약 1줄보다 큰 내용이 삭제된 경우라면 1 레지스터에 저장될 것이다.

알파벳 레지스터

알파벳 a ~ z의 총 26개 레지스터로 일반적으로 사용자가 사용하는 영역이다. 읽을 때에는 대소문자를 구분하지 않지만, 기록할 때에는 대소문자를 구분한다. 소문자를 사용하면 기존 내용을 무시하고 교체하며, 대문자를 사용하면 기존 내용 뒤에 추가하는 방식으로 동작한다. (SED의 홀드 영역을 생각하면 되겠다.) ‘이름이 없는’ 레지스터에 대응하여 이름이 있는 레지스터가 바로 알파벳 레지스터이다.


그외 읽기 전용 레지스터

몇몇 레지스터는 읽기 전용으로 사용자가 쓰기를 할 수 없는 레지스터가 몇 개 있다.

". : 가장 마지막에 삽입된 문자열을 가지고 있다. 삽입모드에서 CTLR-ACTRL-@을 눌렀을 때 동작이 이 레지스터를 사용한다. 하지만 EX모드의 CTRL-R에서는 동작하지 않는다. (뭔가 내부적으로 차이가 있는 듯)

"% : 현재 편집중인 파일의 이름을 저장하고 있다.

": : 가장 최근에 실행된 명령줄을 기억하는 레지스터.

대체 파일 이름

"#은 현재 창의 대체 파일 이름을 저장하는 레지스터이다. vim에서 창은 버퍼를 표시하는 공간이며, 여러 개의 버퍼가 같은 창을 통해서 번갈아가며 표시될 수 있다. 대체 파일은 이 창에서 표시될 다른 버퍼이며 보통 직전에 현재창을 사용한 버퍼를 가리킨다. 대체 파일 레지스터는 변경이 가능하며, 따라서 Ctrl-^ 동작을 변경한다. (이 명령은 대체 버퍼를 편집하는 명령이다.) 버퍼이름(파일이름)이나 버퍼의 번호를 받을 수 있다. 보통은 플러그인에서 이를 변경하는 경우가 있고, 원상 복구를 위해서 다음과 같은 식으로 사용한다.

let altbuf = bufnr(@#)
..
let @# = altbuf

표현식 레지스터

"=로 쓰는데, 등호를 사용하는 것으로 봐선 뭔가 특별한 느낌이 든다. 이 레지스터는 문자열을 저장하는 레지스터는 아니다. 어떤 표현식의 평가 결과를 리턴하는 레지스터이다. 일반 모드에서 "=를 타이핑하거나 명령 모드에서 <c-r>=을 타이핑하면 명령창에 = 라는 새로운 입력창이 표시된다. 여기에 어떤 값이나 함수식을 쓰면 그 값을 평가한 후에 리턴한다.

선택과 드롭 레지스터

"+는 시스템 클립보드를 가리킨다. Windows환경에서는 "*도 동일한 역할을 한다. 시스템 클립보드에 대한 액세스는 +clipboard 기능이 활성화되어 있어야 한다. "~ 레지스터는 gVim으로 텍스트를 드롭했을 때 사용되는 저장소이다. 이 기능은 gtk용 gvim에서만 사용가능하다. 기본적으로는 "+로 클립보드로 복사/붙여넣기가 가능할 수 있다 정도만 이해하면 되겠다.

블랙홀 레지스터

앞서 잠깐 언급된 레지스터. 무엇이든 써 넣을 수 있지만, 항상 아무것도 리턴하지 않는다. 따라서 "_dd를 실행하면 제거된 라인이 레지스터에 남지 않는다.

검색어 레지스터

최근 검색한 텍스트가 들어있는 레지스터. n 명령에서 사용된다. 이 레지스터에 직접적으로 쓰거나 지우는 것은 허용되지 않지만 :let @/ = 명령을 통해서 액세스할 수 있다. 이렇게 변경하는 경우 n 명령의 동작에 영향을 주게 된다.


레지스터의 내용을 확인

:register [:reg] 명령을 사용하면 현재 각 레지스터에 들어있는 내용을 확인할 수 있다. 레지스터에 관한 도움말은 :h registers로 찾아볼 수 있다. (:h register는 후원 등록에 관한 내용이다.)