마개조 그거슨 개발자의 로망
…이 아니라, 불편한 것을 고쳐 씁시다.

IdeaVIM 의 문제점들

이 글에서 다루는 IDEA 의 VIM 플러그인인 IdeaVIM의 버전은 2015년 11월 2일에 나온 0.44 버전을 기준으로 합니다.
(2016년 6월이 되었는데도 아직 다음 버전이 나오지 않았습니다)

5월 11일부터 회사에서 라이선스를 받은 IntelliJ IDEA 를 사용하고 있습니다. 한 달 정도 지났군요.
물론 IDEA 만 사용하고 있는 건 아니고, VIM 플러그인이 워낙 불편해서 VIM 과 함께 사용하고 있습니다.

IdeaVim 은 매우 구립니다. 차라리 VIM 에 다양한 플러그인을 올려 쓰는 쪽이 낫겠다는 생각이 들 정도죠.
일단 생각나는대로 나열해보기만 해도 다음과 같은 문제들이 있습니다.

  1. :shell 명령어가 없습니다. IDE 에 내장된 터미널을 실행하려면 단축키를 사용해야 합니다.

  2. mark 가 제대로 작동하지 않습니다.
    m[a-z] 는 잘 작동하지만, m[A-Z] 에 문제가 있습니다.
    예를 들어, a 파일의 3 번 라인에서 mA 를 입력해 mark 한 다음, b 파일을 열고 'A 를 입력하면
    a 파일의 3 번 라인으로 이동하는 게 아니라 b 파일의 3 번 라인으로 이동합니다. 매우 짜증납니다.

  3. q 로 레코드해서 사용하는 @ 매크로가 엄청나게 느립니다.
    같은 파일을 VIM 에서 열어 작업하는 쪽이 훨씬 빠릅니다.

  4. / 검색시 incsearch 가 되지 않습니다. set incsearch 옵션이 없어요.
    :set incsearch 를 입력해도 unknown command 라는 경고 메시지만 출력됩니다.
    IdeaVIM GitHub 에 올라와 있는 set-commands.md에는 incsearch 가 명시되어 있는 걸 보면 다음 버전에는 incsearch 가 지원될 것 같습니다.

  5. set showcmd 가 없어서 NORMAL 모드에서 입력중인 커맨드를 볼 수 없습니다.

  6. :actionlist 로 IDEA 의 기능 리스트를 볼 수 있고 :action 명령으로 IDEA 의 기능들을 다양하게 사용할 수 있다는 장점이 있습니다만,
    이 장점을 묻어버리는 치명적인 단점이 있어요. 새로운 탭이나 창을 띄우는 종류의 액션의 경우 (예 : nnoremap \<F10\>r :action GotoFile\<CR\> ) 해당 창이 활성화되자마자 커서를 에디터로 다시 옮겨버리기 때문에 결국 마우스에 손이 가게 만듭니다.
    검색 창을 띄웠으면 검색 창에 검색할 문자열을 입력할 수 있도록 커서가 남아 있어야 검색을 할 텐데 말이에요.

  7. 두번째 키스트로크로 0 이외의 숫자를 받아들이는 커맨드가 f, F, t, T 뿐입니다.
    :action 으로 IDEA 의 bookmark[0-9] 를 지정하는 것이 가능하길래
    .ideavimrc 에서 nnoremap 으로 m[0-9], '[0-9] 를 지정해 보았으나 m0, '0 만 되고 나머지는 작동하지 않습니다.

  8. .ideavimrc 에서도, command line 에서도 :command 명령을 사용할 수 없기 때문에
    사용자 정의 command 를 만들 수 없습니다.

  9. function 을 정의할 수 없습니다.

  10. 이건 딱히 IdeaVIM 의 잘못은 아닌데, 옆집 Eclipse 의 VIM 플러그인인 vrapper 는 :vim 을 입력하면 현재 편집하고 있는 파일을 VIM 에서 열어줍니다. 지구방위대 후뢰시맨이 거대 로봇 후뢰시 타이탄을 소환하는 것과 같은 막강하고 훌륭한 기능입니다.
    vrapper 는 됩니다. IdeaVIM 은 안됩니다.
    이 기능 하나만으로도 vrapper 는 IdeaVIM 보다 백만배는 좋은 VIM 플러그인입니다.

  11. IdeaVIM 의 github 을 보면 Emulated Vim Plugins 기능이 지원된다고 나와 있는데 (surround.vim 을 사용할 수 있다고 합니다)
    0.44 버전은 지원하지 않습니다.

  12. VISUAL 모드에서 ~ 은 잘 되지만, gugU 가 안 됩니다.

현재 개발 버전에서 개선된 점들

0.44 버전이 릴리즈된 것은 2015년 11월 2일입니다. 그런데 master 브랜치의 최근 커밋을 보니 2016년 4월 30일입니다.
커밋 로그를 읽어보니 그동안 수정된 버그와 추가된 기능들이 꽤 있습니다.
다음 버전을 기다리기보다 빌드해서 써 보는 것도 괜찮겠다는 생각이 드는군요.

IdeaVIM 의 개발 환경 구성 방법을 참고하여 IdeaVIM 을 fork 하고 다운받아 빌드한 다음, IntelliJ IDEA 에 설치해 보았습니다.
슥슥 사용해 보니 몇 가지 개선점들이 눈에 들어옵니다. 일단 위에서 언급한 문제점들만을 살펴보도록 합니다.

  1. :shell 은 여전히 지원되지 않습니다.
  2. mark 문제는 그대로입니다.
  3. 매크로 실행이 좀 빨라졌습니다. 그럭저럭 아쉬운대로 괜찮은 속도가 나옵니다.
  4. set incsearch 가 먹힙니다. / 로 검색을 하면 한 글자 한 글자 입력할 때마다 검색 결과가 있는 곳으로 커서를 옮겨줍니다.
  5. set showcmd 문제는 여전합니다. 이건 없어도 그만이니 괜찮습니다.
  6. 이제서야 되는군요. 검색 창이 나온 이후 커서가 에디터로 복귀하지 않고 검색 창에 남아있습니다.
    이제 map 명령어로 매핑할 수 있게 되었습니다. 숨통이 좀 트이는 느낌입니다.
  7. 여전히 m0, '0 만 되고 나머지 숫자는 안 됩니다.
  8. :command 는 아직 안됩니다. 앞으로도 안 될 것 같습니다.
  9. function 을 정의하는 것도 여전히 안 됩니다. 앞으로도 안 될 것 같습니다.
  10. 옆집 vrapper 와 비교하는 일은 pass.
  11. set surround 로 surround 를 사용할 수 있습니다. 이건 좀 괜찮네요.
  12. gugU 는 여전히 안 됩니다.

incsearch 가 되는 것과 검색 창을 사용할 수 있게 된 것, 그리고 surround 를 쓸 수 있게 된 것이 눈에 띕니다.
easymotion 도 가능했으면 좋겠지만 아직까지는 surround 만 사용할 수 있습니다.
(extention 패키지를 열어보 surround 만 있습니다. 취미삼아 괜찮은 VIM 플러그인을 하나씩 포팅해 추가해보는 것도 재미있겠어요.)

최신 개발 버전을 설치하니 그나마 좀 나아지기는 했습니다.
그러나 .ideavimrc 를 편집하는 것만으로는 부족한 점이 많습니다.
그렇다면 커스터마이징을 해야죠. IdeaVIM 의 소스코드를 고쳐봅니다.

기능을 추가해 봅시다

파일이 너무 많아 막막한데, 일단 생각나는대로 hello 부터 찍어 봅시다.
그러려면 echo 부터 검색해 봐야 겠군요.
(참고로 :echo 'test' 를 입력해 보면 test 라는 문자열이 스테이터스 라인에 출력됩니다.)

EchoHandler.java 라는 파일이 검색되어 나오네요. execute 메소드의 소스 코드를 읽어 봅시다. EchoHandler.java

이제 새로운 커맨드 라인 명령어를 추가할 수 있을 것 같습니다.
다음과 같이 JohnGribTestHandler 라는 이름의 클래스를 새로 만들어 보았습니다.
‘test’ 를 입력하면 제 영어 이름을 부르며 인사하는 기능입니다.
JohnGribTestHandler.java

새로운 커맨드를 사용하려면 CommandParser.java 의 registerHandlers 메소드에도 등록을 해줘야 합니다.
(해당 메소드를 열어보면 다른 커맨드들이 new new new 되어 있는 것을 볼 수 있을 것입니다.)

빌드 후 다음과 같이 입력을 해 보면 :test

원하던 문구가 출력이 됩니다. Hello John Grib!

이제 다른 기능도 붙여 볼 수 있을 것 같네요. :tabonly 와 비슷한 기능을 하나 만들어 보는 것이 좋을 것 같습니다.
:only 또는 :onlytab 을 입력하면 현재 편집중인 에디터를 제외한 다른 에디터를 모두 종료해주는 기능을 붙여 보죠.1

처음에는 VimPlugin.getFile().closeAllButCurrent(); 를 써서 종료해보려 했는데 이게 이제는 안 쓰는 메소드더군요.
그래서 아래와 같이 작성하였습니다. JohnGribOnlyHandler.java

와아~ 테스트해보니 잘 되네요. 여러 파일 탭을 열어놓은 상태에서 :only 를 입력하니 편집중인 탭 하나만 남고 다 닫힙니다.

그러면 이번에는 불만사항 1 번이었던 :shell 명령어를 구현해 봅시다.
:actionlist term 으로 검색해보니 ActivateTerminalToolWindow 액션이 있네요. 이걸 쓰면 될 것 같습니다. ActivateTerminalToolWindow

:shell 뿐만 아니라 :sh 로도 실행되게 해 줍니다. JohnGribShellHandler.java

CommandParser 의 registerHandlers 에 등록해주는 것도 잊지 말고 해줍니다. CommandParser.java

빌드 후 :shell 을 입력해 보면, IDEA 의 터미널 윈도우가 빰 하고 나타납니다. shellWindow

이제 얼마든지 새로운 커맨드 라인 명령어를 만들어 붙일 수 있게 되었군요.
입맛에 맞게 고쳐 쓰면 될 것 같습니다.

마개조는 이제부터 시작입니다.

링크 모음

IdeaVIM

예제 코드

EOB

  1. 사실 :only 는 이미 구현되어 있는 기능입니다. 하지만 deprecated action 을 사용하기 때문에 작동하지 않습니다. 디버깅은 이 글의 목적이 아니니 일단 기능을 추가하는 내용으로 작성하였습니다. 해당 기능을 디버깅한 코드는 여기에서 읽어볼 수 있습니다.