Edited at

`vimproc#system({expr})`の{expr}の展開のされ方

More than 5 years have passed since last update.

この記事はVim Advent Calendar 2012 : ATND231日目の記事になります。

昨日の記事は@ujihisaさんのVim script初心者用入門記事でした。

なので、今回はVim scripterになると必ずお世話になるだろうvimproc.vim

具体的にはvimproc#system({expr})の{expr}の展開のされ方について説明します。


この記事で語ることは、基本的にvimproc#system()でのみで確認しています。

vimproc#system_bg()などでも同じ展開のされ方になると思いますが(たぶん)、

未確認なのでご了承ください。

以下のVim環境で確認しています。


  • Windows7 Pro SP1 64bit

  • VIM - Vi IMproved 7.3 MS-Windows 32-bit GUI version Included patches: 1-966

  • set shell=C:\Windows\System32\cmd.exe

  • set noshellslash

  • vimproc: c7bada0



{expr}の展開の流れ

vimproc#system({expr})の{expr}に指定された文字列は大まかに以下の順番で展開されます。

(実際にはもうちょっと複雑で、以下の通りではありません。が、処理は以下のようなことが処理されています。)


  1. コメント除去

  2. 複数のステートメントに分解する(アンパサンド、パイプ、セミコロン)



  3. 特殊文字を展開する


    1. ブロック

    2. チルダ

    3. 実行コマンドパス

    4. 変数

    5. ワイルドカード

    6. チルダ



  4. コメント除去


  5. 複数のステートメントに分解する(リダイレクト)


  6. 各ステートメントの実行


ただし、文字が以下に当てはまる場合には上記とは異なる扱いになります。


  • シングルクォート内の文字

  • ダブルクォート内の文字

  • バッククォート内の文字

  • エスケープされている文字


それぞれの説明


コメント除去

#以降の文字列はすべてコメントととして扱われます。

echo vimproc#system('echo hello # world!')

" hello
echo vimproc#system('echo hello $HOGE world!') " $HOGEが'#'のとき
" hello
echo vimproc#system('echo hello # world $HOGE hoge') " $HOGEが'#'のとき
" hello


複数のステートメントに分解する(アンパサンド、パイプ、セミコロン)

vimprocは&&||;によって複数のステートメントだと認識します。

もし変数に'&&'などが入っている場合、vimprocは1つのステートメントだと認識します。

(この場合の'&&'の処理は処理系に依存します)

また、vimprocは&|を単なる文字列として認識します(これも処理系に依存しますね)。

echo vimproc#system('echo hello && echo world')

" hello
" world
echo vimproc#system('echo hello || echo world')
" world
echo vimproc#system('echo hello ; echo world')
" hello
" world
echo vimproc#system('echo hello $HOGE echo world') " $HOGEが'&&'のとき
" hello
" world


特殊文字を展開する


ブロック

vimprocはブロックという値リストのようなものをサポートしています。

(:h vimshell-tips-blockを参照)

echo vimproc#system('echo /bin/{cd,ls}')

" /bin/cd /bin/ls
echo vimproc#system('echo {0..9}')
" 00 01 02 03 04 05 06 07 08 09
echo vimproc#system('echo {00..09}')
" 000 001 002 003 004 005 006 007 008 009
echo vimproc#system('echo {0..3}-{0..3}')
" 0..3}-{0..3
echo vimproc#system('echo /bin/$HOGE') " $HOGEが'{cd,ls}'のとき
" /bin/{cd,ls}


チルダ

~$HOMEの値に置換します。(チルダの前のスペースも必要!)

echo vimproc#system('echo ~')

" C:/Users/rbtnn
echo vimproc#system('echo a~')
" a~


実行コマンドパス

=に続くコマンド文字列をそのコマンドのパスに置換します。(イコールの前のスペースも必要!)

echo vimproc#system('echo  =cmd')

" C:/Windows/SysWOW64/cmd.exe
echo vimproc#system('echo =ls')
" C:/Git/bin/ls.exe
echo vimproc#system('echo =ls hello')
" C:/Git/bin/ls.exe hello

https://github.com/Shougo/vimproc.vim/pull/68 要参照


変数

環境変数を展開します。

echo vimproc#system('echo $HOME')

" C:/Users/rbtnn


ワイルドカード

vimprocは3種類のワイルドカード(*,?,[])をサポートしています。

(:h vimshell-tips-wildcardを参照)

echo vimproc#system('echo ~/ntuser.dat.????')

" C:/Users/rbtnn/ntuser.dat.LOG1 C:/Users/rbtnn/ntuser.dat.LOG2
echo vimproc#system('echo ~/.vim[a-z]c')
" C:/Users/rbtnn/.vimrc
echo vimproc#system('echo ~/.git*')
" C:/Users/rbtnn/.git C:/Users/rbtnn/.gitconfig C:/Users/rbtnn/.gitconfig.local C:/Users/rbtnn/.gitignore


複数のステートメントに分解する(リダイレクト)

vimprocは5種類のリダイレクト(<,1>,2>,>&,>>)をサポートしています。


シングルクォート

vimprocはシングルクォート内のシングルクォートを''で表すことができます。変数は展開されません。

echo vimproc#system("echo 'He''s a student.'")

" "He's a student."


ダブルクォート

vimprocはダブルクォート内で特定の文字をエスケープすることができ、以下のような辞書(escape_sequences)にて変換が行われます。変数は展開されます。

let escape_sequences = {

\ 'a' : "\<C-g>", 'b' : "\<BS>",
\ 't' : "\<Tab>", 'r' : "\<CR>",
\ 'n' : "\<LF>", 'e' : "\<Esc>",
\ '\' : '\', '?' : '?',
\ '"' : '"', "'" : "'",
\ '`' : '`', '$' : '$',
\}

echo vimproc#system('echo "hoge\nfoo"') " fooが出力されなかった。バグ?

" hoge
"
echo vimproc#system('echo "hoge\tfoo"')
" hoge foo
echo vimproc#system('echo "\$HOHE"')
" $HOHE
echo vimproc#system('echo "$HOME"')
" C:/Users/rbtnn


バッククォート

vimprocはバッククォート内にコマンドもしくはVim script式を入れて評価した結果を展開することができます。

(:h vimshell-tips-backquoteを参照)

echo vimproc#system('echo `git --version`')

" git version 1.8.1.msysgit.1
echo vimproc#system('echo `=3`') " Vim script式
" 3
echo vimproc#system('echo `=3*&columns`') " Vim script式
" 510


エスケープ

vimprocはクォート外では以下の4つの文字をエスケープ出来ます。

echo vimproc#system('echo \\')

" \
echo vimproc#system('echo \''')
" '
echo vimproc#system('echo \"')
" "\""
echo vimproc#system('echo \`')
" `


以上、「vimproc#system({expr})の{expr}の展開のされ方」でした。

vimproc.vim暗黒美夢王さんのプロダクトなのでvimshell.vimの挙動そのままですね。

明日の記事は@deris0126さんです。