👻

Neovim + oil.nvim + Weztermで頑張って画像を表示する

2024/04/24に公開

TLDR

1.gif
oil.nvimで画像を選択し、Weztermで画像を表示。 画像はこちらから

  • Neovimで画像と向き合う方法を紹介
  • Quicklookを呼び出す方法は簡単
  • 今回はWeztermとoil.nvimをフル活用して、Terminal上で画像を表示する方法を紹介をメインに紹介

はじめに

Vimmerたるもの、普段はTerminalに引きこもっているものです。
特にVim(Neovim)上で作業をすることが多いはず。

しかし、Terminalが苦手なファイルも存在します。
ご存じ、画像ファイルです。

これまで、自分は画像ファイルを見たいときは

  • openコマンドで画像を開く(MacならPreviewで開く)
  • open .でFinderを開いて画像を見る

としてきましたが、やはり画像を見たいためだけにFinderを立ち上げたりアプリを起動、終了するのは面倒です。

そこで、これらを改善することにしました。

本記事では、ファイラとしてoil.nvimを使った例を紹介しますが、他のファイラでも同様のことができるはずです。
https://github.com/stevearc/oil.nvim

また、設定はluaで書かれています。

Step 1: Quicklookを使う

macOS には標準でQuicklookという機能があります。
みなさん、一度はお世話になったことのある、Finderでファイルを選択してスペースキーを押すと、ファイルの中身をプレビューできるあれです。

実は、TerminalからもQuicklookを使うことができます。

qlmanage -p hoge.png

つまり、これをVim(Neovim)から呼び出せば、画像をプレビューできるはずです。

https://github.com/ryoppippi/dotfiles/blob/359609ea44ddbc7b4b621aaea4ea5d4a9a06e88e/nvim/lua/core/utils.lua#L52-L55
https://github.com/ryoppippi/dotfiles/blob/359609ea44ddbc7b4b621aaea4ea5d4a9a06e88e/nvim/lua/plugin/oil/actions.lua#L24-L31
https://github.com/ryoppippi/dotfiles/blob/359609ea44ddbc7b4b621aaea4ea5d4a9a06e88e/nvim/lua/plugin/oil/init.lua#L41

これで、oil.nvimで画像を選択し、Quicklookを呼び出すことができますね。

0.gif
oil.nvimで画像を選択し、Quicklookを呼び出す

Step 2: Weztermを分割&画像表示

さて、Quicklookの方法にもまだ改善点があります。

  • いちいちEscキーを押してQuicklookを閉じるのは面倒
  • QuicklookにFocusが当たってしまうので、他のファイルを選択できない

というわけで、本命択はTerminal上で画像を表示したいわけです。

これまで、Vim/Neovimで画像を表示する試みはいくつかありました。

https://github.com/kjuq/sixelview.nvim/
https://zenn.dev/vim_jp/articles/358848a5144b63

しかし、先の記事にも触れられているように、いくつか課題があります。

  • 画像のサイズをいい感じに調整するのが難しい。
  • gifをポンと渡しても再生されない。

そのため、今回はTerminalの機能を使って画像を表示することにしました。

自分の使用しているWeztermには、画像を表示する機能があります。
https://wezfurlong.org/wezterm/imgcat.html
https://wezfurlong.org/wezterm/cli/imgcat.html

これにより、任意の画像をTerminal上で表示することができます。

またWeztermには wezterm cliコマンドがあり、Weztermの動作をコマンドで制御することができます。

https://wezfurlong.org/wezterm/cli/cli/index.html

これらをフル活用して、次のような設定を行いました。

(以下、この機能のことをWezterm Previewと呼びます)

oil.nvimでgpを押すとWezterm Previewを起動

https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/init.lua#L40

現在のNeovimが開かれているPane IDを取得

現在のPane IDを取得するには、環境変数 WEZTERM_PANE を使います。

https://wezfurlong.org/wezterm/cli/cli/spawn.html#synopsis
https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L34-L41

Weztermの画面を分割して、分割されたpaneのidを取得

Weztermで画面を分割するには、wezterm cli split-paneコマンドを使います。
このコマンドの戻り値には、分割されたpaneのidが含まれています。
https://wezfurlong.org/wezterm/cli/cli/split-pane.html
https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L48-L66
https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L140

もしすでにpaneが分割されている場合は、そのpaneのidを取得します。
この時は wezterm cli list --format=json コマンドを使います。

https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L91-L117

Neovimが開かれているPaneにFocusを戻す

https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L43-L45
https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L153

oil.nvimでカーソルが動くたびに、Wezterm Previewを更新

まず、カーソルが選択しているファイルの情報を取得します。
https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L148-L151

そしてその情報を元に、もし新しいファイルであれば、WeztermのPreview用のPaneにコマンドを送って実行します。
この時

  • ディレクトリであれば、lsコマンド
  • 画像ファイルであれば、wezterm imgcatコマンド
  • そのほかはbatコマンド

を実行するようにします。

https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L151-L183

Weztermでpaneにコマンドを送るには、 wezterm cli send-text コマンドを使います。
https://wezfurlong.org/wezterm/cli/cli/send-text.html
https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L77-L89

oil.nvimが終了したら、Wezterm Previewを閉じる

oil.nvimの現在のバッファが閉じられたら、WeztermのPreview用のPaneも閉じるようにします。

https://wezfurlong.org/wezterm/cli/cli/kill-pane.html
https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L201-L211
https://github.com/ryoppippi/dotfiles/blob/6c587dfbc3773a5adfff661f0943e0edf9288a7f/nvim/lua/plugin/oil/actions.lua#L68-L75

コードの全体像

全体像

動作は冒頭のGIFをご覧ください。

まとめ

今回は、oil.nvimとWeztermを使って、Terminal上で画像を表示する方法を紹介しました。
まだプラグインとして公開してないのですが、要望があれば公開するかもしれません。

今回はWeztermの機能をフル活用しましたが、他のTerminal Emulatorでも同様のことができるはずです。
ぜひみなさんも、自分の環境に合わせて設定してみてください。

Discussion