Hatena::ブログ(Diary)

Alone Like a Rhinoceros Horn

2012-02-21

unite-outline の近況: 次期バージョンの開発

昨年の秋頃から目立った変化のない unite-outline ですが、開発が停滞しているとか、作者のやる気がなくなった*1とかではなく、「今年の抱負 - Vimプラギン編」で述べた通り、次期バージョンの開発(準備)を少しずつ進めています。

ある程度形になったら別ブランチを切って push しようと思ってますが、まだ仕様をあれこれ考えたり非同期実行のやり方を模索している段階で、ものは全然できておりません(汗 まあ、上半期のうちに最初のバージョンを push できたらいいな、ぐらいの見込みです。*2

大きな変更が必要になるついでに、「もうこの際、たまった負債を全部返済してやる!」みたいな意気込みでして、プラグインの構成上前から気になっていた点や、作者がまずいと思っている outline info の仕様など、全面的に見直してドカンと刷新する予定です。(というか、そうせざるを得ないのです…… 詳細は以下を参照)

で、その次期バージョンですが、青写真は以下の通りです。

NuOutline(仮)

アウトライン解析部を独立したプラグイン(NuOutline(仮))として切り出し、unite-outline をそのフロントエンドとして添付するという構成をとります。

プラグインの構成上一番大きな変更点がこれです。

「unite.vim の source として unite-outline は大き過ぎる」、「アウトライン解析を行うプラグインに unite-outline を添付すべきでは?*3」という指摘は以前から何度かあり、自分でも気になっていました。また、

  • autoload/unite/sources/outline/ 以下のディレクトリ階層の深い位置にファイルがごちゃごちゃと多過ぎる。
  • その結果、オートロード関数の名前がやたら長くなる。
  • また、動作が複雑になってオプション変数も増えたが、unite.vim の source のそれはやはり名前が長くなる。
  • unite.vim の source とアウトライン解析部が渾然一体、なんだかなー

といったこともあり、アウトライン解析を行う部分を独立したプラグインとして切り出し、プラグイン全体の構成を仕切り直すことにしました。図で示すと以下のようになります。

f:id:h1mesuke:20120221221020p:image

きれいに 3層に分離しました。3者の役割分担は Webアプリケーションなどでおなじみの MVCパターンでとらえると理解しやすいです。アウトライン表示のインターフェースを提供してくれる unite.vim がビュー、見出し抽出のロジックを持っている NuOutline がモデル、両者の間に入ってあれこれと調停をし、見出しの自動更新のための面倒をみたりする unite-outline がコントローラというわけですね。

V, C は交換可能(にしたい)

NuOutline は(頑張って)unite.vim, unite-outline と密に結合させないで作ろうと思っています。unite-outline はあくまでフロントエンドのデフォルト実装として NuOutline に添付されているもの、という位置付けにして、第三者が別のフロントエンドを提供できる余地を残しておきます。(そんな人が現れるかは別にして ;-) )

が、リポジトリは unite-outline のままで!

どちらかというと unite-outline の方が NuOutline のオマケ的な存在なのですが、Vundle や neobundle.vim 全盛(?)の昨今、リポジトリURL が変わるというのは致命的だと思うので、開発は引き続き、現行の unite-outline のリポジトリで行います。まあ、使うだけなら NuOutline は unite-outline の影に隠れて見えませんし、ユーザーが使うのはあくまで unite.vim を通してですからね。

というわけでなんと、unite-outline という unite.vim の source に、プラグインがまるまる1個付いてくるということになります(笑)

オプション変数名が変化

「unite.vim上でどう表示するか」に関する設定を除き、オプション変数の所管が NuOutline の方へ移るので変数の名前が変わってしまいます。しばらくは古い変数の方も見るようにしたいところですが……

outline info → parser

unite.vim の source である unite-outline の source……的な存在であった outline info は所管が NuOutline の方へ移ります。それにともない名称も outline info から parser に変更し、配置場所も

  • autoload/nuoutline/parsers/

とします。*4unite.vim における sources, kinds, filters などと同様の位置付けになります。

DRY でない create_heading() よ消え去れ!

outline info の仕様には(今となっては)気に入らない部分がたくさんあり、その最たるものが見出し抽出のためのパターンが複雑になると create_heading() の中身が DRY でなくなるというものです。例えば、

'^\s*\(foo\|bar\|baz\|fizz\|buzz\)\>'

のようなパターンを設定したとして、マッチングが行われ、マッチが見つかって create_heading() が呼び出されたとします。その場合、マッチしたサブマッチがどれかによって処理を分けなければならないことがほとんどで、現行の outline info ではマッチした文字列に対して再度マッチングを試み、サブマッチのうちのどれに実際にマッチしたのかを判定するような DRY でないコードが氾濫しています。

これは outline info を書く側の問題ではなくて、そのようにしか書けなくしている outline info の仕様の方に問題があるのです。

「こんなことでは outline info を書いてみようと思ってくれた人も離れていくわ!」

と強く思った私は、outline info の所管が NuOutline へ移るこのタイミングで、その仕様を刷新することにしました。

まだ仕様を練っている段階ですが、

let s:parser.foo_pattern = "foo's pattern"
function! s:parser.create_foo_heading()
endfunction

let s:parser.bar_pattern = "bar's pattern"
function! s:parser.create_bar_heading()
endfunction

let s:parser.baz_pattern = "baz's pattern"
function! s:parser.create_baz_heading()
endfunction

こんな風に、見出しの種類ごとに個別にパターンを設定できるようにし、「どのパターンにマッチしたか」の判定までを本体側の責任として、適切なコールバックが呼び出されるようにします。parser側では見出し(辞書)の作成に専念できるようになるので、パターンマッチ方式の parser を作るための敷居はかなり下がるはずです。

構文解析が必要になるケースのサポート

create_heading() について力説した直後にアレですが、「正規表現によるパターンマッチ → create_heading() 」というやり方で見出しが拾えるファイルタイプは実は少なく、ほとんどのプログラミング言語では見出しを「ちゃんと」拾うのに構文解析が必要になります。

具体的に言うと、ctags などの外部の構文解析プログラムを呼び出し、その出力を解析して見出しの木を parser が自前で作る必要があります。

今後、対応ファイルタイプを増やしていくためにも、その辺の処理が書きやすくなるようなユーティリティコードの充実やドキュメントの整備などが必要と考えています。

まとめ

最初からちゃんと設計しとけや! ヽ(*`Д´)ノゴルァ

うう、当初は「正規表現でマッチさせて拾うだけやん」程度の軽いノリで作り始めたのでございます。最初にコミットされたバージョンの素朴さがすべてを物語っている……

しかし、まあ、ここまできたらプラグインとしてちゃんとしたものにしたいですね!

*1:むしろ逆で、変なブーストが入ったw

*2:今年の抱負ということになってるので、遅くとも年内にはw

*3:alignta に unite-alignta が同梱されているのがこの構成ですね。

*4:outline info は autoload/outline/ に配置してもよいことになっていましたが、これは autoload/unite/sources/outline/ が自作の outline info を配置する場所として位置が深すぎるだろうとの配慮からでした。通常、autoload/ に何かを配置させるにあたっては、プラグイン名できちんと名前空間を切るべきです。

2011-12-05

word の中の単語を選択する textobj-wiw を書いた

(この記事は Vim Advent Calendar 2011 5日目の記事です。前日は thincaさんでした!)


前々から、地味にフラストレーションを感じていたこととして、

この状態から、"word" の部分を書き換えたい場合、 

this_is_a_word_in_a_very_long_identifier

 ↓

this_is_a_word_in_a_very_long_identifier

こう選択する text-object が欲しいんだよ! というのがありました。


また、選択と同様に、

ここから、

this_is_a_word_in_a_very_long_identifier

 ↓

this_is_a_word_in_a_very_long_identifier

this_is_a_word_in_a_very_long_identifier

this_is_a_word_in_a_very_long_identifier

こんな具合にジャンプしていきたいんだよ! とか。


で、この手の「word の中の単語」は上に挙げたような snake case の中だけでなく、thisIsAWordInAVeryLongIdentifier のような camel case の中にもあるし、this#is#a#word#in#a#very#long#identifier のような、Vim script のオートロード関数の名前の中にもあります。

それら「word の中の単語」を一様に取り扱える text-object があれば便利だと思い、kanaさんの textobj-user を使って textobj-wiw というのを書いてみました。

wiw は word in word の略です。「word の中の単語」とは要するに、「Vim における word に含まれている、人間が単語と認識している部分」のことです。

これを使うと、「word の中の単語」間をジャンプで移動できたり、おなじみの iw, aw と同様の操作で「word の中の単語」をサクッと編集/削除/選択できるようになります。

インストール

プラグインインストールするいつもの方法で

の2つをインストールして下さい。

説明になってないような気もしますが、重要なことは textobj-user が必要だということです。

キーマッピング

textobj-wiw には w, b, e, ge, iw, aw に相当する一連のキーマッピングがあり、デフォルトでは以下のキーマッピングを定義するようになっています。

        lhs     Modes   rhs
        ---------------------------------------
        ,w      nxo     <Plug>(textobj-wiw-n)
        ,b      nxo     <Plug>(textobj-wiw-p)
        ,e      nxo     <Plug>(textobj-wiw-N)
        ,ge     nxo     <Plug>(textobj-wiw-P)

        a,w     xo      <Plug>(textobj-wiw-a)
        i,w     xo      <Plug>(textobj-wiw-i)

対応する動作がわかりやすいように prefix を付ける方式にしました。prefix は g:textobj_wiw_default_key_mappings_prefix変数で設定できます。(デフォルトは ",")

デフォルトのキーマッピング体系が気に入らない場合は、vimrc にて g:textobj_wiw_no_default_key_mappings 変数を定義すればデフォルトキーマッピングの定義をキャンセルできます。その上で、各自でよさげなキーマッピングを定義して下さい。

似ている text-objects

キャメルケースについては既にやっている方がいました。あわわ。

また、ある特定の文字で囲まれた部分、を取り扱う text-object としては thincaさんの textobj-between もあります。こちらは選択範囲が word内に限定されません。

探せば他にもあるような気がしますが、恐いのでこれ以上は探しませんw


それでは皆さん、Happy Vimmer days!

2011-09-14

alignta でパターンを正規表現として解釈、は本当に使いやすいのか?

試行錯誤の自問自答中。

を受けて、別ブランチにて作業を開始し、パターンを(デフォルトで)正規表現として解釈するように修正したところ、(当然のごとく)テストがこけるようになった。見てみると

Alignta /* */

みたいなやつが軒並みこけていた。当然。なぜなら * は正規表現のメタ文字だからだ。これまでは ! を付けなければパターンは字面通りの文字列として解釈(正規表現のメタ文字はエスケープ)されていたので、これでよかったのだが、

新しい仕様ではこれを正規表現として解釈するので /* は 0回以上の / という意味のパターンになってしまう。これをエスケープするには

Alignta -e /* -e */

または

Alignta -E /* */

としなければならない。こうして見ると結構めんどくさい気がする。というか、うっかりエスケープの指定忘れが頻発しそうな予感。

厄介なことに * は C言語のコメント開始/終了に使われている記号なので、このミス(エスケープの指定忘れ)、やる人が多いんじゃないかなー。

やっぱり、こういう意図しない整列が行われてしまう可能性があるので、デフォルト正規表現になっているのはちょっとまずいかも知れないと考えている。デフォルトとしては字面通りの文字列として解釈されることを保証して、一部正規表現を使用したいところで、安全装置を解除する的な仕様の方がいいのではないだろうか。

コマンド名に ! を付けたら正規表現として解釈、というのは元々そういう発想にもとづいたものだった。ただ、「それって2つのコマンドの使い分けだよね」、「一括指定しかできないの」、というところが元々の問題意識だったはず。

だったら逆に、正規表現として解釈したいものの前に -r とか -R とかを付けるようにした方がいいのではないか。(-regexp, -Regexp ね)

Alignta -r \d\+

だがこれも、うっかり -r を忘れるというミスが頻発しそうな予感。あちら立てればこちら立たず、ぬーん。

こうなったら、正規表現っぽく見えるものは正規表現として解釈、みたいな仕組みを取り入れてみようか。例えば、\ でエスケープされた文字があればそれは正規表現のメタ文字(である可能性が大)なので、それは正規表現と解釈するとか。そうすれば、エスケープの指定やら、正規表現としての解釈の指定やらをしなくても

Alignta \d\+ /* */

こんなのが通るようになる。で、この自動的な解釈の振る舞いを抑制するのに -e とか -r とかを使うようにすればいい感じになるのではないか。

2011-09-07

unite-outline が見出しを自動更新するようになりました

やった! これで <C-l> ともおさらばだ!

unite-outline の「なんでこれができないの?」の筆頭であった見出しの自動更新をついに実装しました。詳細はヘルプで g:unite_source_outline_filetype_options、unite-outline-filetype-option-auto-update*1 の辺り見てもらいたいのですが、ここで簡単にその設定について解説してみます。

なお、以下の設定はファイルタイプごとに、g:unite_source_outline_filetype_options変数に設定します。とりあえずデフォルトを変更したい場合は「すべてのファイルタイプ」を意味する "*" の設定を変更すれば OK です。

auto_update

見出しを自動更新するかどうか。

1 に設定すると見出しの自動更新が有効になります。
0 に設定するとこれまで通り。見出しを更新したい場合は自分で <C-l> を押します。

デフォルト値は 1 です。

auto_update_event

見出しの自動更新の契機となるイベント、以下のどれか。

  • "write"
    バッファをファイルに書き込んだ時点で見出しが更新されます。通常はこれで十分です。
  • "hold"
    "write" のタイミングに加え、一定時間('updatetime' に設定された時間)カーソルを放置したタイミングでも見出しを更新します。-no-quit な場合に真価を発揮する少しアグレッシブな設定です。*2

デフォルト値は "write" です。

自動更新をオンにしていると unite.vim のウィンドウが開くタイミングでも更新がかかるので、実のところ見出しの一覧を -no-quit で表示させない限り "hold" を選択する意味はあまりありません。-no-quit で使うなら "hold" を使うかどうかを選択、そうでないなら "write" のままがいいでしょう。*3

ファイルタイプごとの特性を見極めて

ファイルタイプによって、見出しの抽出に要する時間や、扱うファイルの平均的なサイズも変化してくるので、そういったファイルタイプごとの特性を見極めた上で、

  1. 自動更新を使わない
  2. 自動更新を使う(更新契機は "write")
  3. 自動更新を使う(更新契機は "hold")

から最適なものを選択して下さい。

以下は、デフォルトでは "write"、C++ では自動更新なし、Markdown では "hold" に設定している例です。*4

        let g:unite_source_outline_filetype_options = {
              \ '*': {
              \   'auto_update': 1,
              \   'auto_update_event': 'write',
              \ },
              \ 'cpp': {
              \   'auto_update': 0,
              \   'ignore_types': ['enum', 'typedef', 'macro'],
              \ },
              \ 'javascript': {
              \   'ignore_types': ['comment'],
              \ },
              \ 'markdown': {
              \   'auto_update_event': 'hold',
              \ },
              \}
追記

Windows では外部プログラムの呼び出しに予想以上に時間がかかる*5ようで、見出し抽出に ctags を使っているファイルタイプ(C, C++, Java, Python)では自動更新にともなう待ち時間が許容できないレベルになることがあるようです。

そのような場合は残念ですが自動更新をオフにして下さい。

この問題を解決するためには外部プログラムの呼び出し部分を非同期にするなどの変更が必要になり、作者の勉強時間も含めてしばらく時間がかかると思われます……

*1:名前が長くてすいません(汗 名前が何かと長くなるのはプラグインプラグインの宿命です。

*2:'updatetime' のデフォルト値は 4000(4秒)でこのままだと少し待たないと更新がかからないので、1000 くらいに設定するといいかも知れません。

*3:-no-quit でない状況で "hold" を使っても、細かな更新作業が増えるだけで恩恵は一切受けられない(見出しの更新に連動して表示を更新させるはずのウィンドウが開いていない)ので、"write" の方が Vim にやさしいです。

*4:これは unite-outline のヘルプにある例のための例です。作者の推奨する設定ではありません。

*5:ちなみに作者は主に Vim を Ubuntu上で使っており、unite-outline の開発ももっぱら Ubuntu でやっているので、そういう問題に気付きにくいのです。

2011-04-16

unite-outline で候補の絞り込みから選択へかけての打鍵数を減らす

unite-outline では、候補の絞り込みの際、見出しの親子関係に配慮し、マッチした見出しだけでなく、その親見出しも絞り込みの結果に残すようにしています。*1

これはメソッド名などで絞り込みを行ったときに、実際にマッチしたもの(メソッド)だけを残すと、絞り込みの結果からはその所属クラスがわからなくなってしまうという問題に対処したものです。

f:id:h1mesuke:20110416084906p:image

▲ 以前の絞り込み結果。絞り込み自体はうまくいっているが、所属するクラスがわからなくなってしまっている。複数のクラスに同名のメソッドがあったりした場合、これではまずい。


f:id:h1mesuke:20110416084905p:image

▲ 現在の絞り込み結果。親見出しも残るようになっているので、所属するクラスがわかる。


これにより、同名のメソッドが複数のクラスにあっても安心安心、というわけなのですが、上の画像を比較してもわかる通り、この場合、絞り込みの結果に(実際にはマッチしていない)親見出しが必ず含まれてくるため、目的の候補へと移動するために必要な打鍵数が増えてしまいます。

特に、モジュール定義、クラス定義の類が深くネストしている場合、目的のメソッドに到達するまでに何度も j を打鍵する必要があり、非常に面倒です。

そこで……

(実際にはマッチしていない)親見出しや、見出し一覧を見やすくするために挿入されている空行をスキップし、実際にマッチしている見出しだけを巡回できるキーマッピングを追加してみました。

追記

unite本体の側で同等のキーマッピングを用意してくれそうな感じなので、以下で紹介している unite-outline で用意したキーマッピングは早くも obsolete と化しました。*2

今回追加したキーマッピングはいずれ削除しますので、お手数ですが、その時には設定の書き換えをお願いします。(追記:2011-04-17)

追記2

上で予告していた通り、実際にマッチしていない候補を飛び越えるキーマッピングが unite.vim 本体の側で実装されましたので、↓で紹介しているような設定はもはや不要となりました。デフォルトキーマッピングで J, K にマップされています。(追記:2011-08-17)


.vim/after/ftplugin/unite.vim に以下のように設定します。*3

if unite#get_context().buffer_name ==# 'outline'
  nmap <buffer> J <Plug>(unite_source_outline_loop_cursor_down)
  nmap <buffer> K <Plug>(unite_source_outline_loop_cursor_up)
endif

このキーマッピングは、unite のバッファの buffer name が "outline" であるで始まる場合にのみ有効なので、unite-outline を呼び出す際には

:Unite -buffer-name=outline outline

とします。これで、絞り込みをかけてから J, K を打鍵すると、(実際にはマッチしていない)親見出しや空行を飛び越えて、マッチした見出しだけを巡回することができます。

*1:ツリーの親子関係に配慮した matcher は先月末に追加された機能です。

*2:とほほ。前にも似たようなことがあった気がする (^^;

*3オプション変数と同様、名前が長くなってしまうのは source の宿命です (^^;

2011-02-26

デフォルトの outline info の作成ポリシー

昨夜、unite-outline の見出し一覧に表示される文字列を簡単にカスタマイズできるように、ユーザーが見出しの変換関数を既存の outline info にモンキーパッチできる仕組みを実装したところ、Lingr の Vim部屋にて、

「この機能は unite本体側に実装したほうがいいんじゃね」

という話になりました↓

自分としても機能の重複は望むところではないし、unite本体側の仕組みとして組み込まれた方がファイルタイプを横断して利用できるフィルタなども簡単に書けそうなので、昨夜の変更は早々に取り下げた*1のですが、

unite.vim の候補一覧の表示のカスタマイズは filter で!

という方向は確かなようですので、それを前提に unite-outline に同梱するデフォルトのoutline info の作成ポリシーを改めたいと思います。

デフォルト outline info の作成ポリシー(改)

情勢変化につき考え直し中

filter によるカスタマイズの余地を残しつつも、ctags を使うもの(C++, Java など)については tagbar の出力を手本にしようかななどと考えている。(2011-02-27)


デフォルト outline info の作成ポリシー

以下のようにします。

  • 見出し一覧の見た目には凝らない
  • なるべくバッファの行をそのまま(情報を欠落させずに)拾う

すなわち、デフォルトの outline info は「ユーザーは必要に応じて unite.vim の filter を書き、見出し一覧の表示をカスタマイズする」との前提に立ち、その入力として適当な、プレーンな見出しを作成するようにします。

ファイルタイプによっては*2デフォルトのままでは少々うるさい感じの表示になると思われます*3が、そこは「見出し一覧を見やすくする filter を書いて公開してくれる」多数のユーザーが現れることを期待し、こちらとしては「どう表示すれば見やすいか」という問題には関知しないことにします。

*1:partial_oinfoブランチに退避してあります。

*2:C++ とか Java とか、型の宣言がある言語は特に。

*3:というか、現にそうなっている。

2011-01-31

unite-outline まとめ

unite-outline の関連エントリが増えてきたのでまとめ。自演乙。*1

*1:ちなみに、私は長島☆自演乙☆雄一郎選手のファンです ( ̄ー ̄)bグッ!

2011-01-30

unite-outline が見出しとして抽出するコメントの形式と見出しレベル

前回のエントリで、unite-outline では、飾り枠線で装飾されたコメントを積極的に見出しとして拾うようにしていると書きました。*1

プログラミング言語用の outline info では、見出しとして抽出されるコメントの形式と設定される見出しレベルに一貫した決まりがあるので、今回はそれについて説明します。

といっても話は簡単で、outline info の "heading-1" なマッチにおいて、「線」と見なされるコメント行の下にある行が見出しとして抽出される、というだけです。そして、その見出しレベルは、マッチした「線」のパターンによって以下の表のように設定されます。

インデント線を構成する文字長さ*2見出しレベル
なし=41〜1
なし=11〜402
なし-
その他*3
41〜2
なし-
その他
11〜403
あり=, -
その他
11〜ファイルタイプによって 5 または 6 に固定*4
またはインデントの深さ + 3

コメント以外の見出しは見出しレベル 4以降からとなります。


この事実を利用して、例えば以下のようにコメントを付加すると、

"=============================================================================
" 見出し1

"-----------------------------------------------------------------------------
" 見出し2

"---------------------------------------
" 見出し3

function! s:foo()
  "---------------------------------------
  " 見出し5
endfunction

function! s:bar()
  "---------------------------------------
  " 見出し5
endfunction

見出し一覧は以下のようになります↓

f:id:h1mesuke:20110129234023p:image

これを積極的に利用することで、Vim script のような関数の定義がフラットに並ぶだけのような言語においても、その見出しを擬似的に階層表示させることができます。

追記

コメント以外の見出しがレベル 4以降からと聞いて、それではコメント見出しがない場合に、見出し一覧の全体が右に寄り過ぎるのではないかと思われたかも知れません。

unite-outline はその辺はうまく処理するようになっていて、例えば抽出された見出しのレベルが [4, 4, 5, 5, 4] の場合、それを [1, 1, 2, 2, 1] に変換してから表示します。

また、[1, 3, 3, 5, 7, 1] のような、中間レベルの見出しがない場合、見かけ上それをないものとして扱い、[1, 2, 2, 3, 4, 1] とします。

*1:実のところこれは unite-outline本体の機能というわけではなく、同梱しているデフォルトの outline info の実装上のポリシーに過ぎない。

*2:長さは大体の目安。桁位置ではないことに注意。

*3:C/C++ では */ も「線」を構成する文字と見なされるなど。

*4:インデントの深さがそのまま見出しレベルとなるような言語(Ruby や Python など)ではインデントの深さ + 3 となり、それ以外では 5 または 6 に固定される。Vim script では関数の見出しレベルが 4 であり、インデントされたコメント見出しはすなわち関数定義の中にあると見てそれより低い 5 となる。

2010-07-20

シェルを求めて三千里〜ほら貝調律編〜

タイトルだけ見ても何のことやらわからないと思いますが…… ほら貝というのは Conque のことです。(余談参照)

シェルを求めて三千里〜悠久のvim編〜」の続編です。導入以来ぼちぼちと固めてきた Conque の設定を晒してみます。


端末エミュレータとして Conque はよくできたプラグインなのですが、作成した端末バッファを管理する機能などはないため、

  • シェルを出したり隠したり
  • 複数のシェルを管理する

といった機能を自分で補っています。

端末バッファは再利用する

Conque の端末バッファ:ConqueTerm などで作成したバッファ)では、作成時に起動したプロセスは一度起動したら最後、終了後もゾンビプロセスとして残り続けます。これは Vim を終了するまで回収されません。よって、ゾンビを大量生産しないために、端末バッファは基本、一度作成したら Vim を終了するまで削除せず、可能な限り使い回します。上記設定では端末バッファと結び付けるプロセスをシェルに固定し、ページャや tail -f などが必要なら、シェルから起動するようにしています。シェルを介してプロセスを起動すれば終了ステータスの回収はシェルがやってくれるため、プロセスの起動と終了を繰り返すうちにゾンビが増えていくといったことは起こりません。(一方、一度起動したシェルとは一蓮托生を決意します)*1

H でシェル1を呼び出します。シェル2〜9については <Space>sh でシェルを作成し、<Space>2〜9 で呼び出します。

端末バッファは謙虚さが大事

端末バッファは番号を指定して呼び出せるので、バッファリストからは外してあります。:bnext などでバッファをローテーションするときにシェルが表示されて挿入モードに入る(次節参照)のがうっとうしいのでこのようにしています。*2

常時 Insert mode*3

端末バッファはシェルに結び付けられているので基本挿入モードしか使いません。なので、BufEnterstartinsert! しています。バッファの切り替え、バッファを隠す、といったことも挿入モードから抜けずにできるように、変数 g:ConqueTerm_CWInsert1 に設定し、一連のキーマップを conque_term の filetype plugin にて設定しています。

<C-w><C-d> でシェルを隠します。

Vim からシェルを使う流れ

大体こんな感じです。

H でシェル1を呼び出す、または <Space>sh でシェルを作る
 ↓
使い終わったら <C-w><C-d> で隠す
 ↓
必要になったら H または <Space>1〜9 でシェルを呼び出す
 ↓
使い終わったら <C-w><C-d> で隠す
 :
今後の課題
  • 特定のシェルで任意のコマンドを実行する関数とかコマンドとか
  • それを使って特定プロセスの起動までをキーマップにする

などなど。


余談

当初 Conque の意味を conquer(征服する)と勘違いして、「すごい挑戦的な名前だなー、vimshell に喧嘩売ってるぞ」と思っていましたが、ググってみるとほら貝の写真がヒットして氷解。Conque というのはフランス語でほら貝のことでした。どうやら、shell とかけた命名になっているようです。

( ・∀・)つ〃∩ ヘェーヘェーヘェー

*1:誤って <C-d> でシェルを終了してしまうと事実上そのバッファは以後使用不能となるので、EOF でシェルが終了しないよう起動時のオプションIGNORE_EOF (-7) を指定しています。

*2:Conque はデフォルトでこれをやってくれないので、:bnext を多用する人はこれをやらないと端末バッファが邪魔で仕方ないはず。

*3:常時挿入モード、と書いてなんだか恥ずかしくなって一部を英語にしてみたがやっぱり恥ずかしい(;^ω^) 汚れた大人になってしまったお……

2010-07-15

USConfig 機能解説 -- テーマを変更する

重要なお知らせ

USConfig の開発は終了しました。(2011-01-11)


の機能解説編その2。テーマ機能について。

USConfig が表示する設定ダイアログは、デフォルトでは黒とグレーを基調とした配色*1になっています。

しかし、スクリプトが @include しているページによっては、この配色がふさわしくない場合があります。例えば、青を基調とした配色のページであれば、設定ダイアログの配色も青を基調としたものにしたいところです。

ダイアログのスタイルは dialog()オプション引数に css を設定することでも変更できます*2が、もっと大雑把に「青っぽく」「紫を基調に」といった指定ができると便利です。

そこで USConfig では、表示するダイアログの配色を簡単に変更できるように、dialog()オプション引数でダイアログのテーマを設定できるようになっています。

  dialog(
    "Title",
    { width: 500, height: 400, theme: 'blue' },
    section(...),
    section(...)
  );

これにより、ダイアログの配色を簡単に変えられます。

f:id:h1mesuke:20100714214758p:image

用意されているテーマの一覧は Wiki を参照して下さい。

新しいテーマを定義して使うこともできます。その方法についてはサンプル samples/themes.user.js を、テーマのフォーマットについては Wiki を参照して下さい。

*1:これは先人である GM_config の配色に倣いました。移行しても違和感がないようにとの配慮です。

*2:USConfig ではダイアログ上のすべてのラベル、コントロールに id と class を割り振っています。