@ryoppippi

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

24 Apr 2024 ・ 8 min read


Note

この​記事はVim 駅伝の​ 4/24 の​記事です。

TLDR

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

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

はじめに

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

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

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

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

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

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

Note

参考までに、​筆者の​環境は​以下の​とおりです。

 neofetch
                    'c.          ryoppippi@ryoppippi.local
                 ,xNMM.          -------------------------
               .OMMMMo           OS: macOS 14.4.1 23E224 arm64
               OMMM0,            Host: Mac15,6
     .;loddo:' loolloddol;.      Kernel: 23.4.0
   cKMMMMMMMMMMNWMMMMMMMMMM0:    Uptime: 7 days, 2 hours, 15 mins
 .KMMMMMMMMMMMMMMMMMMMMMMMWd.    Packages: 1 (brew)
 XMMMMMMMMMMMMMMMMMMMMMMMX.      Shell: fish 3.7.1
;MMMMMMMMMMMMMMMMMMMMMMMM:       Resolution: 2560x1080, 1512x982, 1080x1920
:MMMMMMMMMMMMMMMMMMMMMMMM:       DE: Aqua
.MMMMMMMMMMMMMMMMMMMMMMMMX.      WM: Rectangle
 kMMMMMMMMMMMMMMMMMMMMMMMMWd.    Terminal: WezTerm
 .XMMMMMMMMMMMMMMMMMMMMMMMMMMk   CPU: Apple M3 Pro
  .XMMMMMMMMMMMMMMMMMMMMMMMMK.   GPU: Apple M3 Pro
    kMMMMMMMMMMMMMMMMMMMMMMd     Memory: 5014MiB / 36864MiB
     ;KMMMMMMMWXXWMMMMMMMk.
       .cooc,.    .,coo:.

本記事では、​ファイラと​して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

コードの​全体​像

全体像

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

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

まとめ

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

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

comment on bluesky / twitter
CC BY-NC-SA 4.0 2022-PRESENT © ryoppippi