torikatsu923.dev

サイト内検索

    【tmux】prefixを押したときにHammerspoonで英字入力に切り替える設定

    macOS で日本語入力のまま tmux の prefix を押すと、次のキーが日本語入力で文字として入力され、tmux を操作できません。prefix を押したときに Hammerspoon で英字入力へ切り替える設定と、変換中でも prefix が tmux に届くようにした工夫を紹介します。

    はじめに

    こんにちは、とりかつ(@torikatsu923)です。

    筆者は macOS の Alacritty で tmux を使用しています。日本語入力のまま tmux の prefix を押すと、次に押したキーが日本語入力で文字として入力され、tmux を操作できません。

    そこで、prefix を押したときに、Hammerspoon で英字入力へ切り替える設定をしました。この設定で、文字の変換中でも prefix で tmux を操作でき、prefix のたびに英数キーを押す手間が無くなりました。

    この記事では、この設定と、設定に至るまでの背景と工夫を紹介します。

    prefix を押したときに英字入力へ切り替える Hammerspoon の設定

    筆者は tmux の prefix を C-t にしています。以下は、筆者の ~/.hammerspoon/init.lua から C-t を処理する部分を抜き出した設定です。全文はGitHubにあります。

    ResendingPrefix = false
    
    function handleEvent(event)
        local keyCode = event:getKeyCode()
        local flags = event:getFlags()
    
        if keyCode == hs.keycodes.map['t'] and flags.ctrl and not flags.cmd and not flags.alt and not flags.shift then
          if ResendingPrefix then
            ResendingPrefix = false
            return false
          end
          local front = hs.application.frontmostApplication()
          if front and front:name() == "Alacritty" and hs.keycodes.currentMethod() ~= nil then
            hs.eventtap.keyStroke({}, 'eisu', 0)
            hs.timer.doAfter(0.02, function()
              ResendingPrefix = true
              hs.eventtap.keyStroke({'ctrl'}, 't', 0)
            end)
            return true
          end
          return false
        end
    
        return false
    end
    
    Eventtap = hs.eventtap.new({hs.eventtap.event.types.keyDown}, handleEvent)
    Eventtap:start()

    Alacritty が前面で、日本語入力のときに C-t を押すと、英数キーで英字入力に切り替えてから C-t を送信し直します。英字入力のときと、Alacritty 以外のアプリでは、C-t をそのまま通します。

    この設定を ~/.hammerspoon/init.lua に追記し、Hammerspoon の設定を読み込み直してください。Hammerspoon のインストールと初期設定は、公式サイトの案内を参照してください。ターミナルが Alacritty でなければ、"Alacritty" を使用しているターミナルのアプリ名に変えてください。prefix が C-t 以外の Ctrl との組み合わせなら、2 か所の 't' をそのキーに変えてください。

    設定に至るまでの背景と工夫

    prefix の次のキーが日本語入力で文字として入力される問題

    筆者は C-t → h で左のペインへ移動するようにしています。しかし、日本語入力のまま C-t → h と押すと、ペインは移動せず、h が日本語入力で文字として入力されてしまいます。

    prefix の前に英数キーを押せば英字入力に切り替わりますが、prefix のたびに押すのは手間です。そこで、macOS のキー入力を Lua で処理できるHammerspoonで、prefix を押したときに英字入力へ自動で切り替えることにしました。

    最初に書いた、英数キーを送信するだけの設定

    Hammerspoon では、キーを押すたびに呼び出される関数を登録できます。最初は、この関数で C-t を受け取ったら英数キーを送信し、C-t はそのまま tmux へ通すようにしていました。macOS のテキスト入力欄では、C-t をカーソルの前後の文字の入れ替えに使います。そのときに英字入力へ切り替わらないように、英数キーを送信するのは Alacritty が前面のときに限っていました。

    変換中の C-t が tmux に届かない問題

    最初の設定で、未確定の「あああ」がある状態から C-t → h と押すと、ペインは移動せず、あああh と入力されました。画面収録をコマ送りすると、C-t を押す直前の「あああ」には下線と変換候補が表示されており、まだ変換中でした。

    C-t は、英数キーで「あああ」が確定するより先に、まだ変換中の日本語入力に届き、tmux には届きませんでした。そのあと英数キーで「あああ」は確定しましたが、tmux は C-t を受け取っていないので、h はそのまま入力されました。

    変換中の C-t が tmux に届かない問題への対策

    未確定の文字が無くなってから送信すれば、C-t は tmux に届きます。そこで、日本語入力のときは押された C-t を破棄し、英数キーで未確定の文字を確定して英字入力に切り替えてから、C-t を送信し直すようにしました。設定の節のコードは、この対策を入れた後のものです。

    日本語入力かどうかは、hs.keycodes.currentMethod() で判定しています。英字入力のときは nil が返るので、C-t をそのまま通すようにしています。

    hs.eventtap.keyStroke は、キー入力を送信するとすぐに処理が戻り、日本語入力による確定と英字入力への切り替えはその後に進みます。そのため、送信し直す C-t を変換中の日本語入力が受け取らないように、英数キーを送信してから 0.02 秒待って C-t を送信しています。0.02 秒は人が次のキーを押すまでよりずっと短い待ちです。測って決めた値ではないので、たまに失敗するようなら延ばすつもりです。

    送信し直した C-t も、同じ関数が受け取ります。0.02 秒のうちに英字入力への切り替えが終わっていなければ、送信し直した C-t でまた英数キーと C-t を送信してしまいます。そこで、送信し直す直前に ResendingPrefix を true にし、次に受け取った C-t はそのまま通しています。

    これにより、未確定の「あああ」がある状態から C-t → h と押しても、左のペインへ移動できました。

    おわりに

    この記事では、tmux の prefix を押したときに、Hammerspoon で日本語入力から英字入力へ切り替える設定を紹介しました。この設定によって、日本語入力のままでも、prefix で tmux を操作できました。

    よかったら試してみてください。