vim에 능숙해지는 법

vim은 익숙해지기 어려운 에디터로 정평이 나 있다. 단축키를 외우지 않고서는 글자 하나도 입력할 수 없기 때문이다.

내가 vim을 배운 방법

나는 2007년 9월부터 vim을 쓰기 시작해서, 2008년 봄 쯤 부터는 능숙하게 사용할 수 있게 되었다. 내가 vim을 익힌 방법은, 그냥 배운 것을 적는 것 뿐이다.

  1. 단축키나 기능을 익혔다면 적어둔다.
  2. vim을 쓰다가 모르는 기능이 있다면 우선 적어둔 것에서 찾아본다. 없다면 찾아보고 적는다.
  3. 완전히 외운 것은 지운다.

완전히 외워서 지우게 된 명령어의 갯수가 15개를 넘어서면 별 불편없이 vim을 사용할 수 있을 것이다(몇달 걸린다).

부연설명

  • 외운 것을 지우는 이유는, 다음번에 찾는 시간을 줄이기 위함이다. 적은 것이 10-20개라면 그 중에서 하나 찾는데 별로 시간이 들지 않지만 30-40개쯤 되면 찾기도 피곤해진다.
  • 지우는 것에 대해 너무 망설이지 말자. 혹시 외웠다고 생각했는데 까먹었다면 그냥 다시 구글링해서 적어넣으면 된다. 그래도 걱정이 된다면 언제라도 지운 것을 복원할 수 있도록 이 메모를 git 등으로 버전관리하는 방법을 추천한다.
  • 적을 필요 없이 매번 구글링하면 되지 않나 하는 생각이 들 수도 있는데, 구글링을 통해 찾은 글을 해석해서 적용 가능한 해결책을 찾아내는 것 보다는 직접 적은 것을 보는 것이 시간면에서 효율적이다. 또한 나는 익힌 것을 적는 행위와, 나중에 그것을 보면서 적었을 때의 상황을 연상하는 행위가 학습효과를 높일 것이라고 믿고 있다.

이 방법에 대해 더 자세하게 잘 설명한 글이 있어 링크한다: vi 배우기 — “컨닝 페이퍼” 기법

vim에 컴파일러/인터프리터의 에러메시지 연동시키기

대부분의 IDE에서는, 컴파일 에러나 런타임 에러가 발생했을 때, 소스코드에서 해당 에러의 원인이 된 라인으로 바로 이동하는 기능이 있다.

물론 vim에서도 약간의 설정으로 가능한 기능이다. 설정 및 사용법을 알아보자.

makeprg 설정

우선 현재의 소스코드를 해석하거나 컴파일할 때 사용할 프로그램을 설정한다. 여기서는 python으로 해 보겠다.

:set makeprg=python

이렇게 하고 나면, :make %로 현재 편집중인 파일을 파이썬으로 실행해 볼 수 있다.

errorformat 설정

다음은 vim이 파이썬의 에러메시지를 해석할 수 있도록 에러포맷을 정의해야 한다.

:set errorformat=%C %.%#,%A  File "%f"\, line %l%.%#,%Z%[%^ ]%\@=%m

이제 :make %로 편집중인 소스코드를 파이썬으로 실행했을 때 에러가 발생한다면, 자동으로 커서가 에러가 발생한 위치로 옮겨진다.

파이썬이 출력한 에러메시지에서 어떤 줄이 위의 식에 매칭된다면, vim은 그 줄이 소스코드에서 에러의 원인이 되는 위치를 알려주는 것으로 생각하고 해석하여 파일명, 라인번호 등의 정보를 얻어낸다. 위의 식이라면 %f에 대응하는 것이 파일명, %l에 대응하는 것이 라인번호다.

예를 들어 파이썬이 아래와 같은 메시지를 출력한다면,

Traceback (most recent call last):
File "test.py", line 13, in <module>
    x = MyClass()
TypeError: __init__() takes exactly 2 arguments (1 given)

vim은 두번째 줄을 인식해서 test.py와 줄번호 13을 얻어낼 것이다.

자세한 문법은 :help errorformat으로 확인해보자.

만약 errorformat과 대응하는 에러메시지가 1개 이상이라면, cncp로 각 에러를 오갈 수 있으며, clist로 에러메시지의 목록을 확인할 수 있다.

단축키 한번에 실행하기

매번 :make %을 입력하는 것이 번거롭다면, 다음과 같이 단축키 한번에 실행되도록 할 수도 있다. 다음은 f5 키로 실행하도록 하는 설정이다.

:map<f5> :make %<cr>

설정파일에 설정하기

물론 위에서 언급한 errorformat이나 makeprg의 설정 등은 모두 언어별로 다를 수 밖에 없다. 따라서 vim의 syntax 설정 디렉토리에 넣어두는 것이 좋을 것이다. 파이썬이라면 ~/.vim/syntax/python.vim 파일에 다음의 설정을 추가하면 된다.

set errorformat=%C %.%#,%A  File "%f"\, line %l%.%#,%Z%[%^ ]%\@=%m
set makeprg=python
map<f5> :make %<cr>

vim과 쉘을 연동하여 사용하기

vim은 그 자체로도 상당히 강력하지만, 쉘과 함께 사용함으로써 서로의 강력함을 곱할 수 있다. vim과 쉘을 연동해서 쓰는 방법들을 몇가지 소개한다.

여기서 소개하는 방법들은 gvim이 아닌 터미널에서 실행하는 vim을 위한 것이다.

쉘로 나갔다가 돌아오기

vim 사용중에 Ctrl+z로 쉘로 나가서 명령을 실행한 뒤, 쉘에서 fg를 입력해 vim으로 돌아온다. 이건 vim과는 아무 상관도 없는 기능이지만, 사실 vim에서 쉘 명령을 써야 할 때 가장 많이 쓰는 방법이다. (쉬우니까)

screen 혹은 tmux

vim은 자신 안에서 쉘을 띄우는 기능이 없다. 플러그인이 있긴 한데 그다지 쓸만하지 않다. 필요하다면 그냥 screen이나 tmux를 써서 창을 쪼개 한쪽 창에 vim을 띄우는 것이 훨씬 낫다.

옛날엔 screen에서 세로 쪼개기를 지원하지 않아 영 쓰기기 좋지 않았지만, 버전 4.01이후부터는 잘 지원한다.

screen에서는 C-a S로 창을 쪼개고, C-a <Tab>으로 창을 오가며, C-a c로 쪼개진 창에 쉘을 띄운다.

tmux에서는 C-b "로 창을 쪼개고, C-b o로 창을 오간다. 창이 쪼개지는 순간 바로 해당 창에 쉘이 실행되므로 별도로 쉘을 실행해 줄 필요는 없다.

쉘 명령 실행

쉘 명령은 :!로 실행할 수 있다. 예를 들어, ls를 실행해본다면,

:!ls

:r!로 표준출력을 바로 붙여넣을 수 있다. ls를 실행한 결과를 vim에 바로 붙여넣고 싶다면,

:r!ls

선택한 영역을 쉘명령의 표준입력으로 넣어 표준출력으로 출력된 결과가 그 영역을 대체하게 할 수도 있다. 선택한 영역에서 특정 단어가 포함된 줄만 남기려면,

:'<,'>!grep word

클립보드

엄밀히 말해 클립보드는 쉘과 아무련 관련이 없지만, 많은 사용자들이 GUI 환경에서 가상터미널을 띄워 쉘을 사용하고 있을 것이고, 그렇다면 클립보드를 통해 vim에 복사-붙여넣기를 해야하는 상황도 꽤 자주 발생할 것이다.

클립보드에 복사하려면 복사할 영역을 선택하고,

"+y

클립보드에 들어있는 문자열을 vim에 붙여넣기하려면,

"+gP

클립보드와 연동하여 복사/붙여넣기를 하려면, vim이 xterm_clipboard가 가능한 상태로 빌드되어 있어야 한다. vim --version을 했을 떄, +xterm_clipboard가 보인다면 가능한 상태인 것이다.

vim-slime

shell 연동의 종결자라 할 수 있는 굉장한 플러그인이다. 뭐가 가능한고 하니, screen이나 tmux로 창을 쪼개서 한쪽 창에는 vim을 띄우고 다른 창에는 repl을 띄운 다음에, vim에서 작성한 코드를 바로 다른 창의 repl에 보내서 실행시킬 수 있다.

단점은 잘 동작하지 않는다는 것이다.

vim-slime은 screen과 tmux를 지원하는데, 여기서는 screen과 함께 사용하는 법을 소개하겠다.

우선 .vimrc 설정에 몇가지 추가해야 하는 것이 있다.

$ echo 'let g:slime_target = "screen" >> ~/.vimrc

screen은 표준입력을 받아들이지 못하므로, 대신 파일을 이용해 통신해야 한다. 이 때 사용할 파일도 설정해준다.

$ echo 'let g:slime_paste_screen = "~/$HOME/.slime_paste"' >> ~/.vimrc

screen을 실행한 뒤 창을 하나 쪼개고 세션의 이름을 적당히 붙여준다. 여기서는 ‘shell’이라고 이름붙였다.

$ screen -S shell

그리고 다른 창에 가서 vim을 열고 간단히 코드를 작성한 뒤,

Ctrl+c Ctrl+c

이렇게 하면 현재 줄이 옆 창의 쉘에 입력된다. 다만 처음에는 세션 이름과 윈도 이름을 물어본다. 세션 이름은 위에서 정했고, 윈도 이름은 아마 0일 것이다.

한번 입력하고 나면 다시 묻지 않는다. 잘못 입력했다면 다음의 명령으로 다시 입력할 수 있다.

Ctrl+c Ctrl+v

vim을 위키처럼 쓰기

저번 포스팅에서 이야기했었지만, 나는 컴퓨터로 메모를 할 때 vim으로 편집하여 한 디렉토리에 페이지 하나를 파일 하나로 저장하며 버전관리는 git 으로 한다. 원래는 위키엔진을 설치하여 웹브라우저로 보고 편집했지만, 3년전부터 이 방식으로 바꿨다. vim으로 충분히 웹브라우저를 대체할 수 있음을 알았기 때문이다.

위키엔진과 웹브라우저의 조합이 제공해주는 기능을 vim으로 대체하기 위해 다음의 단축키 및 기능들을 사용한다.

링크 따라가기

링크된 페이지(파일)를 열어야 할 때는 링크에 커서를 놓고 다음 명령을 입력한다. 커서 위의 단어로 파일을 여는 명령이다.

g f

새 윈도를 열어 링크된 페이지(파일)를 열어보고 싶다면,

Ctrl+w f

링크된 페이지를 본 뒤 다시 원래 페이지로 돌아가려면,

Ctrl+o

자동완성

위키페이지 이름을 입력할 때 자동완성이 필요하다면,

Ctrl+x Ctrl+f

현재 디렉토리에 있는 파일 이름으로 자동완성된다.

커밋

Git 저장소로 쉽게 커밋하려면 VCSCommand 플러그인이나 fugitive를 사용한다.

VCSCommand 로 커밋하려면 다음과 같이 ex 명령(:을 입력하면 들어가지는 그것)을 실행한다.

:VCSCommit 커밋로그

fugitive에선 이렇게 하면 된다.

:Gcommit -m 커밋로그

fugitive가 더 기능이 좋은데 종종 불안정한 모습을 보인다. 문제가 있는 것 같다면 VCSCommand를 사용하자.

검색

vim에서 grep을 사용할 수 있다. 다음과 같이 ex 명령을 입력하면 된다.

:grep 키워드

날짜/시각 넣기

가끔 오늘 날짜와 시각을 넣어줘야 하는 경우가 있다. :r!으로 쉘명령을 실행해서 표준출력 을 바로 붙여넣기 할 수 있다. 따라서 리눅스라면 다음의 명령으로 현재 날짜와 시각을 바로 입력할 수 있다.

:r! date

표 정렬

그다지 자주 쓰이지는 않지만, 종종 표를 그려야 하는 경우가 있다. 사실 이것만큼은 vim만으로는 좀 보기가 힘들다. 조금이라도 더 나아보이도록 하기 위해 정렬이라도 해주자.

정렬을 위한 플러그인은 align, Tabular 등이 있는데, 나는 Tabular를 사용한다. 정렬할 내용을 블럭으로 선택하고 다음의 명령을 입력하면 |을 기준으로 정렬한다.

:Tab/|

합계 계산

이것도 역시 쓸 일은 매우 드문데, 아주 간혹 유용하다. 숫자들을 블록으로 선택하고 다음의 ex 명령을 입력하면 선택한 숫자들의 합계가 계산된다.

:VisSum

VisSum 플러그인이 설치되어 있어야한다.