vim-quickrun でやりたいことメモ
複数の種類のコマンドの切り分けを自動的にやらせる
pukiwiki で作業ログを書いているときに, 一つのページに複数のコマンドの作業ログを書くことがある.
再実行させるときに, 毎回自分で切り替えながらコマンド実行しているけど, 範囲を選択して \r で実行できるようにしたい.
ヘッダ部用意して, いつでもシェルを起動するようにすればいいのかな?
ここからは python コード xxx xxx ここまでは python コード ほげほげ ほげほげ ここからは ruby コード yyy yyy ここまでは ruby コード
quickrun 用の window の開き方
自動的にかわっているようだけど自分にとってヘンな位置にいくことがある.
どう開くかは機能としてありそうだけど, 自分にとってうまい位置、をどうにか設定したい.
writefile() 時の改行コード
試しに fileformat を指定してから結果を確認してみた.
set fileformat=dos call writefile(a, "/tmp/dos") set fileformat=mac call writefile(a, "/tmp/mac") set fileformat=unix call writefile(a, "/tmp/unix") set fileformat=dos call writefile(a, "/tmp/dos2", "b") set fileformat=mac call writefile(a, "/tmp/mac2", "b") set fileformat=unix call writefile(a, "/tmp/unix2", "b")
これだとバイナリ版とそうでない版での違いはでる(最後の改行コード有無)が, 改行コードは同じもの.
windows でもいつも LF であるなら問題ないのだけど, windows vim 環境はないのであった.
writefile() 時に改行コードを設定するオプションはなさげ. いったいどうするんだろう.
/* Always open the file in binary mode, library functions have a mind of * their own about CR-LF conversion. */ ... if (!binary || li->li_next != NULL) if (putc('\n', fd) == EOF) { ret = -1; break; }https://code.google.com/p/vim/source/browse/src/eval.c
ふむむ..
2013/05/27 追記
:h writefile() ... Inserting CR characters needs to be done before passing {list} to writefile().
vital.vim の Data.List を使ってみた
typo があったので修正しました.
Haskell を触ったことがない人はたくさんいると思うので、
fixed document by syngan · Pull Request #55 · vim-jp/vital.vim · GitHub
list のヘルプ「Haskell 風に動作する」は修正したほうが良いと思います.
なんとなくヘルプを眺めていたら typo みつけて, そのながれで Data.List を見てみたけど,
vim 力が足りないからなのかなんなのかわからないけど,
そのうち pull req 送ろうと思うよメモ.
- そもそも英語力ないからちゃんとドキュメントかかないなら例でもあったほうがいいと思う.
- あと例の書き方も統一したほうが良いと思う.
- 2013/05/25 追記: pull req した.
pop()
pop({list}) *Vital.Data.List.pop()* Removes the last element from a list and returns the element.https://github.com/vim-jp/vital.vim/blob/5547268490ae58b3f2b7daf2d37c81b590f6f682/doc/vital-data-list.txt
:let VITAL = vital#of('vital') :let List = VITAL.import('Data.List') :let p = [1, 2, 3] :echo List.pop(p) 3 :echo p [1, 2]
- 引数がリストであることの説明がない.
push()
push({list}, {val}) *Vital.Data.List.push()* Appends {val} to {list} and returns the list itself.https://github.com/vim-jp/vital.vim/blob/5547268490ae58b3f2b7daf2d37c81b590f6f682/doc/vital-data-list.txt
:let VITAL = vital#of('vital') :let List = VITAL.import('Data.List') :let p = [1, 2, 3] :echo List.push(p, [5]) [1, 2, 3, [5]] :echo p [1, 2, 3, [5]]
- 引数がリストであることの説明がない.
- 一番後ろに追加することの説明がない
shift()
shift({list}) *Vital.Data.List.shift()*
https://github.com/vim-jp/vital.vim/blob/5547268490ae58b3f2b7daf2d37c81b590f6f682/doc/vital-data-list.txt
Removes the first element from a list and returns the element.
:let VITAL = vital#of('vital') :let List = VITAL.import('Data.List') :let p = [1, 2, 3] :echo List.shift(p) 1 :echo p [2, 3]
- 引数がリストであることの説明がない.
unshift()
unshift({list}, {val}) *Vital.Data.List.unshift()* Inserts {val} to the head of {list} and returns the list itself.https://github.com/vim-jp/vital.vim/blob/5547268490ae58b3f2b7daf2d37c81b590f6f682/doc/vital-data-list.txt
echodoc を使ってみて その2
echodoc を使ってみた - vim 初心者の作業メモ難点として、まだドキュメントがありません。
http://vim-users.jp/2010/12/hack189/
- 関数の I/F については, ドキュメント書いて pull req 送って取り込んでもらった. 英語がう○こだけど.
- 日本語マニュアルは取り込まれないと *思う* ので, ここで.
- 他の Shougo Ware のように更新が進むことはないと思われるので当分使えると思います.
- 最新版との差異があっても自己責任でお願いします.
- ドキュメント内の "思います" は syngan の感想文.
概要
echodoc はエコーエリアに情報を表示するプラグインです.
一定時間キー操作を行わなかった場合(autocmd CursorHold, CursorHoldI)にカーソル上にある文字列に対応する情報を表示します.
echodoc は以下の特徴を持ちます. 少なくともこれらの機能は ftplugin では実現できません.
インストール
NeoBundle (https://github.com/Shougo/neobundle.vim) を利用する場合には
.vimrc に以下のように記述してください.
NeoBundle 'Shougo/echodoc', '', 'default' call neobundle#config('echodoc', { \ 'lazy' : 1, \ 'autoload' : { \ 'insert' : 1, \ }})
注意: 本設定では挿入モードが開始したときに echodoc がロードされます.
insert (Number) If set to non-zero, neobundle will |:NeoBundleSource| on |InsertEnter| autocmd.https://github.com/Shougo/neobundle.vim/blob/436e4d4c5fff7023e95d93886724adfb690f3425/doc/neobundle.txt#L700
インターフェース:コマンド
:EchoDocEnable
echodoc を有効にします.
:EchoDocDisable
echodoc を無効にします.
インターフェース:変数
g:echodoc_enable_at_startup
本変数の値が 0 以外の場合には echodoc は起動時に自動的に有効になります.
デフォルト値は 0 (無効) です.
インターフェース:関数
echodoc#enable()
echodoc を有効にします. :EchoDocEnable の関数版です.
echodoc#disable()
echodoc を無効にします. :EchoDocDisable の関数版です.
echodoc#is_enabled()
echodoc が有効な場合に
echodoc#register({name}, {dict})
ドキュメント {dict} を {name} という名前で登録します.
もし同じ {name} のドキュメントが追加済みの場合には上書きされます.
{dict} は辞書型で以下を要素に持ちます:
- "name" 文字列型 (必須)
- このドキュメントの名前です. ユーザが任意に設定することができます.
- 引数の {name} と同じ値であることが要求されます.
- "rank" 数値型 (必須)
- このドキュメントの検索優先度です. この値が小さいほど優先度が高くなります.
- (注意: 1 を設定しておけば良いと思います.)
- "filetypes" 辞書型 (必須)
- このドキュメントを検索対象とする filetype を指定します. キー名が対象とするファイルタイプで
キー値は任意の値を設定します.
-
- (注意: 1 を設定しておけば良いと思います. プラグイン内では使用されていません)
- "search" 関数型 (必須)
- 検索に使用する関数を指定します. この関数はカーソル位置より前にある文字列(?) が cur_text を引数として渡されます.
- 復帰値は辞書型のリストです.
- 辞書は以下の要素を持ちます.
- "text" : 出力する文字列 (必須)
- "highlight" : 出力する文字列に対するハイライト (任意)
echodoc#unregister({name})
名前が {name} であるドキュメントの登録を解除します.
- (注意: echodoc#register の引数 {name} が対象ではないことに注意.)
echodoc#get({name})
名前が {name} である {dics} を返します. 登録されているか確認するのに利用できます.
例
対応している Shougo Ware
neocomplecache や neosnippet, vimshell を利用すると自動的に検索用のドキュメントが追加されます.
[ " neocomplcache {'rank': 5, 'name': 'include_complete', 'search': function('120'), 'filetypes': {}}, " neocomplcache {'rank': 10, 'name': 'vim_complete', 'search': function('144'), 'filetypes': {'vim': 1}}, " neosnippet {'rank': 100, 'name': 'neosnippet', 'search': function('102'), 'filetypes': {}}, {...} ]
register()
let s:sample_dict = { \ 'name' : 'sample', \ 'rank' : 1, \ 'filetypes' : {'text' : 1, 'vim' : 1}, \} function! s:sample_dict.search(cur_text) let completion_length = 4 let words = [] let i = 0 while i >= 0 let word = matchstr(a:cur_text, "[0-9a-zA-Z]\\+", i) call add(words, word) let i = matchend(a:cur_text, "[0-9a-zA-Z]\\+", i) endwhile if len(words) == 0 return [] endif for word in reverse(words) if len(word) >= completion_length break endif endfor return [ \ {'text' : word, 'highlight' : 'Identifier'}, \ {'text' : ' is found'}, \] endfunction call echodoc#register("sample", s:sample_dict)
echodoc を使ってみた
概要
eldoc.elはエコーエリアに関数の引数を表示させることができるプラグインです。 これと同様なものとして、私はechodocを開発しました。 現在neocomplcacheが対応しています。 eldocのように対応プラグインが自由に機能を追加できるのですが、難点として、まだドキュメントがありません。
http://vim-users.jp/2010/12/hack189/
1.複数のプラグインから出力できる(cmdheightを大きくしないと意味がない)
http://lingr.com/room/vim/archives/2010/08/10#message-610766
2.優先度を設定できる
3.動的にプラグインを追加・削除できる
4.ハイライトを設定できる
5.neocomplcacheがインストールされていれば、context filetypeに対応できる
6.認識するファイルタイプは複数設定できる
少なくとも、ftpluginではこういうことはできません
statuslineに表示できないのはデメリットかもしれませんが。
とはいえ、statuslineに長い情報を載せるわけにはいかないので、
るびきちさんも画面最上部に表示するようにしていましたし
echo areaに表示しても問題はないと思います
syngan の解釈
- echodoc#register() で登録された dict を探索して, 見つかった情報をエコーエリアに表示する
- 対象となる文字はカーソル位置より前にある文字列?
- 一定時間カーソルが動作しない (autocmd CursorHold, CursorHoldI) ときに発動する.
autocmd CursorHold,CursorHoldI * call s:on_cursor_moved()
インストール
NeoBundle で. 最初は lazy じゃないほうがいいかも.
register() されたタイミングで動作するようになるので vim 起動時に動作するわけではないことに注意.
NeoBundle 'Shougo/echodoc', '', 'default' call neobundle#config('echodoc', { \ 'lazy' : 1, \ 'autoload' : { \ 'insert' : 1, \ }})https://github.com/Shougo/shougo-s-github/blob/36def7452ab88258d0160b1ec45dd6e799809811/vim/.vimrc#L135
insert (Number) If set to non-zero, neobundle will |:NeoBundleSource| on |InsertEnter| autocmd.https://github.com/Shougo/neobundle.vim/blob/436e4d4c5fff7023e95d93886724adfb690f3425/doc/neobundle.txt#L700
5/18 22:05 追記
lazy 設定すると, g:echodoc_enable_at_startup が有効にならない感じがする. issue あげていたからそのうち直ると思う.
5/20 21:00 追記
- 上記のバグは修正されました. neobundle の更新が必要
echodoc#register(name, dict)
独自でエコーエリアに表示させたいものがある場合には, echodoc#register を使って登録すれば良い.
- name は unregister で使用される. dict.name と同じ値を指定すれば良いと思う.
- dict: 辞書形式, 以下のキーを持つ
- name::string (必須)
- 任意につける名前. unregister 時のみに使われる.
- rank::integer (必須)
- 登録する dict の優先度. rank が小さいものから優先的に探索される.
- filetypes::dictionary (必須)
- dict を検索対象とする filetype を登録する. 辞書のキー名のみを使用し, 値は使用していない. dict.filetypes が空の場合には, すべての filetype に対して探索対象となる (必須)
- search::funcref(cur_text::string)
- 探索する関数. カーソル位置より前にある文字列?が cur_text に設定される. (@see echodoc#s:get_cur_text())
- 復帰値は dictionary の list. dictionary は以下のキーを持つ
- text: 出力する文字列 (必須)
- highlight echohl により設定される文字列のハイライト(任意)
- name::string (必須)
注意点
- 同じ名前で登録すると, 以前登録したものは削除される.
autoload/echodoc.vim
function! echodoc#register(name, dict) "{{{ call echodoc#unregister(a:name) call add(s:echodoc_dicts, a:dict) call sort(s:echodoc_dicts, 's:compare') endfunction"}}}
なぜか何もしなくても使える
Shougo Ware を install しているといくつかの plugin が register する
今のところ、neocomplcache や vimshell が対応している
Shougoの開発環境
実際, こんな感じで echodoc が追加されていた.
[ " neocomplcache {'rank': 5, 'name': 'include_complete', 'search': function('120'), 'filetypes': {}}, " neocomplcache {'rank': 10, 'name': 'vim_complete', 'search': function('144'), 'filetypes': {'vim': 1}}, " neosnippet {'rank': 100, 'name': 'neosnippet', 'search': function('102'), 'filetypes': {}}, {...} ]
登録部はこんな感じ
autoload/neocomplcache/sources/include_complete.vim
if neocomplcache#exists_echodoc() call echodoc#register('include_complete', s:doc_dict) endif
NOTE
- insert モードに入った時に echodoc が初期化されるが, そのときに echodoc#register() されるわけではないので, vim 起動時にすぐに動作するわけではない. neocomplcache 発動時などに登録される.
TODO
某言語のマニュアルを引くために, 外部コマンドを叩きにいくのだけど, これがとっても遅くて固まる.
非同期でやりたいけど vim 力不足により回避できないでございます.
vital.vim の Web.Http.request を使ってみた その2
get/post/request
get({url}, {param}, {header}) Vital.Web.Http.get() post({url}, {param}, {header}) Vital.Web.Http.post() request(...) Vital.Web.Http.request()
get/post に関しては request のラッパであり, request() が使えるようになればいい.
function! s:get(url, ...) let settings = { \ 'url': a:url, \ 'param': a:0 > 0 ? a:1 : {}, \ 'headers': a:0 > 1 ? a:2 : {}, \ } return s:request(settings) endfunction function! s:post(url, ...) let settings = { \ 'url': a:url, \ 'data': a:0 > 0 ? a:1 : {}, \ 'headers': a:0 > 1 ? a:2 : {}, \ 'method': a:0 > 2 ? a:3 : 'POST', \ } return s:request(settings) endfunction
client/command
"client" Default: "curl" or "wget" (executable one) HTTP client used for a request. "command" Command name for client. You should use with "client".
- 現状, "client" には "curl" か "wget" しか設定できない.
"command" は使い道がわからない. たとえば "curl" と全く同じ引数をとるコマンド "hoge" が存在するなら, 以下のように設定すればいいはずだが...- "command" は "client" へのフルパスを指定するのを想定しているらしい.
{"client" : "curl", "command" : "hoge"}
"maxRedirect"
manpage of curl
リダイレクト追跡回数の上限を指示します
-
- wget は指定方法が間違っている気がする.
- let command .= ' --max-redirect ' . a:settings.maxRedirect + let command .= ' --max-redirect=' . a:settings.maxRedirect
"param"
-
- dictionary or string と書いてあるが, string は動作しない.
"param" Default: (None) Get parameters. This is a string or a dictionary. If dictionary, it is converted to a string by |Vital.Web.Http.encodeURI()|.
-
- "data" は対応しているのでバグだとおもう
- let getdatastr = s:encodeURI(settings.param) + if s:Prelude.is_dict(settings.param) + let getdatastr = s:encodeURI(settings.param) + else + let getdatastr = settings.param + endif
"data"
元のコマンドとの対応
Vital | curl | wget |
---|---|---|
maxRedirect | --max-redirs | --max-redirect |
timeout | --max-time | --timeout |
username/password | --anyauth --user | --http-user, --http-password |
data | --data-binary | --post-file? |
headers | -H | --header |
復帰値
ヘルプに復帰値に関しての説明はほとんどない. 実行結果での比較
let g:VITAL = vital#of('vital') let HTTP = g:VITAL.import('Web.Http') echo HTTP.get("localhost") { 'status': 200, 'success': 1, 'header': [ 'Date: Tue, 07 May 2013 06:24:47 GMT', 'Server: Apache/2.2.22 (Ubuntu)', 'Last-Modified: Fri, 26 Feb 2010 10:31:14 GMT', 'ETag: "64d92-2d-4807e66192080"', 'Accept-Ranges: bytes', 'Content-Length: 45', 'Content-Type: text/html' ], 'statusText': 'OK', 'content': '<html><body><h1>It works!</h1></body></html> '}
% telnet localhost 80 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. GET / HTTP/1.0 HTTP/1.1 200 OK <== status, statusText Date: Tue, 07 May 2013 06:30:25 GMT Server: Apache/2.2.22 (Ubuntu) Last-Modified: Fri, 26 Feb 2010 10:31:14 GMT ETag: "64d92-2d-4807e66192080" Accept-Ranges: bytes Content-Length: 45 Connection: close Content-Type: text/html <html><body><h1>It works!</h1></body></html> Connection closed by foreign host.
- 一番問題なのは正常終了か異常終了かの確認方法が記述されていないこと.
- HTTP から復帰がある場合には, "success", "status", "statusText" に値が設定される.
- HTTP の status コードをみて, "success" に 0 (異常)または 1 (正常/200番台)が設定される.
- たとえばネットワークエラーで web サーバに接続できなかったときには "success" は設定されない.
- エラーメッセージも得られない. 何か異常があったことだけはわかる.
- たとえば 302 が返ってきた場合にも 0 (異常)が設定される
- あとから追加された "maxRedirect" の考慮不足かな. うちのせい?
- HTTP から復帰がある場合には, "success", "status", "statusText" に値が設定される.
- "header" はヘッダ部の情報が一行ずつ文字列としてリストに格納される.
- 解析には parseHeader を使うと良い
parseHeader
parseHeader({headers}) Vital.Web.Http.parseHeader()
- request/get/post 関数で得られるヘッダ部は「文字列のリスト」でそれを解析して辞書に変形する.
- requst() 関数の処理を軽くするために別にしてあるのだと思う.
let g:VITAL = vital#of('vital') let HTTP = g:VITAL.import('Web.Http') let RET = HTTP.get("localhost") echo HTTP.parseHeader(RET.header) { 'ETag': '"64d92-2d-4807e66192080"', 'Content-Type': 'text/html', 'Date': 'Tue, 07 May 2013 06:39:55 GMT', 'Accept-Ranges': 'bytes', 'Content-Length': '45', 'Last-Modified': 'Fri, 26 Feb 2010 10:31:14 GMT', 'Server': 'Apache/2.2.22 (Ubuntu)' }
encodeURI/decodeURI
encodeURI({param}) Vital.Web.Http.encodeURI() decodeURI({str}) Vital.Web.Http.decodeURI()
URL エンコード/デコードをする. まだ使っていない. ローカルの関数を呼び出し中. そのうち使う
encodeURIComponent
encodeURIComponent({str}) Vital.Web.Http.encodeURIComponent()
まだ使っていない. 使い道もしらない.
まとめ
- いまだに csh 環境で Vitalize するとカレントディレクトリに "1" という空ファイルができるバグは残っている.
- カレントディレクトリの 1 ファイルを壊すバグが残っている
- (続):Vitalize を複数回実行するとカレントディレクトリに空ファイルができる. - vim 初心者の作業メモ
- 実行環境に curl か wget がインストールされている必要がある.
- 復帰値に関する説明がほとんどない.
- エラー処理に関する記述はない
- 接続エラーなどの情報は全く得られない
- 302 が返ってきた場合にも "success" に 0 が設定される
- エラー処理に関する記述はない
- request(param) に string が指定できない (ドキュメントとの差異)
- "curl -F" がないから, pukiwiki.vim における curl 直呼び出し部分は完全に削除できない?? 理解不足かな?
- デバッグ用の手段を用意して欲しい.
差分
--- autoload/vital/__latest__/web/http.vim 2013-05-05 23:55:12.000000000 +0900 +++ autoload/vital/_3370e3e/web/http.vim 2013-05-07 22:12:02.000000000 +0900 @@ -116,7 +116,11 @@ let settings.headers['Content-Type'] = settings.contentType endif if has_key(settings, 'param') - let getdatastr = s:encodeURI(settings.param) + if s:Prelude.is_dict(settings.param) + let getdatastr = s:encodeURI(settings.param) + else + let getdatastr = settings.param + endif if strlen(getdatastr) let settings.url .= '?' . getdatastr endif @@ -194,7 +198,7 @@ let command .= ' -O ' . a:quote . a:settings._file.content . a:quote let command .= ' --server-response -q -L ' if has_key(a:settings, 'maxRedirect') - let command .= ' --max-redirect ' . a:settings.maxRedirect + let command .= ' --max-redirect=' . a:settings.maxRedirect endif let command .= s:_make_header_args(a:settings.headers, '--header=', a:quote) let timeout = get(a:settings, 'timeout', '') @@ -210,7 +214,7 @@ let command .= ' ' . a:quote . a:settings.url . a:quote if has_key(a:settings._file, 'post') let file = a:settings._file.post - let command .= ' --post-data @' . a:quote . file . a:quote + let command .= ' --post-file ' . a:quote . file . a:quote endif call s:Prelude.system(command)