vim “:command” 명령

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

  1. 인자는 기본적으로 텍스트로 인식되며 표현식이 되지 않는다. 특히 s:var를 쓴 경우라면, 이는 실행되는 곳이 아니라 스크립트가 선언된 곳에서 이미 계산된 값이 사용된다. 아래의 간단한 예에서 script2.vim 파일에서 표시하는 메시지는 None!이 표시될 것이다.