Hatena::ブログ(Diary)

日記

2012-09-29

[Vim] if_python のおかしな挙動

if_python を使っていたらおかしな挙動ではまったのでメモ。

if_python では vim.eval 関数を使えます。 vim.eval は引数Vim script の式を取って、それを評価した結果を python の値として取得できます。

以下のコードでは、 Vim script の matchstr('', 'a') を評価した結果を表示します。

これを実行した結果として、空文字列('')が表示されることを期待しましたが、 None と表示されました。Vimバグ

python import vim
python print repr(vim.eval("matchstr('', 'a')"))
" Noneと表示される

普通に Vim script として評価した場合は期待通りの結果となります。 if_python で vim.eval したときだけなぜか None となってしまいます。

echo matchstr('', 'a')
" 結果は空文字列となる
echo type(matchstr('', 'a')) == type('')
" 型は文字列型となっている

ちなみに、 matchstr が空文字列以外を返す場合は期待通りの動作となります。

python import vim
python print repr(vim.eval("matchstr('a', 'a')"))
" 'a'と表示される

let g:str = ''
python print repr(vim.eval("g:str"))
" ''と表示される

let g:str = matchstr('a', 'a')
python print repr(vim.eval("g:str"))
" Noneと表示される。一時変数に入れてもやっぱりだめ

回避策

とりあえず、 matchstr の結果に空文字列を結合することで期待通りの動作になりました。

python import vim
python print repr(vim.eval("matchstr('', 'a') . ''"))
" ''と表示される。期待通り

2012-09-18

[Vim]エスケープシーケンスを含む vimshell バッファで表示通りにヤンクする

vimshell は、エスケープシーケンスを解釈し、 vimshell バッファ上で色付けして表示することができます。

以下は vimshell で git log --color を実行した図です。コミットハッシュ番号が黄色になっています。

f:id:chikatoike:20120918070020p:image

問題

これをそのままヤンクするとエスケープシーケンス文字もそのままヤンクされ、このようになってしまいます。

^33m4391e8e^m Implement new cache method.
^33m947fb43^m - Changed default cache lines in nofile buffer.
^33m3232f40^m Merge pull request #250 from ujihisa/master
^33mec342f3^m better english
^33m407608b^m - Improved FAQ.

vimshell は vim が conceal に対応している場合は conceal 機能でエスケープシーケンス文字を隠していますが、conceal はバッファの実際の文字を変えるわけではないため、ヤンクしたときにエスケープシーケンス文字も一緒に付いてきてしまいます。

これは不便ですね。表示されているものがそのままヤンクされるようになってほしいです。

解決方法

conceal された文字を取得する方法は vim に用意されています。 synconcealed 関数です。この関数は現在のバッファの行番号、桁位置を引数に取り、Conceal 可能リージョンの中にいるかどうかの情報を返します。

この関数を使えば、表示されている文字列を取得できます。これを使ってプラグインを作りました。

設定

プラグインGitHub - chikatoike/concealedyank.vim で公開しています。これを neobundle 等でインストールしてください。

このプラグインは <Plug>(operator-concealedyank) をマッピングとして公開しています。例として、例えばこのように .vimrc に書きます。

xmap Y <Plug>(operator-concealedyank)

以上の設定をすることで、 vimshell バッファでビジュアルモードで範囲選択し、Yを押すとエスケープシーケンスを除いた、表示されているままの文字列をヤンクできます。

補足

このプラグイン自体は、 vimshell のみを対象にしたものではなく、 conceal が使われているバッファすべてで機能します。conceal は、例えば :help のバッファで使われています。

また、 conceal は文字を消すだけではなく置き換えることもできますが、置き換えた後の文字列をヤンクできるはずです。(確認していません)

また、手抜きしたため、現在のところオペレーターとして動作しません。ビジュアルモードのみで機能します。例えば、 ノーマルモードで Yiw としても普通に yiw と同じようにヤンクします。これはいずれ直すかもしれません。

2012-09-09

Source Mapを使ってJSXで生成したJSファイルからJSXファイルの対応箇所にジャンプする

SourceMapについては以下の記事を参照してください。

無料で作成 べんりなブログ:MARUTA

基本的にブラウザに搭載されているデバッガで使用することを想定しているようですが、当然他のツールから使用することもできます。というわけで、タイトルの通りのプラグインを作ってみました。

インストール

GitHub - chikatoike/sourcemap.vim: Switch between generated file and orignal file using source map.インストールしてください。

準備

Source Mapの情報を.mappingファイルに出力する必要があります。JSXファイルをコンパイルするときに、 --enable-source-map オプションを使用してください。

ちなみに、.mappingファイルに含まれるファイルパスが相対パスだと、うまく動作しないかもしれません(JSXコマンドが sourceRoot を出力してくれないため。ただ、spec 的には sourceRoot は optional)。そのため、絶対パスで出力したほうがいいかもしれません。絶対パスで出力するには、JSXコマンドに渡すファイル名を絶対パスにすればよいみたいです。

動作

JSXコンパイルして出力されたJSファイルをVimで開いている状態で、 :SourceMapSwitch コマンドを実行すると、JSXファイルの対応箇所にジャンプします。ただし、JSXが自動的に挿入したコードなど、対応関係がない位置で実行してもジャンプしません。また、逆のJSXファイルからJSファイルへのジャンプはまだ出来るようになっていません(可能なのかもわかっていませんが)。

さらに、Source Mapとしては行内の桁位置を情報として持っていますが、手を抜いたため、行番号しか見ていません。なので、ジャンプする位置は行頭となっています。

実装

このプラグインGitHub - mozilla/source-map: Parse and consume source maps. のコードを流用して作りました。javascriptのコードをVim scriptへベタ移植しています。vital.vimも使用しています。

また、この記事 source map generatorの使い方 - Islands in the byte stream も参考にしました。

JSX以外の言語について

Source Mapは言語非依存の機能だし、このプラグインにもJSX特有の処理はないので、他のSource Map対応の言語でも使用できるはずです。ただし、JSXでしか確認していません。

また、コンパイル後のソースコードの末尾のsourceMappingURLを見てmappingファイルを特定しているので、それも必要です。

2012-09-07

非同期で動作するVim用のシンタックスチェックプラグインを開発しています

プラグイン名は activefix.vim です。まだ開発途中ですが、それなりに動作するようになったので公開します。

説明

シンタックスチェックを行うVimプラグインGitHub - vim-syntastic/syntastic: Syntax checking hacks for vim が有名ですが、これはシンタックスチェックを実行している間ユーザーの操作をブロックしてしまいます。

そこで、操作をブロックせずに、syntasticのように多数のファイルタイプに対応したシンタックスチェッカーを開発することにしました。

必要なもの

GitHub - Shougo/vimproc.vim: Interactive command execution in Vim.が必要です。ただし、vimprocがインストールされていなくても動作しないわけではなく、syntasticと同様にファイルを保存するときにブロックして実行するようになります。

プラグイン本体はGitHub - chikatoike/activefix.vim: Syntax checker for Vimにあります。これをpathgenやneobundle等、任意の方法でインストールしてください。

対応する形式

syntasticのソースコードを流用しているので、基本的にsyntasticと同じ形式に対応しています。また、形式毎のオプション変数も同じです。形式毎、というのはたとえばpythonなら g:syntastic_python_checker_args などです。一方g:syntastic_check_on_openはsyntastic本体のオプション変数で、activefix.vimでは適用されません。

また、そのまま流用できなかった形式があり、それらは現状未対応となっています。

使用できない形式は、ada,c,cpp,d,haskell,haxe です。

注意点として、上ではsynasticと同じ形式に対応していると書きましたが、今のところ動作を確認したのは python/pyflakes と ruby/mri だけです。その他の形式は動作しないかもしれません。そのうち確認していきます。

使い方

シンタックスチェックに使う外部プログラムインストールされている状態であれば、以下のタイミングでシンタックスチェックを開始します。

  • ファイルを開いた時
  • ファイルを書き込んだ時
  • バッファを編集して、一定時間経過した時(updatetimeに設定してある期間)

インサートモードに入っている時でも動作します。ブロックしないので開始した後も操作可能です。

チェックが終了したら、自動的にlocation-listを開いてエラー一覧を表示します。該当行のハイライトもしますが、不完全かもしれません。

注意点

上に書いてあるupdatetimeはデフォルトで4000ミリ秒となっているので、バッファを変更してから開始するまでちょっと待つ必要があります。もっと早く開始したい場合は以下のような感じで短い時間を設定してください。

:set updatetime=1000

その他

上に書いた通り、syntasticのソースコードを流用しています。また、 id:thinca さんのquickrunのソースコードを流用しています。このプラグインの実装について大雑把にいうと、 quickrunの上にsyntasticを乗せた感じです。quickrunのrunnerやhookのようなモジュール構造も参考にした、というよりほとんどそのまま使っています。ただし、quickrunと互換性があるけでもないし、現状は拡張性もないです。

最後に

いまはまだドキュメントを用意できていません。そのうち書きます。