病みつきエンジニアブログ

機械学習、Python、Scala、JavaScript、などなど

vim-slimeで「for ... in ...」構文を便利に転送する

Vimにはvim-slimeという便利なプラグインがあり、Vim上で書いているコードを、tmuxやscreen経由で別ペインに転送することができる。

これの何が嬉しいかというと、「左はPythonソースコード」「右はPythonの実行結果」みたいな感じで、書きながら実行できる。↓

f:id:yamitzky:20151006175309p:plain

RStudioとか使ったことがある人は、便利さがイメージし易いはず。

f:id:yamitzky:20151006175521p:plain

Download and Install RStudio | RProgramming.net

for文の中だけ実行したいとき、iterableなオブジェクトの先頭を仮で入れたいケースがよくある
下記のようなコードを、

array = [1, 2, 3]
for i, x in enumerate(array):
    print(i, x)

下記のように実行したい。

i, x = enumerate(array).next()
print(x)

Vim力が足りないので、下記のような手順でとりあえず対応した。

~/.vim/after/ftplugin/python.vim を開いて、下記のような関数を追加

function! _EscapeText_python(text)
  if exists('g:slime_python_ipython') && len(split(a:text,"\n")) > 1
    return "%cpaste\n".a:text."--\n"
  else
    let no_empty_lines = substitute(a:text, '\n\s*\ze\n', "", "g")
    let stripped = substitute(substitute(a:text, '^\s*', '', ''), '\s*$', '', '')
    if stripped[:3] == 'for ' && stripped[-2:-2] == ':'
      return  substitute(stripped[4:-3], ' in ', ' = iter(', '') . ').next()
'
    else
      return substitute(no_empty_lines, "\n", "
", "g")
    end
  end
endfunction

これで、

for i, x in enumerate(array):

i, x = iter(enumerate(array)).next()  # i = 0; x = 1

で転送される、最高