この記事は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}に指定された文字列は大まかに以下の順番で展開されます。
(実際にはもうちょっと複雑で、以下の通りではありません。が、処理は以下のようなことが処理されています。)
-
コメント除去
-
複数のステートメントに分解する(アンパサンド、パイプ、セミコロン)
-
特殊文字を展開する
- ブロック
- チルダ
- 実行コマンドパス
- 変数
- ワイルドカード
- チルダ
-
コメント除去
-
複数のステートメントに分解する(リダイレクト)
-
各ステートメントの実行
ただし、文字が以下に当てはまる場合には上記とは異なる扱いになります。
- シングルクォート内の文字
- ダブルクォート内の文字
- バッククォート内の文字
- エスケープされている文字
それぞれの説明
コメント除去
#
以降の文字列はすべてコメントととして扱われます。
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さんです。