콘텐츠로 건너뛰기
Home » Vim – 레지스터에 관해

Vim – 레지스터에 관해

Vim에서 문자열을 복사하는 동작을 지칭할 때 흔히 copy라는 단어 대신에 yank라는 단어를 사용한다. vim의 전신인 vi가 개발되던 때에는 OS의 사용환경이 터미널이었으며, 이 때에는 클립보드라는 개념이 없었기 때문에, 어떤 데이터를 임시로 복사했다가 다른 곳에 옮기는 것은 응용 프로그램이 사용하는 메모리의 특정 영역을 사용했고, 이 당시에는 ‘copy’라는 단어는 복사본을 만드는 것이지 지금처럼 클립보드에 데이터를 넣어두는 개념이 아니었기 때문이다.

Vim은 내부에서 임시로 복사해두는 메모리 영역을 하나가 아니라 여러 개를 사용하며, 이는 CPU의 기억장치와 같이 “레지스터”라는 이름으로 부른다. 이 레지스터들은 알파벳이름과 숫자 그리고 몇 가지 기호로 이름이 붙은 여러 개가 존재하는데, 보통 알파벳 이름의 레지스터는 사용자가 임의로 사용할 수 있으며, 숫자와 기호로 이름이 붙은 레지스터들은 특정한 동작이 발생할 때 변경된 데이터가 자동으로 임시로 보관되는 영역으로 사용된다.

레지스터 사용방법

vim에서 복사 붙여 넣기는 각각 y 명령과 p 명령으로 사용한다. 앞서도 말했듯이 이 때 사용되는 기억 공간은 시스템의 클립보드가 아니라 레지스터 영역이다. 복사나 붙여넣기 동작은 앞에 레지스터를 지정하는 명령을 동반할 수 있는데, 겹따옴표(") 다음에 레지스터의 이름을 붙인다. 예를 들어 레지스터 a 영역에 현재 행을 복사하고 싶다면 "aY 명령을 입력하면 된다. 반대로 레지스터 a 에 들어있는 내용을 커서 뒤에 붙여넣으려면 "ap 를 사용한다.

레지스터는 노멀모드외에 입력모드나 명령 모드에서도 사용될 수 있다. 입력모드에서 레지스터의 내용을 붙여넣는 명령은 <C-r>이다. 입력하던 중에 Ctrl + R 키를 누르면 겹따옴표가 입력된 것처럼 보이는데, 이 상태에서 레지스터의 이름에 해당하는 키를 입력하면, 해당 레지스터의 내용이 이 자리에 삽입된다. 명령모드에서도 마찬가지로 Ctrl + R 키를 눌러서 레지스터를 사용할 수 있다.


알파벳 문자 이름의 레지스터

알파벳 문자 이름의 레지스터는 a ~ z 까지의 26개를 사용할 수 있고, 이 공간은 모두 사용자가 사용하는 공간이다. 단 모두 복사/붙여넣기 용도로 사용하는 것은 아니다. 키 입력을 녹화하는 매크로도 실제로는 레지스터에 기록된다.

  • “iArray”를 입력한다.
  • 노멀모드로 빠져나와서 viw"xy를 눌러서 이 단어를 레지스터 x 에 복사한다.
  • 다른 위치로 이동한 다음 @x 를 누른다.

레지스터 x에는 “iArray”가 들어있는데, @x 명령은 실제로는 “레지스터 x에 기록된 키 시퀀스를 순서대로 입력하라”는 명령이기 때문에, 키 입력을 녹화한적이 없더라도 녹화했던 것처럼 매크로를 입력한 셈이 된다.

알파벳 레지스터의 이름은 대소문자를 구분하지 않아서 "ap"Ap 는 같은 동작이다. 단 레지스터로 yank하는 동작은 레지스터 이름이 대문자일 때와 소문자일 때가 다르다. "aY는 현재 라인의 내용을 레지스터 a에 덮어쓴다. "AY는 현재 라인의 내용을 레지스터 a의 뒤에 이어붙인다.

별도의 이름의 레지스터들

vim에서는 a ~ z 의 26개의 레지스터 외에 숫자 레지스터 및 기호 레지스터들이 있다. 이들은 vim이 작동하는 과정에서 자동으로 데이터가 기록된다. 예를 들어 "- 는 최근에 버퍼에서 삭제한 내용이 자동으로 기록된다. 이를 "-p 와 같은 식으로 읽어와서 사용하는 것이 가능하며, 일부 읽기 전용의 레지스터를 제외하면 이러한 레지스터에도 값을 쓰는 것이 가능하다. vim에서 관리하는 다른 레지스터들에 대해서 알아보자.

0 ~ 9 : 숫자 레지스터

숫자 레지스터 중 1~9는 순서대로 가장 최근에 편집 명령을 통해서 삭제됐거나 변경된(변경의 경우 변경 이전의) 텍스트가 복사되는 영역이다. 만약 삭제 명령이 레지스터를 지정하여 삭제 내용을 알파벳 레지스터에 보관하거나, 삭제된 내용이 너무 작은 경우 (한 줄 이내)에는 여기에 보관되지 않는다. 새로운 내용이 들어오게 되면 자동으로 각 숫자 레지스터의 값은 다음번 레지스터로 옮겨지고, 9개보다 많아지면 레지스터 9의 내용은 사라진다.

레지스터 0은 약간 다르게 작동하는데, 최근에 삭제했거나 복사한 내용이 여기에 기록된다. 그래서 주로 최근에 복사했던 값을 사용하고자 하는 경우에 주로 사용된다.

삭제 레지스터 ("-)

한 줄 이내의 작은 내용을 삭제한 경우, 삭제된 내용은 삭제 레지스터에 임시로 보관된다. 단, 삭제 명령이 별도의 레지스터를 지정했다면 삭제 레지스터에는 기록되지 않는다. 만약 최근에 어떤 단어나 라인들을 삭제했다면 "0"- 이나 "0"1에 삭제한 내용이 중복하여 기록된다.

읽기 전용 레지스터

":, ". , "% 의 세 레지스터는 읽기 전용의 레지스터로 각각 다음의 내용을 담고 있다. 이 값들은 붙여넣기 용도로 읽는 것은 가능하지만, 강제로 변경하는 것은 허용되지 않는다.

  • ". – 편집모드를 통해서 가장 최근에 입력한 내용이 들어간다.
  • "% – 현재 편집중인 버퍼의 파일 이름이 들어간다.
  • ": – 명령모드(EX)를 사용하여 가장 최근에 실행한 명령이 들어간다.

그 외 레지스터들

  • "# – Alternative file name 으로 현재 창에서 이전에 작업하던 버퍼의 파일 이름을 말한다.
  • "* "+ "~ – GUI를 통해서 선택한 텍스트를 저장하기 위한 레지스터인데, 시스템의 클립보드와 연계된다.
    "~ 는 드롭 레지스터라 부르른데, 다른 응용 프로그램에서 텍스트를 긁어서 드래그/드롭한 텍스트가 들어간다.
  • "/ – 마지막으로 검색한 단어가 들어간다.
  • "_ – 블랙홀 레지스터. 쓰기 전용이며, 여기에 쓴 내용은 어딘가에 보관되지 않고 없어진다.

수식 레지스터 "=

수식 레지스터는 실제로 텍스트를 저장해두는 레지스터가 아니며, 레지스터를 사용하는 명령에서 표현식을 사용하기 위해 사용하는 레지스터이다. 예를 들어 입력모드에서 Ctrl + R을 누른 뒤 = 키를 누르면 커서는 화면 아래쪽 명령 입력 영역으로 이동하는데, 여기서 특정한 표현식을 작성할 수 있고, 엔터키를 누르면 표현식의 결과가 계산된 후 버퍼에 삽입된다. 이 때 수식의 결과는 문자열로 표현이 가능해야 한다. 만약 숫자값이 산출되면 이는 자동으로 문자열로 변경된다. 결과가 리스트로 나온다면 각각의 요소가 한 라인이 되는 식으로 버퍼에 삽입된다.

스크립트에서 레지스터 사용하기

vimscript에서 @x 와 같이 레지스터 이름 앞에 “@”을 붙이면 해당 레지스터의 값을 참조할 수 있다. 레지스터가 쓰기가 허용되는 경우, 그 값을 변경하는 것도 가능하다. 플러그인 함수를 작성하면서 텍스트를 yank 하는 등 레지스터를 변경시키는 동작을 한다면, 해당 레지스터는 동작 전에 별도의 변수에 백업했다가 다시 복구시키는 동작을 해주는 것이 좋다.

레지스터 내용 확인하기

사실 이렇게 각 레지스터에 대한 내용을 알아둔다고 해도, 평소에는 복잡/다양하게 사용하기는 어렵다. 종류도 많고 외우기도 힘들기 때문이다. :reg[ister] 명령을 사용하면 현재 레지스터에 들어있는 내용들을 확인할 수 있다. 이 명령을 이용해서 이전에 편집했거나 삭제한 내용들 중에서 운좋게 되살릴 수 있는 기회를 얻을 수도 있을 것이다.

참고로 레지스터의 내용은 vim 세션으로 저장되기 때문에, vim을 종료한 후 다시 시작하더라도 제거되지 않고 계속 유지된다.

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는 후원 등록에 관한 내용이다.)