Humanity

Edit the world by your favorite way

Re: vimでclispの式を評価(簡易版)

http://d.hatena.ne.jp/c3po_r2/20100817/1281997466

ちょっとだけコメントで言うつもりが
なんとなく言いたいこととかがいろいろあってこんな量になってしまった...

shellescape()

文字列をシェルへ渡す場合はshellescape()関数でエスケープしておくと安全です。
あとコマンドラインやインサートモードでは=*1
で式を評価して結果を挿入なんてことができるので、それを使ってこんな風にできる。

nnoremap <C-g>j v%y:!clisp -x -q <C-r>=shellescape(@@)<CR><CR>


追記:

そうだった...
:help filename-modifiers
に書いてある記法が:!でも使えるのでshellescape()だけじゃダメですね。
なので上のは完全とは言えません。
後述するsystem()を使った例が安全かと思います。

map, noremap

あとmapだとビジュアルモード(v)と演算子未解決モード(o)*2でもマッピングされちゃうので、
これもnmapとした方が誤爆する可能性がなくて安全です。

ただnmapでもまだ問題があって、右辺が再帰的に解釈されてしまう。

nmap foo bar
nmap bar baz

として「foo」を入力すると「baz」が実行される。

また

nmap j gj

この場合も右辺の「gj」を再帰的に解釈しようとするので
jを押した瞬間に「recursive mapping」とか表示される。


そこでnnoremapを使うと

nnoremap j gj

再帰的に展開せず、右辺を「デフォルトのマッピング」として解釈する。

system()

system()関数という標準出力を返す関数では
引数として実行するプログラムの標準入力を指定することができる。
具体的にはこんなことができる。

:echo system('perl', 'print "hello"')    " => hello
:echo system('clisp -q', '(+ 1 1)')    " => 2


これを使ってタイトルのはこんな風にもできる。

" 「@@」は「@"」と同じで「"レジスタ」の内容を表す
nnoremap <C-g>j v%y:echo system('clisp -q -i '.shellescape(expand('%')), @@)<CR>

quickrun

真打登場。
これを使えば特定の箇所やソース全体をささっと評価して結果を表示することができる。

let g:quickrun_config['lisp'] = {
\   'command': 'clisp',
\   'eval': 1,
\   'eval_template': '(print %s)',
\}

こんな設定をしとくといいかも。
quickrunは「標準出力を表示」するプラグインだけど、
id:c3po_r2の要求を満たすために式をprintで囲って表示させてみた。


実行は「:QuickRun」か、マッピングから実行する場合
デフォルトでは「r」に割り当てられている。
ビジュアルモードで選択してrするか、
ノーマルモードでrすればソース全体が実行される。

実行したら結果を表示したウインドウに移る

コマンドラインに表示するだけならエンター押せばコマンドラインの表示は消えるけど、
quickrunだとウインドウが開くのでめんどくさいかもしれない。
結果を表示したウインドウに移ればすぐ:quitして閉じられるのに...

「それintoでできるよ」

let g:quickrun_config['*'] = {
\   'into': 1,
\}
quickrunなどのウインドウを別ウインドウからさっと閉じれるマッピング

実は自分は上の設定は使ってない。
というか以下の設定があるので必要なかったりする。

ccでhelpとかquickrunのバッファとか大抵の「一時的なバッファ」を閉じれるようにしてる。
誤爆が怖いと思うかもしれないけど、案外そういうことは起こってない。


近々汎用化してプラグインにでもするかなーと思ってたりする。
それかquickeyに含めてもいいかもしれない。

*1::help c_CTRL-R_= と :help i_CTRL-R_=

*2:普通はoperator-pending-modeとか言っちゃうけど。日本語訳だとそう訳されてたので