Hatena::Groupvim

Vim Script Idioms

Vim Script Idioms

Emacs Lisp: How to Write CommandsのVim Script版を作ろうぜ! 的なキーワード。

目次

  • Interactive Command Idioms
    • Grabbing Text
      • Grab by given starting and ending positions
      • Grabbing the current word or line
      • Grab Between Matching Pairs
    • Acting on Region
    • Prompting User for Input
  • Batch Style Text Processing Idioms
    • Open File, Process, Save, Close
    • Find Replace strings
    • Calling A Shell Command
    • Traverse a directory
    • Running Elisp in Batch mode

Interactive Command Idioms

" 簡単なコマンドは:commandで定義する。
command! MySimpleCommand  echo "do something..."
" ある程度複雑な処理なら関数に分離して、:commandはそれを呼び出す形にする。
command! MyComplexCommand  call MyFunction()
function! MyFunction()
  let a = 123
  let b = "456"
  " do something ...
endfunction
" キーへの割り当て例。
nnoremap \a  :<C-u>MySimpleCommand<Return>
nnoremap \b  :<C-u>MyComplexCommand<Return>
  " Command-line modeで直接使わないものなら、関数だけ定義してそれを呼ぶだけでもいい。
nnoremap \c  :<C-u>call MyFunction()<Return>

Grabbing Text

Grab by given starting and ending positions
  • 基本はgetline()のみ。
  • elispの(buffer-substring myStartPos myEndPos)的なものはない。選択されたテキストの取得のような方法では可能である。
  • Emacsと異なり、文字列にはプロパティ等の付加情報はない。
let the_123rd_line = getline(123)
let lines_from_10_to_20 = getline(10, 20)
Grabbing the current word or line
  • Vimのwordは'iskeyword'によって対象範囲が異なるので、elispの(thing-at-point 'symbol) ≒ Vim Scriptのexpand('<cword>')である。
  • elispの(bounds-of-thing-at-point)相当のものはない。強いて言えばtext-objectsが近いが、該当範囲を得る簡単な方法はない(書けなくはない)。
" grab the current word/WORD
let the_current_word = expand('<cword>')
let the_current_WORD = expand('<CWORD>')

" grab the current word with hyphens or underscore
" ==> expand('<cword>')

" grab the current line
let the_current_line = getline(line('.'))

" grab the start and end positions of a word (or any other thing)
" 強いて書けば以下のような感じになる。諸々の事情を考慮すると完璧ではないが。
normal! yiw
let [start_pos, end_pos] = [getpos("'<"), getpos("'>")]
Grab Between Matching Pairs
normal! ya(
let [start_pos, end_pos] = [getpos("'<"), getpos("'>")]
  • 強いて書けば上記のような感じになる。諸々の事情を考慮すると完璧ではないが。
  • ネストしたケースも考慮される。
  • a(の他にa[、a{、a<なども使える。

Acting on Region

Emacsでいうregionは、VimではVisual modeでの選択範囲か、あるmarkとカーソル位置で囲まれた領域になる。

" 123,456MyCommand などの行単位の指定を取り扱う場合。
command! -range MyCommand  call MyFunction('<line1>', '<line2>')

" Visual modeでの選択範囲を取り扱う場合。
" 厳密にはcharacterwise/linewise/blockwiseの区別があるのでこれでは不完全。
function! MyFunction()
  let start_pos = getpos("'<")
  let end_pos = getpos("'>")
  " do something
endfunction

Prompting User for Input

let x = input('What editor do you love?  Emacs or Vim? ', 'I love sudo gedit.')


Batch Style Text Processing Idioms

Open File, Process, Save, Close

Find Replace strings

Calling A Shell Command

Traverse a directory

Running Elisp in Batch mode