home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/vim/「Vimを使ってくれてありがとう」, "Thanks for flying Vim" の消去

技術/vim/「Vimを使ってくれてありがとう」, "Thanks for flying Vim" の消去

技術 / vim / 「Vimを使ってくれてありがとう」, "Thanks for flying Vim" の消去
id: 1110 所有者: msakamoto-sf    作成日: 2012-10-08 16:55:14
カテゴリ:

puttyやTerminalなど端末エミュレータ上でvimを起動し、終了させると、端末エミュレータ自身のウインドウタイトルが「Vimを使ってくれてありがとう」(英語表記では "Thanks for flying Vim" ) になってしまい、元の、例えばカレントディレクトリなどの表示に戻らない現象が発生する、場合があります。
自分の場合は以下の環境で発生しました:

Win7SP1日本語版
$ cygcheck -c cygwin bash mintty vim
Cygwin Package Information
Package              Version        Status
bash                 4.1.10-4       OK
cygwin               1.7.16-1       OK
mintty               1.1.1-1        OK
vim                  7.3.646-1      OK

これをどうにかして元の表記に戻したい・・・ということでネット上では既に阿鼻叫喚の地獄絵図が繰り広げられていたらしいですが、今のところ勝者が誰もいないようです。

結論から言うと、vim単体で元に戻す方法は現時点では見つかりませんでした。vimを起動したシェル側で、vim終了後に元に戻して上げてください、あるいは後述のtitleoldを適当にセットアップしてvimを起動してください。例えばcygwinであれば、 技術/Windows/Cygwin/minttyのタイトルをcdやpwdで変更する にまとめたようにcdやpwd実行時にminttyのタイトルも更新するようにしておき、vim終了後にpwdなどでタイトルを更新する、というように運用で回避します。
または"set notitle"をvimrcに書いておき、vimがxtermのウインドウタイトルを変更しないようにしてください。

少し原理的な部分について調べてみますと、そもそも「グラフィカルな端末エミュレータのウインドウタイトルを変更する」とはどういうことか?これは一気にPOSIXとかSUSまで遡った、端末の機能にアクセスするtermcapの世界の話になってしまうわけです。
unix系でグラフィカルな端末エミュレータの事実上の標準はxtermになります。ということは、xtermのtermcapにウインドウのタイトルを変更する機能があるわけです。("termcap"という用語の使い方はかなりいい加減にしてます。とりあえず、エスケープシーケンスに続けて独自のコマンドを出力することでxtermのGUI要素を操作できる、と覚えておけばOKかと。)
ちなみにxtermの制御シーケンスについて、以下の資料を見つけました。

技術/Windows/Cygwin/minttyのタイトルをcdやpwdで変更する でminttyのウインドウタイトルを変更するのに

echo -ne "\e]2;$t\007"

というechoを使いましたが、これは

\e]2; -> 上記制御シーケンスの資料ではoscに当たります。
\007 -> octet表記でASCII制御コードのBELに当たります。

これをxtermの制御シーケンスに当てはめると、ちょうど

osc Ps ; Pt BEL
Ps -> 2が "Change Window Title to Pt"に当たります。
Pt -> 変更するWindowタイトルの文字列

でビンゴ!とヒットしてるわけです。

本記事と若干関連していて、vimの話題で「"set title"してるのに端末エミュレータ側のウインドウタイトルが変更されない」という話もあるらしく、これなどはまさしくvim側が出力しているウインドウタイトル変更用の制御シーケンスが、端末エミュレータ側の種類が異なるなどして無視されているものと推測されます。この場合の解決方法は一応vim側で用意されていて、t_tsとt_fsにその端末エミュレータ用のウインドウタイトルの変更開始・終了用制御シーケンスを割り当てます。詳しくは":help t_ts", ":help t_fs"や以下の参考リンクを参照してください。

vimではウインドウのタイトル変更について以下のオプションが関連します。

title <> notitle
titleold
titlestring
titlelen

基本的に "set title" されると、"titlestring"がウインドウタイトルに設定され、vim終了時にtitleoldに戻されます。
このtitleoldが本記事でも問題となっている "Thanks for flying Vim" というわけで、":help titleold"で見てみると

This option will be used for the window title when exiting Vim if the
original title cannot be restored.  Only happens if 'title' is on or
'titlestring' is not empty.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.

とあります。「オリジナルのタイトルに戻せなかった場合に、titleoldに変更する」と読めます。じゃぁ「オリジナルのタイトルに戻せなかった場合」ってどんな場合か・・・ってこればっかりはvimのソースコードを追うしか無いんですが、もうそんな余力はありません。今日一日ずっとこれとか、派生して 技術/Windows/Cygwin/minttyのタイトルをcdやpwdで変更する の調査に費やしてるわけです。

視点を変えれば、「オリジナルのタイトルに戻そうとしている」ことは確かです。じゃぁオリジナルのウインドウのタイトルはどうやって取得するの?というところですが、ここでもxtermの制御シーケンスが関連してくるわけです。
ウインドウタイトルを変更する制御シーケンスがあるので、その逆に「現在のウインドウタイトルを取得する制御シーケンス」もあり得る訳です。

CSI Ps ; Ps ; Ps t
...
Ps = 21 → Report xterm window’s title. Result is OSC l label ST
Ps = 23 ; 2 → Restore xterm window title from stack.

このあたりがそれっぽいです。が、ちょっとbash上からこれらの制御シーケンスを叩いてみたのですが何も表示されず・・・もしかしたら使い方の時点で間違ってるかもしれませんが。

ひとまず事実としてわかっていることは、どうやらvimは、現在の端末エミュレータのウインドウタイトルを取得するのに失敗する場合があり、それが原因でvim終了時に"titleold"のデフォルト値である "THanks for ..." に強制的に戻してしまう、というのが事の顛末のようです。

まぁこのあたりの問題ってvimだけじゃなくて、端末エミュレータのウインドウタイトルを変更するようなコマンドラインプログラムはたくさんありますので、似たような問題はそれら全般に渡って潜んでいる、とも考えられます。(screenとかtmuxなんかもその種の問題と関わりが出てきそうです。)
となれば、1ユーザとしてはvimだけで局所的に解決するのではなく、もっとお手軽に・汎用的に解決したいところです。
ということで一番手っ取り早いのがシェル側でpwdとかcdすることでカレントディレクトリをウインドウタイトルに設定することで、そのcygwin + minttyバージョンが 技術/Windows/Cygwin/minttyのタイトルをcdやpwdで変更する となったわけでした。

ただ、シェル側で解決する方法を採ったとしても、vim終了時点ではやっぱり "Thanks for..." が残ってしまします。これをクリアするにはユーザが明示的に一度cdやpwdを実行しなければなりません。
中途半端でも良いので、とりあえずvim起動時のディレクトリ名とかに戻したい場合は、以下のように.vimrcを設定します。

let &titleold=expand("%:p:h")
set title

この例では編集中ファイルのディレクトリ部分をtitleoldに設定しますので、少なくとも何らかのディレクトリ情報はウインドウタイトルに残せます。(この2行にたどり着くまでに6時間以上費やしました (´Д⊂ヽ)
vimscriptの腕に覚えのある方は、もっと色々とカスタマイズすることで、もしかしたらシェル側のpwdやcdとうまく連携出来るかも・・・しれません・・・。

ということで冒頭に書いた結論に戻りますと、vimでは「現在の端末エミュレータのウインドウタイトルの取得」に失敗することがあり、その場合にvim終了時に"titleold"オプションの値にウインドウタイトルを変更します。これのデフォルト値が"Thanks for..."になります。現在のウインドウタイトルの取得がなぜ失敗するのか、どうすれば正常に端末エミュレータとインタラクトして取得できるようになるのかは現時点では調べきれませんでした。
運用上の回避方法として、以下の様な方式をmsakamoto-sfは採用しました。

  1. ひとまずvimrcでtitleoldを調整し、最低限度の情報はウインドウタイトルに残して終了するようにする。
  2. シェル側でpwdやcd実行時に端末エミュレータのウィンドウタイトルを適宜変更するようにする。

以下、調査時に参照したリンクです。

「vimを使ってくれてありがとう」に巻き込まれた人たちの阿鼻叫喚地獄絵図:

vimscriptの勉強:

Macだと"TITLE"環境変数が使えるようです:



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2012-10-08 16:55:34
md5:24ae5f101f2e8ebfc790d79c229f8bbe
sha1:45731079e47fda92c1580ba143e157c428bb7afe
コメント
コメントを投稿するにはログインして下さい。