Develop Vim Plugin in Python - KAT(3-2)
Introduce
Vim Script라고 불리는 Vim 전용 DSL인 VimL을 사용하여 플러그인을 개발할 수 있다. 그러나 제한적인 문법으로 인해 이 프로젝트에 적합하지 않은 언어로 판단하여 Python3를 이용하기로 하였다.
이 Post는
의 많은 부분 참고하였다. 추후 많은 분들이 따라할 수 있도록 원본 글의 내용을 최대한 유지한 채 본 글을 작성하였다. 단, python2 기준으로 작성된 부분은 모두 python3를 기준으로 변경하였다.
Vim Python Support
Vim이 Python으로 작성된 플러그인을 수행하기 위해선 설치된 Vim이 Python을 지원하는지 확인해야 한다.
$ vim --version
위 명령어를 수행했을 때, +python이 있을 시엔 Python2를 지원하고
+python3가 있을 시엔 Python3를 지원하는 것이다.
저의 경우엔 Python3로 개발할 것이고, 마침 vim도 Python3를 지원하므로 이 문서는 Python3 개발을 기준으로 작성할 것이다.
Usage
Plugin structure
플러그인 디렉터리 내부:
sampleplugin/
├ doc/
│ └ sampleplugin.doc
├ plugin/
│ └ sampleplugin.vim
├ LICENSE
└ README
Plugin Import
- sampleplugin.vim에 Plugin으로 사용할 내용을 작성.
~/.vim/bundle/에 위 프로젝트를ln -s혹은mv함.~/.vimrc에 다음과 같이 작성함.Plugin 'file:///home/{username}/.vim/bundle/sampleplugin'- vim 재실행.
Use Python3
.vim 파일에서 python 사용. sampleplugin.vim:
1
2
3
4
5
6
7
8
if !has('python3')
echo "Error: Required vim compiled with +python3"
finish
endif
python3 << EOF
print ("Hello from Vim's Python!")
EOF
python 파일을 import하여 사용. sampleplugin.vim:
1
2
3
4
5
6
7
8
9
10
11
let s:plugin_root_dir = fnamemodify(resolve(expand('<sfile>:p')), ':h')
python3 << EOF
import sys
from os.path import normpath, join
import vim
plugin_root_dir = vim.eval('s:plugin_root_dir')
python_root_dir = normpath(join(plugin_root_dir, '..', 'python3'))
sys.path.insert(0, python_root_dir)
import sample
EOF
- 1: 플러그인 디렉터리 경로를 지역변수에 저장
- 7: python script에서 지역변수에 접근
- 8: python 코드가 있는 디렉터리 경로 구축
- 9: python 코드가 있는 디렉터리 경로를 sys.path에 추가
- 10: 우리가 작성할 파이썬 모듈을 import
~/.vim/bundle:
$ mkdir sampleplugin/python3
$ touch sampleplugin/python3/sample.py
~/.vim/bundle/sampleplugin/python3/sample.py:
print "Hello from Python source code!"
def print_test():
print ("Hello from Python Function \'print_test\'")
~/.vim/bundle/sampleplugin/plugin/sampleplugin.vim:
function! Sample()
python3 print("asd")
python3 sample.print_test()
endfunction
Plugin 함수 수행
: call Sample()

The Python Interface to Vim
This documentation is from [Here: Part of python of Vim Official Documentation][vim help].
= 이 문서는 [이곳][vim help]을 베이스로 작성되었습니다.
Commands
:[range]py[thon]3 {statement}
:[range]py[thon]3 << [endmarker]
{script}
{endmarker}
The {endmarker} below the {script} must NOT be preceded by any white space.
= {script}아래의 {endmarker}의 앞에는 절대로 공백이 와서는 안된다.
:[range]py3do {body}
{body} for each line in the [range], with the function arguments begin set to
the text of each line in turn.
The default for [range] is the whole file: "1,$"
= [range]의 각 라인을 돌면서 {body}의 내용으로 각 라인을 치환한다.
[range]의 기본 값은 파일 전체이다.
:[range]pyf[ile] {file}
Execute the Python script in {file}.
= {file} 안의 파이썬 스크립트를 실행한다.
Modules
Overview
:py print "Hello" # displays a message
:py vim.command(cmd) # execute an Ex command
:py w = vim.windows[n] # gets window "n"
:py cw = vim.current.window # gets the current window
:py b = vim.buffers[n] # gets buffer "n"
:py cb = vim.current.buffer # gets the current buffer
:py w.height = lines # sets the window height
:py w.cursor = (row, col) # sets the window cursor position
:py pos = w.cursor # gets a tuple (row, col)
:py name = b.name # gets the buffer file name
:py line = b[n] # gets a line from the buffer
:py lines = b[n:m] # gets a list of lines
:py num = len(b) # gets the number of lines
:py b[n] = str # sets a line in the buffer
:py b[n:m] = [str1, str2, str3] # sets a number of lines at once
:py del b[n] # deletes a line
:py del b[n:m] # deletes a number of lines
vim.command(str): Executes the vim (ex-mode) command str. Returns None.:py vim.command("set tw=72") :py vim.command("%s/aaa/bbb/g")vim.eval(str): Evaluates the expression str using the vim intenal expression. evaluator. Returns a string if it evaluates a string or number, list if list, dictionary if dictionary.:" value of the 'textwidth' option :py text_width = vim.eval("&tw") : :" contents of the 'a' register :py a_reg = vim.eval("@a") : :" Result is a string! Use string.atoi() to convert to a number. :py str = vim.eval("12+12") : :py tagList = vim.eval('taglist("eval_expr")')-
vim.bindeval(str): Like python-eval, but returns special objects described in python-bindeval-objects. These python objects let you modify (List or Dictionary) or call (Funcref) vim objects. -
vim.chdir(*args, **kwargs)/vim.fchdir(*args, **kwargs): Run os.chdir or os.fchdir. vim.buffers: list of buffers.:py b = vim.buffers[i] # Indexing (read-only) :py b in vim.buffers # Membership test :py n = len(vim.buffers) # Number of elements :py for b in vim.buffers: # Iterating over buffer listvim.windows: list of windows.:py w = vim.windows[i] # Indexing (read-only) :py w in vim.windows # Membership test :py n = len(vim.windows) # Number of elements :py for w in vim.windows: # Sequential accessvim.tabpages: list of tab pages.:py t = vim.tabpages[i] # Indexing (read-only) :py t in vim.tabpages # Membership test :py n = len(vim.tabpages) # Number of elements :py for t in vim.tabpages: # Sequential accessvim.current: various “current” objects available in vim.- vim.current.line The current line (RW) String
- vim.current.buffer The current buffer (RW) Buffer
- vim.current.window The current window (RW) Window
- vim.current.tabpage The current tab page (RW) TabPage
- vim.current.range The current line range (RO) Range
- How to switch without triggering autocommands use
py << EOF saved_eventignore = vim.options['eventignore'] vim.options['eventignore'] = 'all' try: vim.current.buffer = vim.buffers[2] # Switch to buffer 2 finally: vim.options['eventignore'] = saved_eventignore EOF
vim.vars: Dictionary-like objects holding dictionaries with global (g:).vim.vars['name_except_prefix_g:']
vim.vvars: vim (v:) variables respectively.
댓글남기기