tmuxでiTermのimgcatを使う

iTermの拡張コマンドであるimgcatはtmux上で実行すると挙動がおかしくなる。 これはどうやらtmuxではpane分割があるため、widthやheightがうまく計算できないので描画がおかしくなってしまうらしい。

https://github.com/Rasukarusan/blog-assets/blob/master/tmux-imgcat/demo1.gif?raw=true
tmuxでimgcatを実行したときの挙動。一瞬だけ表示されて消える。

ただ、どうやらimgcatの実行後、何らかの方法で処理をブロッキングすることで描画がちゃんとされることがわかった。

https://github.com/Rasukarusan/blog-assets/blob/master/tmux-imgcat/demo2.gif?raw=true
imgcat実行後、処理をブロッキングした場合のimgcatの挙動

画像はTerminalに残らず、catではなくlessっぽい挙動になってしまうが、十分使える感じはある。

方法

例えばreadコマンドを使って処理をブロッキングすることができる。

imgcat_for_tmux() {
  imgcat "$1"
  # ENTERで画像表示を終了できる。
  read && clear && exit
}
alias imgcat='imgcat_for_tmux'

もしくはsleepコマンドで処理をブロッキングし、trapコマンドでCtrl-cをフックしてもいい。

imgcat_for_tmux() {
  trap 'clear && exit' SIGINT
  imgcat "$1"
  sleep 100
}

ただいちいちCtrl-cするのも面倒だし、trap仕掛けるのもアレなのでreadが一番シンプルだと思う。

引数やカーソル位置等を諸々考慮した版を一応載せておく。

_imgcat_for_tmux() {
    # @See: https://qastack.jp/unix/88296/get-vertical-cursor-position
    get_cursor_position() {
        old_settings=$(stty -g) || exit
        stty -icanon -echo min 0 time 3 || exit
        printf '\033[6n'
        pos=$(dd count=1 2> /dev/null)
        pos=${pos%R*}
        pos=${pos##*\[}
        x=${pos##*;} y=${pos%%;*}
        stty "$old_settings"
    }
    command imgcat "$1"
    [ $? -ne 0 ] && return
    [ ! "$TMUX" ] && return
    get_cursor_position
    # 2行分画像が残ってしまうためtputで再描画判定させて消す
    read && tput cup `expr $y - 2` 0
}

色々問題はある

Terminalのサイズが小さすぎると画像が表示されないとか、画面の下の方で実行すると描画がおかしくなったりと、色々問題はあるけど全く使えないよりはいいかなっていうレベル。
とりあえずtmuxでもimgcat使えるじゃん!!って嬉しかったのでこの世に残しておく。