tools/vim

Learn Vimscript The Hard Way - 29. Normal

seul chan 2020. 4. 6. 03:46

Normal

vimscript의 유용한 command 이외에도 매일 사용하는 vim 명령어들을 vimscript에서 사용할 수 없을까?

가능하다. 이번 장에서는 이전에 잠깐 다뤘던 normal을 더 자세하게 살펴볼 것이다.

:normal G

normal 모드에서 G를 누른 것과 마찬가지로 파일의 마지막 라인으로 이동한다.

:normal ggdd

가장 첫 번 째 라인으로 이동하여 (gg) 해당 줄을 제거한다. (dd)

Avoiding Mappings

Gdd를 매핑시킨 뒤에 다시 normal 명령어를 실행시켜보자.

:nnoremap G dd
:normal G

vim은 dd를 대신 실행시킬 것이다. normal 커멘드는 매핑이 있다면 그것을 실행시켜준다.

누군가 normal 모드에 매핑을 해 놓았으면 그것을 알 방법이 없기 때문에 문제가 생길 수 있다.

이를 해결하기 위한 방법이 normal!이다.

:normal! G

위 명령어는 기존대로 파일의 가장 마지막 부분으로 이동한다.

vimscript를 작성할 때에는 항상 normal!을 사용하고, 절대 normal을 사용하지 말 것을 권장한다.

Special Characters

normal!을 가지고 이리저리 테스트를 하다 보면 문제에 봉착하게 될 것이다. 다음 명령어를 실행시켜보자.

:normal! /foo<cr>

따로 에러가 발생하지는 않지만 작동하지는 않는다. 그 이유는 normal! 명령어가 <cr>과 같은 special character를 인식하지 못하기 때문이다. 이 경우 vim은 "f, o, o, left bracket (<), c, r, right bracket (>)"을 순차적으로 누른 것으로 작동한다.

이에 대한 내용은 다음 장에서 다룰 예정.

execute를 사용하면 된다. :execute "normal \/foo\<cr>"

Exercises

  • Read :help normal. The end of it will hint at the topic of the next chapter.
An alternative is to use |:execute|, which uses an
expression as argument.  This allows the use of
printable characters to represent special characters.

Extra Credit

If you're not feeling up for a challenge, skip this section. If you are, good luck!

Recall what :help normal said about undo. Try to make a mapping that will delete two lines but let you undo each deletion separately. nnoremap d dddd is a good place to start.

You won't actually need normal! for this (nnoremap will suffice), but it illustrates a good point: sometimes reading about one Vim command can spark an interest in something unrelated.

If you've never used the helpgrep command you'll probably need it now. Read :help helpgrep. Pay attention to the parts about how to navigate between the matches.

Don't worry about patterns yet, we're going to cover them soon. For now it's enough to know that you can use something like foo.*bar to find lines containing that regex in the documentation.

Unfortunately helpgrep can be frustrating at times because you need to know what words to search for before you can find them! I'll cut you some slack and tell you that in this case you're looking for a way to break Vim's undo sequence manually, so that the two deletes in your mapping can be undone separately.

In the future, be pragmatic. Sometimes Google is quicker and easier when you don't know exactly what you're after.

정리하면, 두 줄을 제거하는 매핑을 만들고 (dddd를 사용하여) undo 하였을 때에는 한 줄 씩 undo되게 하는 문제이다.

  • 사용한 help text
:help helpg
:helpg undo.*sequence
:helpg break.*undo
:help undo
:help i_CTRL-G_u
  • 내가 생각한 답

insert mode에서 undo를 나누고 싶을 때 <C-G>u를 사용하면 해당 시점에 undo가 나눠진다.

:nnoremap <leader>d ddi<C-G>u<esc>dd
:normal ,d

위 명령어를 실행하고 undo(u)를 하면 한 번에 한 줄씩 undo가 된다.