Petro Verkhogliad @ Experiment Room 4

Entries in the Category “Vim”

Epydoc style docstrings with snippetsEmu

written by Petro, on Oct 5, 2009 12:08:00 PM.

snippetsEmu is a great Vim plugin that attempts to emulate some of the behaviour of snippets from Textmate. It has support for multiple languages. I primarily use the Python, Latex, Javascript and HTML snippets.

At the same time, when I write Python code I use Epydoc for documentation. By default snippetsEmu outputs the following docstring for a function definition:

1
2
3
4
def hello(varname):
    """
    varname -- <{}>
    """

This is pretty good, but what I want is something like this:

1
2
3
4
5
def hello(varname):
    """
    @param varname: <{}>
    @type varname: <{}>
    """

This can be done by changing a single line in the ~/.vim/plugin/after/ftplugin/python_snippets.vim file. There is a function there called PyGetDocstringFromArgs. The line we want to change is this:

1
let docvars = map(split(text), 'v:val." -- ".st.et')

We want to change it to:

1
let docvars = map(split(text), '"\@param ".v:val."\: ".st.et."\n".indent."@type ".v:val."\: ".st.et')
Now whenever I do def and type the function parameters they are generated in Epydoc style.

Working with Vim and IPython

written by Petro, on Oct 4, 2009 9:03:00 PM.

Note: the text below is not for the fainthearted. Setting up Vim to communicate with IPython is currently not very straightforward. The situation will improve soon.

When I write Python code I tend to use IPython quite a bit to test and experiment. Currently this means quite a bit of reloading and writing test code in the IPython shell. I’ve always been a little jealous of the Emacs folks for being able to communicate with the Python shell with ease. Vim has a different philosophy. We use the editor to edit stuff and the shell to run it. With that in mind, one can set up Vim to talk to IPython.

There are several steps for this:

  1. Ensure that Vim is compiled with +python
  2. Get the code that enables communication with IPython
  3. Write code to send code from Vim to the server
Note: this assumes that you have Python, IPython and Twisted installed.

1. Ensure that vim is compiled with +python

Open your favorite version of Vim and do
1
:version

In there look for “+python”. If it is not there, you need to somehow get a version that has “+python”. It is also important to check which version of Python your Vim was compiled against. For this, execute the following command in vim:

1
:python import sys; print sys.version
The output should be the same as your primary version of Python. For example, I am on OS X 10.5.8. By default it ships with Apple Python 2.5. I prefer to use Python 2.6 from MacPorts. Because of this I had to build a version of Macvim from source that pointed to my installation of Python 2.6. This deserves its own post.

2. Getting the code for communicating with IPython

Matt Foster has written a plugin for Textmate called ipythontm-bundle. This Textmate bundle uses the ipy_textmateserver.py to create a Twisted server to which stuff is sent for evaluation from Vim.

This file is can be downloaded from the textmate-server branch of IPython. For Vim we only need this file. Why only this file will be explained at the end of this post. Once the file is downloaded put it in your IPython/Extensions directory. For me this directory is:

1
/opt/local/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/site-packages/IPython/Extensions

3. The Vim side of life

At the moment, Vim has no idea that there will be a server running. Therefore, we have to write a plugin. The following (very very simple) code server as said plugin.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import vim
import socket

def runner(content):
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    try:
        # make sure to chage the directory here
        s.connect("/YOUR/HOME/DIR/.ipython/IPYS")
        s.send(content)
        s.close()
    except:
        print "Error: could not connect to iPython server."

# --- Functions for running code in iPython --------------------------------- #

def run_current_line():
    runner(vim.current.line)

def run_selection():
    runner("\n".join(vim.current.range))

def run_buffer():
    runner("\n".join(vim.current.buffer))

# --- Clean up function

def remove_sockets():
    import os
    import sys
    os.remove("/Users/petrov/.ipython/IPYS")

Essentially, the server will create a UNIX socket. By default the socket is:

1
$HOME/.ipython/IPYS

It is possible to rename the socket or use different ones for different Vim windows. For now, I wanted to get the basics going. The Python code above should go into

1
$HOME/.vim/plugin

4. Using the code

Now that the code is in place we can start using it. Start IPython and execute the following code:
1
2
3
4
5
6
import ipy_textmateserver
# create the server
s = ipy_textmateserver.TextMateServer()
# start the server
s.start()
# to stop the server do: s.stop()
Now the server is running in that instance of the shell. Open a Python file in Vim. Create a map for executing the current line in Vim:
1
:map ,el :python run_current_line()<cr>

Put the cursor on the line of code you want to eval and do: ,el. This should send the line to IPython and you should see the results of execution in the shell.
The other two functions in on the plugin side can also be mapped to whatever you want.

Question and Answer

This is very complicated!
Yes, this is not the easiest thing in the world. But it let’s me work the way I want to work. In the future this will be packaged better as a proper Vim plugin.

Why not use the client that comes with the ipythontm-bundle.
I did try to use that code. However, it seems that Vim and Textmate do things differently. The Vim client that comes with ipythontm-bundle uses a Twisted reactor to send code to the server. This is great. However, once the reactor is stopped it can’t be restarted. Any attempts to do so result in a blocked thread. When this happens from inside Vim, it kills the whole session. This sucks. My guess is that Textmate reloads the whole client file. Vim doesn’t seem to do this. Therefore, I opted to use simple Python sockets.

Why not use ipy_vimserver.py?
I tried this as well. However, it uses socket code that doesn’t work on my machine. If you’re on Linux you should be able to use ipy_vimserver.py without any problems.

Nice colorscheme for Vim

written by Petro, on May 4, 2009 1:50:00 PM.

By accident I came across a really nice colorscheme for Vim called Mustang. The link takes you to a page with a screenshot, alternatively you can download here.

vim

written by Petro, on Mar 17, 2009 9:31:00 PM.

Here is my .vimrc file

You can download the file here

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
set nocompatible

set autoindent
set smartindent

" set the tab width to 4 chars
set tabstop=4

" set the number of space characters used for identation
set shiftwidth=4

" set the backspace to something sane
set backspace=2
set whichwrap+=<,>,h,l
" convert the tabs to spaces
set expandtab

" visually show matching parens 
set showmatch

" visually highlight search results
set hlsearch

" use incremental search
set incsearch

" turn on syntax highlighting
syntax on

" set the background type to dark
set background=dark


" tell vim to figure out the file type
filetype plugin on

" indent based on the file type
filetype indent on

" dont wrap the lines
set nowrap

" turn on the folding
"set foldmethod=indent
"

" set up the nice command matching
set wildmenu
set wildmode=longest,list

" turn off the toolbar and menubar
if has('gui')
    set showtabline=1
    set guioptions-=m
    set guioptions-=T
    set guioptions-=l
    set guioptions-=L
    set guioptions-=r
    set guioptions-=R
    set guioptions+=e
	set background=light
    " set the font for gui vim
"    set gfn=Envy\ Code\ R\ 11
    set gfn=Monaco:h12
end

" set the directory for .swp files so that they 
" dont appear in the current directory of the file being
" edited
set dir=/Users/petrov/.tmp

" show the line numbers by default
set number

set ruler

" set to auto read when a file is changed from the outside
set autoread

" no sound on errors.
set noerrorbells
set novisualbell
set t_vb=

" Set mapleader
let mapleader = ","
let g:mapleader = ","

" set the map for make
map ,m :make<CR>

" remap the escape, it is tiny on the macbook keyboard and i miss the ctrl-[ key
imap ,e <ESC>

" Nice statusbar
set laststatus=2
set statusline=
set statusline+=%2*%-3.3n%0*\                " buffer number
set statusline+=%f\                          " file name
set statusline+=%h%1*%m%r%w%0*               " flags
set statusline+=\[%{strlen(&ft)?&ft:'none'}, " filetype
set statusline+=%{&encoding},                " encoding
set statusline+=%{&fileformat}]              " file format
"if filereadable(expand("$VIM/vimfiles/plugin/vimbuddy.vim"))
"    set statusline+=\ %{VimBuddy()}          " vim buddy
"endif
set statusline+=%=                           " right align
set statusline+=%2*0x%-8B\                   " current char
set statusline+=%-14.(%l,%c%V%)\ %<%P        " offset

" If possible, try to use a narrow number column.
if v:version >= 700
    try
        setlocal numberwidth=3
    catch
    endtry
endif

" Enable fancy % matching
if has("eval")
    runtime! macros/matchit.vim
endif

" quickfix things
nmap <leader>co :copen<cr>
nmap <leader>cq :cclose<cr>
nmap <leader>cn :cnext<cr>
nmap <leader>cl :clast<cr>
nmap <leader>cp :cprevious<cr>

" Use o in insert mode
imap <C-O> <end><cr>

"Tab configuration
map <leader>tn :tabnew<cr>
map <leader>te :tabedit
map <leader>tc :tabclose<cr>
map <leader>tm :tabmove

" Fast split movement
set wmh=0
map <c-j> <c-w>j
map <c-k> <c-w>k
nmap <c-h> <c-w>h
nmap <c-l> <c-w>l

"Fast saving
nmap <leader>q :q!<cr>
nmap <leader>w :w!<cr>
nmap <leader>f :find<cr>

" Vim config reloading without leaving the editor
map <leader>v :sp /Users/petrov/.vimrc<cr>
map <leader>V :source /Users/petrov/.vimrc<cr>

" Taglist 
let Tlist_Ctags_Cmd="/opt/local/bin/ctags"



" put the search result in the middle of the screen
nmap n nzz
nmap N Nzz
nmap * *zz
nmap # #zz
nmap g* g*zz
nmap g# g#zz

set listchars=tab:>-,trail:-

set grepprg='grep\ -nH\ $*'
let g:Tex_DefaultTargetFormat = 'pdf'
let g:Tex_CompileRule_dvi = 'latex --interaction=nonstopmode $*'
let g:Tex_CompileRule_ps = 'dvips -Pwww -o $*.ps $*.dvi'
let g:Tex_CompileRule_pspdf = 'ps2pdf $*.ps'
let g:Tex_CompileRule_dvipdf = 'dvipdfm $*.dvi'
let g:Tex_CompileRule_pdf = 'pdflatex $*'
"we dont do dvi :)
"let g:Tex_ViewRule_dvi = 'texniscope'
let g:Tex_ViewRule_ps = 'Preview'
let g:Tex_ViewRule_pdf = 'Skim'
let g:Tex_FormatDependency_ps  = 'dvi,ps'
let g:Tex_FormatDependency_pspdf = 'dvi,ps,pspdf'
let g:Tex_FormatDependency_dvipdf = 'dvi,dvipdf'
" if the line below is not set then it will not compile 
" bibtex for pdf. It will only do it for dvi.
" As stated above, we dont do dvi. : )
let g:Tex_MultipleCompileFormats = "pdf"
let g:Tex_IgnoredWarnings ='
       \"Underfull\n".
       \"Overfull\n".
       \"specifier changed to\n".
       \"You have requested\n".
       \"Missing number, treated as zero.\n".
       \"There were undefined references\n".
       \"Citation %.%# undefined\n".
       \"\oval, \circle, or \line size unavailable\n"' 


" Run the current buffer through python
autocmd FileType python map <buffer> <leader><space> :w!<cr>:!python %<cr>

"Run in the Python interpreter
function! Python_Eval_VSplit() range
 let src = tempname()
 let dst = tempname()
 execute ": " . a:firstline . "," . a:lastline . "w " . src
 execute ":!python " . src . " > " . dst
 execute ":pedit! " . dst
endfunction

au FileType python vmap <F7> :call Python_Eval_VSplit()<cr>

" markdown stuff
augroup mkd
    autocmd BufRead *.mkd set ai formatoptions=tcroqn2 comments=n:>
augroup END
au FileType mkd map <buffer> <leader><space> :w!<cr>:!markdown %<cr>

" turn on autocompletion for python and others
autocmd FileType python set omnifunc=pythoncomplete#Complete
autocmd FileType javascript set omnifunc=javascriptcomplete#CompleteJS
autocmd FileType html set omnifunc=htmlcomplete#CompleteTags
autocmd FileType css set omnifunc=csscomplete#CompleteCSS
autocmd FileType xml set omnifunc=xmlcomplete#CompleteTags
autocmd FileType php set omnifunc=phpcomplete#CompletePHP
autocmd FileType c set omnifunc=ccomplete#Complete

" haskell mode configuration
au BufEnter *.hs compiler ghc
let g:haddock_browser = "/Applications/Firefox.app"
let g:haddock_docdir = "/opt/local/share/ghc-6.10.1/"

MacVim Theme

This is the default MacVim color scheme. I keep a local copy here.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
" MacVim colorscheme
"
" Maintainer:   Bjorn Winckler <bjorn.winckler@gmail.com>
" Last Change:  2008 May 9
"
" This is the default MacVim color scheme.  It supports both light and dark
" backgrounds (see :h 'background').
"


highlight clear

" Reset String -> Constant links etc if they were reset
if exists("syntax_on")
  syntax reset
endif

let colors_name = "macvim"


"
" First list all groups common to both 'light' and 'dark' background.
"

" `:he highlight-groups`
hi DiffAdd      guibg=MediumSeaGreen
hi Directory    guifg=#1600FF
hi ErrorMsg     guibg=Firebrick2 guifg=White
hi FoldColumn   guibg=Grey guifg=DarkBlue
hi Folded       guibg=#E6E6E6 guifg=DarkBlue
hi IncSearch    gui=reverse
hi ModeMsg      gui=NONE
hi MoreMsg      gui=NONE guifg=SeaGreen4
hi NonText      gui=NONE guifg=Blue
hi Pmenu        guibg=LightSteelBlue1
hi PmenuSbar    guibg=Grey
hi PmenuSel     guifg=White guibg=SkyBlue4
hi PmenuThumb   gui=reverse
hi Question     gui=NONE guifg=Chartreuse4
hi SignColumn   guibg=Grey guifg=DarkBlue
hi SpecialKey   guifg=Blue
hi SpellBad     guisp=Firebrick2 gui=undercurl
hi SpellCap     guisp=Blue gui=undercurl
hi SpellLocal   guisp=DarkCyan gui=undercurl
hi SpellRare    guisp=Magenta gui=undercurl
hi StatusLine   gui=NONE guifg=White guibg=DarkSlateGray
hi StatusLineNC gui=NONE guifg=SlateGray guibg=Gray90
hi TabLine      gui=underline guibg=LightGrey
hi TabLineFill  gui=reverse
hi TabLineSel   gui=NONE
hi Title        gui=NONE guifg=DeepSkyBlue3
hi VertSplit    gui=NONE guifg=DarkSlateGray guibg=Gray90
if has("gui_macvim")
  hi Visual       guibg=MacSelectedTextBackgroundColor
else
  hi Visual       guibg=#72F7FF
endif
hi WarningMsg   guifg=Firebrick2

" Syntax items (`:he group-name` -- more groups are available, these are just
" the top level syntax items for now).
hi Error        gui=NONE guifg=White guibg=Firebrick3
hi Identifier   gui=NONE guifg=Aquamarine4 guibg=NONE
hi Ignore       gui=NONE guifg=bg guibg=NONE
hi PreProc      gui=NONE guifg=DodgerBlue3 guibg=NONE
hi Special      gui=NONE guifg=BlueViolet guibg=NONE
hi String       gui=NONE guifg=SkyBlue4 guibg=NONE
hi Underlined   gui=underline guifg=SteelBlue1


"
" Groups that differ between 'light' and 'dark' background.
"

if &background == "dark"
  hi Boolean      gui=NONE guifg=DeepPink4 guibg=NONE
  hi Comment      gui=italic guifg=CadetBlue3
  hi Constant     gui=NONE guifg=Goldenrod1 guibg=NONE
  hi Cursor       guibg=LightGoldenrod guifg=bg
  hi CursorColumn guibg=Gray20
  hi CursorIM     guibg=LightSlateGrey guifg=bg
  hi CursorLine   guibg=Gray20
  hi DiffChange   guibg=MediumPurple4
  hi DiffDelete   gui=NONE guifg=White guibg=SlateBlue
  hi DiffText     gui=NONE guifg=White guibg=SteelBlue
  hi LineNr       guifg=#552A7B guibg=Grey5
  hi MatchParen   guifg=White guibg=Magenta
  hi Normal       guifg=Grey50 guibg=Grey10
  hi Search       guibg=Blue4 guifg=NONE
  hi Statement    gui=NONE guifg=Purple1 guibg=NONE
  hi Todo         gui=NONE guifg=Green4 guibg=DeepSkyBlue1
  hi Type         gui=NONE guifg=Cyan4 guibg=NONE
  hi WildMenu     guibg=SkyBlue guifg=White
  hi lCursor      guibg=LightSlateGrey guifg=bg
else
  hi Boolean      gui=NONE guifg=Red3 guibg=NONE
  hi Comment      gui=italic guifg=Blue2 guibg=NONE
  hi Constant     gui=NONE guifg=DarkOrange guibg=NONE
  hi Cursor       guibg=fg guifg=bg
  hi CursorColumn guibg=#F1F5FA
  hi CursorIM     guibg=fg guifg=bg
  hi CursorLine   guibg=#F1F5FA
  hi DiffChange   guibg=DeepSkyBlue
  hi DiffDelete   gui=NONE guifg=Black guibg=SlateBlue
  hi DiffText     gui=NONE guibg=Gold
  hi LineNr       guifg=#888888 guibg=#E6E6E6
  hi MatchParen   guifg=White guibg=MediumPurple1
  if has("gui_macvim")
    hi Normal       gui=NONE guifg=MacTextColor guibg=MacTextBackgroundColor
  else
    hi Normal       gui=NONE guifg=Black guibg=White
  endif
  hi Search       guibg=CadetBlue1 guifg=NONE
  hi Statement    gui=NONE guifg=Maroon guibg=NONE
  hi Todo         gui=NONE guifg=DarkGreen guibg=PaleGreen1
  hi Type         gui=NONE guifg=Green4 guibg=NONE
  hi WildMenu     guibg=SkyBlue guifg=Black
  hi lCursor      guibg=fg guifg=bg
endif


"
" Change the selection color on focus change (but only if the "macvim"
" colorscheme is active).
"
if has("gui_macvim") && !exists("s:augroups_defined")
  au FocusLost * if exists("colors_name") && colors_name == "macvim" | hi Visual guibg=MacSecondarySelectedControlColor | endif
  au FocusGained * if exists("colors_name") && colors_name == "macvim" | hi Visual guibg=MacSelectedTextBackgroundColor | endif

  let s:augroups_defined = 1
endif

" vim: sw=2