つくった
画像は https://ghlinkcard.com/から生成
参考: みんなにOSSを見てもらいたい人の為に、GitHubリポジトリのOGP的画像を自動生成してくれるサービスを作った
どういうやつ?
Vim/Neovim の terminal mode で Vim/Neovim を実行すると Vim/Neovim が入れ子に起動してしまう
これを回避するには Neovim の場合は mhinz/neovim-remoteを使うとよい
Vim8 の場合でも clientserver 機能や terminal-api を利用すればよい
参考(clientserver): Vim の :terminal の中から外の Vim を操る方法
参考(clientserver): :h clientserver
参考(terminal-api): :terminal に関する小さい Tips
参考(terminal-api): :h terminal-api
しかしいずれにせよ、vim/nvim の中と外で実行するコマンドを切り替えねばならんというのは面倒である
なので、自身が vim/nvim の中なのか外なのかをよしなに判断して上記の回避策を実行してくれるツールを作成した
先行研究もあったが、Vim8 のみ対応のようだったので Neovim にも対応する形で実装してみた
参考: Vim in Vim しない :terminal
どうやってつかう?
あとは alias vim=vimalter
みたいな感じで shell の alias 登録すれば、どこでもとりあえず vim
って実行すればいい感じに vim/nvim が開く
なにをしている?
vimalter
コマンドを実行しているのは vim なのか nvim なのか shell なのか
vim/nvim は terminal mode のとき、いくつか環境変数を追加してくれているので、それを利用した
環境変数 VIMRUNTIME
に runtimepath を入れてくれているようなので(ex. VIMRUNTIME=/usr/share/nvim/runtime
)一つ上のディレクトリ(ex. /usr/share/nvim
) の部分が nvim
なのか vim
なのかで判定した
もしかすると自前で vim/nvim を build してたりするとここに vim
or nvim
が入っておらず、上手く動かないかもしれない
neovim の場合
単純に引数を nvr
コマンドに食わせて実行すればよい
vim の場合
vim は少し複雑で :term
する前に call remote_startserver('hogehoge')
を叩いているかどうかで挙動を変える必要があるremote_startserver()
は +clientserver
オプションを付けて build された vim でしか実行できない関数で、引数に指定された名前(例では hogehoge
)で vim サーバを起動するコマンドである
これが実行されていれば terminal mode では 環境変数 VIM_SERVERNAME
に hogehoge
と入っているので vim --servername $VIM_SERVERNAME --remote
file_name というコマンドを実行すれば親の vim で file_name
を開いてくれる
call remote_startserver('hogehoge')
されていない場合は環境変数 VIM_SERVERNAME
は空なので他の方法を考える必要がある
今回は terminal-api を利用した
terminal-api の詳細は先に挙げた参考資料に任せるとして、とにかく echo -e \x1b]51;[\"drop\",\"file_name\"]\x07
と terminal mode で実行すれば親の vim で file_name
に指定したファイルを開いてくれる
vim の実行ファイルを探索する
/usr/bin/vim
が vim だといつから錯覚していた?
はい、debian 系(というか update-alternatives
を使用している場合などは大抵) /usr/bin/vim
とはただのシンボリックリンクである
実態はどこにいるかは辿ってみないと分からないので雑に vim
に引数を食わせるわけにはいかない
ちゃんと現在 terminal mode で実行中の vim の実 path を辿ってやる必要がある
方法は愚直に PPID を辿って vim
または vim.basic
(debian で apt
で入れた vim の実行ファイル名はこれになる) という文字列が実行ファイル名になっているものを探すapt
でインストールされた vim の実行ファイル名は他にも vim.tiny
とかもあるが、vim.tiny
は terminal mode が使用できないので除外した
他にも実行ファイル名のパターンがあれば Issue か PR をください...!
この実装をする際 shirou/gopsutilが非常に便利だった
-tab
option
Vim の --remote
オプションは親でファイルを開く際、ファイルをウィンドウ分割して開く、という挙動となっており、個人的には --remote-tab
の挙動のほうが好みだったので -tab
オプションで制御できるようにした
弊害として、vim 側のオプションを渡す際は --
を付ける必要があるが、まあ大抵こういうコマンドはそうなってるのでいいかな、と(適当)
vim --remote-tab
だと、既存に空ファイルのウィンドウがあればそのウィンドウでファイルを開き、それ以外の場合は新規に tab を作成してそこでファイルを開く、という挙動をする
このとき困るのは terminal-api
での実装で、現状 drop
コマンド(つまり挙動としては --remote
と同じ)しか雑にファイルを開くときには使えないので --remote-tab
を真似ることはできないcall
コマンドというユーザ定義関数を呼ぶコマンドもあるにはあるが、Tapi_
で始まるユーザ定義関数しか呼べない、という制限があるため現状は未実装ということにしている
今後の予定として Tapi_
関数群を提供する Vim plugin を書いて、この挙動を実装する方針である