少しばかり機能追加した
- EVL105: グローバル変数が g: なしで代入されているときにはエラーになるようにした.
- EVL205: scriptencoding のチェックを追加した
- コマンドI/F を追加した [shell script]
$ ./bin/vimlint.sh file1 [...]
- exists() を監視するようにした.
- https://github.com/syngan/vim-vimlint/issues/21
- これまでは以下のような場合, hoge 変数に対して, EVL104 (値が未設定かもしれないエラー) を返していた.
if cond let hoge = 10 endif if exists('hoge') echo hoge endif
-
- 以下のような場合には対応していない.
- case1: exists の引数が文字列でない場合
- 以下のような場合には対応していない.
let str = "hoge" if exists(str) echo hoge
-
-
- case2: あるルートで複数の変数に値を代入して, 一つの変数のみでチェックする場合
-
if cond let hoge1 = 10 let hoge2 = 20 endif if exists('hoge1') echo hoge1 echo hoge2 endif
- エラーメッセージの抑止をできるようにした
- https://github.com/syngan/vim-vimlint/issues/8
- ただ, これだといつでも抑止される可能性大なので, 部分的に抑止する方法を提供したい.
- また, 現状では watchdogs 経由の場合には効果がない.
では皆様良い vim script ライフを.
vim-vimlint 作った
この記事は Vim Advent Calendar 2012 357日目の記事になります.356日目は id:leafcage さんによる 'nobuflisted' なバッファの作り方 - cafegale(LeafCage備忘録) でした.
vim-vimlint を作りはじめたのはだいぶ前で更新も止まっているのですが, 記事を書いていなかったので紹介します. いまだにドキュメントまともに書いていません. すいません.
概要
vim-vimlint は vim script の文法チェックを行うプログラムです.
以下のような実行時ではないと検出できないエラーを検出します.
- 初期化されていない変数の参照
- 初期化されているが参照されない変数
- build-in 関数の使用法誤り (引数の数チェック)
- 使用されない関数の引数
これにより, 関数の引数に a: を付け忘れて参照していたり, エラールートなど実装したけど通したことがないルートのバグを事前に検出することができます.
例えば以下のようなバグを検出しました.
- vitalizer s:git_checkout() · Issue #95 · vim-jp/vital.vim · GitHub (エラールートの a: 付け忘れ)
- fix s:validate() by syngan · Pull Request #35 · thinca/vim-ref · GitHub (エラールートの文字列結合子漏れ)
- undefined variable: bundle_names · Issue #142 · Shougo/neobundle.vim · GitHub
- fix vimlint error: by syngan · Pull Request #111 · Shougo/vimshell.vim · GitHub
インストール
NeoBundle を使う場合, 以下のように vimrc に記述してください.
NeoBundle 'syngan/vim-vimlint', { \ 'depends' : 'ynkdir/vim-vimlparser', \ 'autoload' : { \ 'functions' : 'vimlint#vimlint'}}
簡単な使い方
" 任意のファイル :call vimlint#vimlint(filename) " 指定されたディレクトリ配下の .vim ファイル :call vimlint#vimlint(directory)
上記のように実行すると, echo でチェック結果を出力します. 出力先はオプションで変更します.
" ファイル outputfilename に出力する場合 :call vimlint#vimlint(filename, {'output': 'outputfilename'}) " リストで結果を取得する場合 :echo vimlint#vimlint(filename, {'output': []})
出力
echo 出力は以下の形式です.
'%f:%l:%c:%m'
%m は以下の形式です.
$ERRNO: $(ERRMSG)
$ERRNO は
- EVPxxx の形式は vim-vimlparser によるエラーメッセージ. このメッセージが出力された場合には vim-vimlparser の解析が停止しているのでそれ以上の処理はできなくなります.
- EVLxxx または Exx の形式は vim-vimlint によるエラーメッセージです.
詳細は vim-vimlint/vimlint.txt at master · syngan/vim-vimlint · GitHub を参照してください.
実装について
本プラグインは vim-vimlparser により解析されたデータを基にしています. したがって, vim-vimlparse が構文解析に失敗すると, 本プラグインは動作しません. コマンドまわりで停止することがあり, 特に test/spec 系のソースではエラーになってしまうことが多いです.
また, どちらも pure vim script で書かれていて, とても遅いです.
vim-vimlint でチェックしている内容は vim-vimlint/test at master · syngan/vim-vimlint · GitHub を見てもらうと一応確認できます. lint と名前をつけたので基本的にあやしいものはエラーに倒す方針で実装しています.
例えば以下のようなコードは判定できず未使用変数のエラーになります.
function! g:open(...) .... let path = printf('gitlab://%s', join(base + args, '/')) let opener = 'edit' execute opener . '`=path`' endfunction
連携プラグイン
vimproc がインストールされていれば, 保存時に非同期で文法チェックしてくれます. watchdogs 便利.
ここで注意ですが, watchdogs で vimlint を使う場合 NeoBundleLazy にしていると動作しないので, Lazy にしないことをお勧めします.
- vimlparser も Lazy だと動作しません (2013/11/25 追記)
終わりに
以下のことをやりたいと思っていますが, 手が回っていません.
- ドキュメント
- エラーを抑止する設定
- unused argument などは無視して良いことが多い
- オプションを追加するか, ソース上にコメントを追加する形にするか.
- PR お待ちしています.
lint を保存毎に実施する必要はないと思いますが, メジャーバージョンアップ時などに思い出して使ってもらえると幸いでございます.
さーて明日の VAC さんは?
明日以降の VAC は決まっていないようですね. まだ #vimconf2013 が終わってない人がたくさんいますよね.
vim-gitlab 作った
今日は vimconf2013 が開催されるようですが, 土日は身動き取れない身分なので参加できません. 残念です..
さて, この記事は Vim Advent Calendar 2012 351日目の記事になります. VAC 初参加であります.
350日目は syui さんによる http://mba-hack.blogspot.jp/2013/11/vim-vim-script.html でした。
近頃は社内で開発している製品のソースも git で管理をしているのですが, 社内で開発している製品を github で公開するわけにはいかないので, GitLab を使っています.
で, GitLab の参照・変更のたびにブラウザと Vim を行き来するのは面倒なので, GitLab を操作する vim プラグイン vim-gitlab を作ってみました.
このプラグインは, id:thinca さん作の絶賛プロトタイプバージョンな vim-github を元に作成しました. (アルファにも届いていないそうですが, 素人がスクラッチ開発するよりは良い作りになっているはず.)
- GitHub - thinca/vim-github: An interface for Github.
- Vim から Github Issues が使いたくなったので github.vim を作り始めた - 永遠に未完成
ということで, まだドキュメントを書いてはいませんが,
さて, 以下, Vim から Github Issues が使いたくなったので github.vim を作り始めた - 永遠に未完成 の転載に近い状態ですが,
インストール
NeoBundle を使う場合, 以下のように vimrc に記述してください.
NeoBundleLazy 'syngan/vim-gitlab', { \ 'autoload' : { 'commands' : 'Gitlab'}}
今のところできること
- Issues のリストの取得/表示
- 個々の Issue の表示(コメント付き)
- 新しい Issue の登録
- 既存の Issue の close/reopen
- 既存の Issue の編集
- コメントの追加
簡単な使い方
準備
グローバル変数 g:gitlab_config に環境を設定します.
Github と異なり, 複数の URL にアクセスできるようにするためです.
g:gitlab_config は辞書でキーは任意に設定します.
キー値は辞書で以下のように設定します.
g:gitlab_config['name'] = { \ 'url' : 'http://localhost/', \ 'user' : '', \ 'email' : 'admin@local.host', \ 'password' : 'optional', \}
ここで,
- url: アクセスする GitLab の URL (必須)
- user/email: ログイン ID (必須)
- password: パスワード (任意)
起動
" 任意のリポジトリ :Github name issues {user}/{repos} " Issue 番号指定 :Github name issues {user}/{repos} {numberk} " Issue 新規作成 :Github name issues {user}/{repos} new
ここで, 第 1 引数 name は g:gitlab_config で設定したキーです.
バッファが開いたら、
- R か
でリストを更新 で個々の Issue を開く で Issue リストに戻る - button 上で
を押すとそれっぽいことが起きる で次の Issue, で前の Issue を開く
連携プラグイン
- GitHub - osyo-manga/vim-precious: Vim constext filetype
- Vim でコンテキストによって filetype を自動的に切り換えるプラグインをつくっている - C++でゲームプログラミング
- precious.vim がチョー便利 - vim 初心者の作業メモ
以下のように設定しておけば, issues に登録されたソースをそのまま実行できます.
let g:context_filetype#filetypes = { \ "gitlab-issues" : [{ \ 'filetype': '\1', \ 'start': '^\s*```\s*\(\h\w*\)', \ 'end': '^\s*```$', \ }], \}
終わりに
さて, 明日以降の VAC は決まっていないようですが, #VimConf2013 の報告に期待しませう.
352日目の VAC は deris さんの vimconf2013 参加報告でした.
エラー発生箇所の探索
function <SNR>96_on_cursor_moved..139 の処理中にエラーが検出されました: 行 22: E715: 辞書型が必要です
上記のエラーが発生した. エラー発生箇所特定のためのメモ*1. このメッセージは, 関数
最初に
:scriptnames .... (略) .... 94: ~/.vim/bundle/context_filetype.vim/autoload/context_filetype.vim 95: ~/.vim/bundle/echodoc/plugin/echodoc.vim 96: ~/.vim/bundle/echodoc/autoload/echodoc.vim 97: ~/.vim/bundle/neosnippet/autoload/neosnippet.vim 98: ~/.vim/bundle/neosnippet/autoload/neosnippet/util.vim .... (略) ....
一つ目の関数は echodoc/autoload/echodoc.vim に定義されている関数 s:on_cursor_moved() だとわかる.
次に, 139 が何かを調べる. これは numbered function と呼ばれるもの.
*numbered-function* *anonymous-function* 関数に名前をつける必要をなくすために、関数を定義して直接辞書に代入することがで きる: > :let mydict = {'data': [0, 1, 2, 3]} :function mydict.len() dict : return len(self.data) :endfunction :echo mydict.len() こうすると関数に番号がふられ、dict.lenがこの関数を参照する|Funcref|となる。こ の関数は|Funcref|を通してのみ呼び出せる。参照している|Funcref|がなくなると、こ の関数は自動的に削除される。 番号付き関数には "dict" 属性を付ける必要はない。 番号付き関数でエラーが発生したときは、あるトリックを使うことで発生源を確認でき る。例えば 42 という関数なら次のようにする: > :function {42}
関数の特定には以下のようにすれば良い.
:verbose function {139} function 139(cur_text) dict Last set from ~/.vim/bundle/neocomplete/autoload/neocomplete/sources/include.vim .... (略) .... 18 19 for word in reverse(words) 20 let key = tolower(word[: completion_length-1]) 21 22 for include in filter(copy(s:include_info[bufnr('%')].include_files), 'ha s_key(s:include_cache, v:val) && has_key(s:include_cache[v:val], key)') 24 for matched in filter(values(s:include_cache[include][key]), 'v:val.wor d ==# word && has_key(v:val, "kind") && v:val.kind != ""') 26 let ret = [] 27 .... (略) ....
{139} の 22 行目でエラーが発生しているので, 上記の部分が問題の箇所であると分かった*2.
precious.vim がチョー便利
http://d.hatena.ne.jp/syngan/20130623/1371923016複数の種類のコマンドの切り分けを自動的にやらせる
pukiwiki で作業ログを書いているときに, 一つのページに複数のコマンドの作業ログを書くことがある.
再実行させるときに, 毎回自分で切り替えながらコマンド実行しているけど, 範囲を選択して \r で実行できるようにしたい.
...ここからは python コード xxx xxx ここまでは python コード ほげほげ ほげほげ ここからは ruby コード yyy yyy ここまでは ruby コード
以前の記事に作者の id:osyo-manga さんからコメントで教えていただいた. precious.vim + quickrun.vim で, pukiwiki.vim での作業が捗ることこの上ない.
設定
必須プラグインである context_filetype.vim に記述している部分が他言語であることを教えてあげる必要がある.
pukiwiki 上に, 整形済みテキストとしてソースコードを記述しているのでそこに自由に仕様を決めれば良い.
FormattingRules
行頭が半角空白で始まる行は整形済みテキストとなります。行の自動折り返しは行なわれません。
他言語毎に設定を書くのは面倒なので markdown の設定を参考にした.
pukiwiki 上では少し目立つようにしたかったので ``` を ### として書き換えた.
\ 'pukiwiki': [ \ { \ 'start' : '^\s*###\s*\(\h\w*\)', \ 'end' : '^\s*###$', \ 'filetype' : '\1', \ }, \ ],
あとは, quickrun を使う設定をすれば \r すれば自動的に言語を切り替えて実行してくれる.
- 参考:コンテキストの範囲を quickrun する @ Vim でコンテキストによって filetype を自動的に切り換えるプラグインをつくっている - C++でゲームプログラミング
- 最初は私の使っている vim のバージョンが古いために動かなかったが, 対応してもらった. thx!
- ヘルプで example を書くときなど便利な場面はたくさんありそう.
vim-pukiwiki で画像表示に対応した
添付ファイルを display コマンド(imagemagic)で表示するだけなんだけど、画像表示に対応した. とっても便利だ.
だけども, 画像を開くたびに違うウィンドウが立ち上がるので、マウスを操作する必要がでてきてうっとーしくて仕方がない。
何か同じウィンドウで画像だけを切り替える方法はないだろうか
- display. たぶん無理
- eog. ローカルだけかと思ったらそうじゃなかった. 便利.
- eog -w. session は何かできそうなにおい.
Session management options --sm-client-id=ID Specify session management ID --sm-config-prefix=PREFIX Specify prefix of saved configuration --sm-disable Disable connection to session manager
アプリケーションのオプション: -f, --fullscreen フルスクリーンモードで開く -g, --disable-gallery 画像ギャラリーを無効にする -s, --slide-show スライドショーモードで開く -n, --new-instance 既存のウィンドウを再利用せずに新しいインスタンスを起動する -w, --single-window 単一のウィンドウで開く (複数のウィンドウを開いている場合は最初のウィンドウを使用する)