write a new vim command
:command!
:command!
는 새로운 vim 명령을 만드는 명령이다. 명령어는 관례적으로 대문자로 시작하며 몇가지 속성과 함께 정의된다. !
가 끝에 붙는 경우에는 기존에 동일한 명령이 있는 경우에 이를 재정의하며, 그렇지 않은 경우 에러가 발생한다. 문법은 다음과 같다.
:com[mand][!] [{attr}...] {cmd} {rep}
{cmd}
는 실행할 명령이며, {rep}
은 대체문자열이다.1
명령 속성
사용자 정의 명령은 다른 Ex 명령과 동일하게 취급되어 인자를 받거나 범위를 지정하여 실행될 수 있다. 인자들은 파일이름 혹은 버퍼 등으로 자동완성되는 것이 가능한데, 이러한 특성은 명령이 정의될 때 주어진 속성들에 의해 결정된다.
명령의 속성은 종류가 많은데 크게는 4가지 카테고리로 구분된다. A.인자 핸들링, B.자동완성동작, C.범위핸들링, D.특별한 경우들이 이러한 분류에 해당한다. 아래에는 각 분류에 해당하는 속성들을 기술해보도록 하겠다.
인자 핸들링
기본적으로 사용자는 인자를 받지 않는 명령을 정의한다. (그리고, 인자가 주어진채로 사용되면 에러가 표시된다.) 하지만 특정한 명령이 인자를 받도록 설정하게 할 수 있는데 이는 -nargs
속성으로 결정한다. 예를 들어,
-nargs=0 : 기본, 인자를 받지 않는다.
-nargs=1 : 인자를 1개 받는다.
-nargs=* : 인자를 0, 1 ... 여러개 받을 수 있다.
-nargs=? : 인자를 0, 1개 받는다.
-nargs=+ : 인자를 1개 이상 받는다.
인자는 공백이나 탭을 기준으로 쪼개진 리스트로 받게1 된다. 다만 인자가 1개인 경웅에는 공백문자는 인자의 일부가 된다.
# script1.vim:
:let s:error = "None"
:command -nargs=1 Error echoerr <args>
# script2.vim:
:source script1.vim
:let s:error = "Wrong!"
:Error s:error
자동완성 결합
기본적으로 사용자 정의 명령은 자동완성과 결합하지 않는다. 하지만 아래와 같은 인자 1개 이상을 주는 경우에는 적용가능하다. 이는 인자의 일부를 통해서 특정한 기록의 자동완성을 접목하는데 사용된다.
-complete=augroup autocmd groups
-complete=buffer buffer names
-complete=behave :behave suboptions
-complete=color color schemes
-complete=command Ex command (and arguments)
-complete=compiler compilers
-complete=cscope |:cscope| suboptions
-complete=dir directory names
-complete=environment environment variable names
-complete=event autocommand events
-complete=expression Vim expression
-complete=file file and directory names
-complete=file_in_path file and directory names in |'path'|
-complete=filetype filetype names |'filetype'|
-complete=function function name
-complete=help help subjects
-complete=highlight highlight groups
-complete=history :history suboptions
-complete=locale locale names (as output of locale -a)
-complete=mapping mapping name
-complete=menu menus
-complete=option options
-complete=shellcmd Shell command
-complete=sign |:sign| suboptions
-complete=syntax syntax file names |'syntax'|
-complete=syntime |:syntime| suboptions
-complete=tag tags
-complete=tag_listfiles tags, file names are shown when CTRL-D is hit
-complete=user user names
-complete=var user variables
-complete=custom,{func} custom completion, defined via {func}
-complete=customlist,{func} custom completion, defined via {func}
범위 핸들링
기본적으로 사용자 정의 명령은 줄번호 범위를 받지 않지만, -range
속성을 정의하여 특정 범위, 몇 개의 값 혹은 줄 내의 위치 등을 받을 수 있다.
-range : 범위를 활성화함. 기본적으로 현재 줄
-range=% : 범위를 활성화하고 기본적으로 전체
-range=N : 줄 번호 위치에서 N 개
-count=N : 줄번호위치 혹은 주어진 범위에서 N 개
그외 특별한 경우들
-bang: 명령이 `!` 수정자를 받을 수 있음
-bar: "|"를 통해서 다른 명령을 받을 수 있게하며, 이 때 인자 내에는 "|"를 쓸 수 없다.
-register: 명령의 첫 인자는 레지스터이이름일 수 있다.
-buffer: 현재 버퍼 내에서만 유효한 명령이다.
대체 텍스트
대체 텍스트는 실명령에서 사용되는 값 중에서 인자로받은 라인, 레지스터, 인자값들로 대체되는 것들을 의미하며 꺾쇠괄호로 둘러싼다.
<line1> : 시작줄
<line2> : 끝줄
<count>
<bang> : `!`을 통해서 실행된 경우에는 `!`이되고 그렇지 않은 경우에 무시된다.
<reg>
<args>
<lt>
예제
현 위치부터 끝까지 삭제하는 명령의 예.
"Delete everything after here to the end
:com Ddel +,$d
"현재 버퍼의 이름을 변경
:com -nargs=1 -bang -compete=file Ren f <args>|w<bang>
"주어진 범위를 파일의 내용을 교체
:com -range -nargs=1 -complete=file
Replace <line1>-pu_|<line1>,<line2>d|r <args>|<line1>d
"주어진 범위의 줄 수를 카운트
:com! -range -nargs=0 Lines echo <line2> - <line1> + 1 "lines"
"사용자 함수 호출
:com -nargs=* MyCmd call MyFunc(<f-args>)
LSON -> JSON
LSON 파일을 JSON 파일로 변경하여 새로운 버퍼에 표시하는 명령을 만들어보자.
:command! -bar LSON new | read !lson -f #
new
명령과 read
명령을 연이어 써야 하기 때문에 -bar
옵션을 주었다. 명령의 내용은 새 버퍼를 열고 이전 파일(#
)을 lson -f
명령에 넘겨서 그 결과를 읽어와서 새 버퍼를 채우는 것이다.
단축키로 한 방에 만드려면 다음 블럭을 vimrc 파일에 추가해준다.
augroup oLSON
command! -bar -buffer LSON new | read !lson -f #
au!
autocmd FileType lson nnoremap <buffer> <F8> :LSON<cr>
augroup END
-
인자는 기본적으로 텍스트로 인식되며 표현식이 되지 않는다. 특히
s:var
를 쓴 경우라면, 이는 실행되는 곳이 아니라 스크립트가 선언된 곳에서 이미 계산된 값이 사용된다. 아래의 간단한 예에서script2.vim
파일에서 표시하는 메시지는None!
이 표시될 것이다. ↩