tools/vim

learn vimscript the hard way 16: More Operator-Pending Mappings

seul chan 2020. 3. 15. 09:44

More Operator-Pending Mappings

Topic One
=========

This is some text about topic one.

It has multiple paragraphs.

Topic Two
=========

This is some text about topic two.  It has only one paragraph.
:onoremap ih :<c-u>execute "normal! ?^==\\+$\r:nohlsearch\rkvg_"<cr>

위 명령어는 ======== 헤더 아래의 모든 문단에 대한 mapping이다. onoremap ih 에 대해서는 저번 챕터에서 설명하였으니 나머지 명령어를 아래에서 설명할 예정

Normal

normal command는 이후에 친 모든 command를 normal mode에서 실행한 것처럼 실행시켜준다.

:normal gg
:normal >>

Execute

executeVimscript를 실행시켜주는 코맨드이다.

# same as :write<cr>
:execute "write"
# same as :normal gg
:execute "normal! gg"

다음 명령어를 실행해보자

:normal! gg/a<cr>

의도한 바는

  • 파일의 맨 위로 이동하여 (gg)
  • a 알파벳을 찾는다(/a<cr>)

하지만 실제 실행해보면 파일의 맨 위로 이동만 한다. (gg)

그 이유는 normal 명령어는 special character (<cr> 등)를 인식하지 못하기 때문이다.
special character를 인식하게 하는 많은 방법이 있지만 execute를 사용하는 것이 가장 쉬운 방법이다.

위에서 사용한 mapping을 예시로 들어서 설명해보자.

:normal! ?^==\+$<cr>:nohlsearch<cr>kvg_

vim은 execute가 없기 때문에 <cr>을 실제 엔터키로 인식하지 못하고 <, c, r, >를 순차적으로 누른 것과 같이 인식하게 된다.

execute는 special character를 스크립트 실행 전에 변경해주기 떄문에 <CR>을 의미하는 \r를 대신 사용해준다.

세부적인 명령어에 대한 설명. 각각의 명령어를 한 줄 씩 실행시켜보면 이해가 빠르다.

# == 한 개 이상을 가지고 있는 캐릭터를 역으로 검색(?)하여 마지막까지 선택
?^==\+$
# 검색 결과의 highlighting을 해지시켜준다. 굳이 필요 없는 명령어
:nohlsearch
# 한 칸 위로 올려서 (k) visutal mode로 (v) 해당 줄의 마지막 non blank character까지 선택 (g_)
# $ 대신 g_를 사용한 이유는 newline character 등을 제외해주기 때문
kvg_

위의 예시와 비슷한 operation pending mapping과 비슷하지만 아래 heading text (======)도 포함하는 명령어를 작성해보자

:onoremap ah :<c-u>execute "normal! ?^==\\+$\r:nohlsearch\rg_vk0"<cr>

Exercises

  • Markdown can also have headings delimited with lines of - characters. Adjust the regex in these mappings to work for either type of heading. You may want to check out :help pattern-overview. Remember that the regex is inside of a string, so backslashes will need to be escaped.
:onoremap ih :<c-u>execute "normal! ?^[==,--]\\+$\r:nohlsearch\rkvg_"<cr>
  • Add two autocommands to your ~/.vimrc file that will create these mappings. Make sure to only map them in the appropriate buffers, and make sure to group them so they don't get duplicated each time you source the file.
:autocmd FileType markdown :onoremap ih :<c-u>execute "normal! ?^[==,--]\\+$\r:nohlsearch\rkvg_"<cr>

만약 vimwiki를 사용중이라면 *.md 파일의 filetype이 markdown 대신 vimwiki로 설정되어 있다
filetype 확인 및 변경은 이 포스트 참고
또한 위 예시에서 사용한 ih, ah 등의 명령어는 vimwiki에서 미리 설정되어 있는 명령어이기 떄문에 vimwiki filetype에서는 제대로 작동하지 않을 수 있다. :onoremap ih로 현재 설정된 매핑을 확인할 수 있따.

  • Read :help normal.

  • Read :help execute.

  • Read :help expr-quote to see the escape sequences you can use in strings.

  • Create a "inside next email address" operator-pending mapping so you can say "change inside next email address". in@ is a good candidate for the keys to map. You'll probably want to use /...some regex... for this.

:onoremap in@ :<c-u>execute "normal! /^[a-zA-Z0-9]\\+@[a-z]\\+.[a-z]\\+.\r:nohlsearch\rjvnk"<cr>