MacBook Pro に Hammperspoon を導入した

マカーの仲間入り

先日、ついにMacBook Proを購入し、僕も無事マカーの仲間入りを果たした。
購入したのは、MacBook Pro 13インチ(Touch Barなし)だ。
Touch Barについては、現時点ではまだ必要性が感じられないことと、Escキーを多用する自分にとってはハードキーがなくなると精神的につらいこともあり、今回は購入を見送った。

MacBook のいいところ

なんといっても、デフォルトでシェルが使える。
Windows時代から、CygwinだのBabunだのを入れたり、自宅鯖を立ててSSHしていた自分にとっては、何の設定もせずにシェル環境が整っているmacOSは非常に良い物だ。
さっそくiTerm2を導入し、自分用の環境を整えた。
今まで育ててきたDOTFILESも、概ね良好に動作している。

不満点

しばらく使用してみて思ったのは、macOSのショートカットによるウィンドウ操作が、Windowsよりも不便だということ。

例えば、ウィンドウの切り替えはWindowsではAlt + TabmacOSだとCommand + Tabだが、macOSでは切り換えの対象がウィンドウ単位でなくアプリケーション単位になっている。

つまり、FinderやChromeなどを複数ウィンドウ開いている場合、それらをまとめて切り替えてしまう。同一アプリ内でウィンドウ切り替えを行うCommand + F1というショートカットキーもあるが、WindowsAlt + Tabに慣れきった身としては、アプリなんか関係なくウィンドウの切り替えを行いたいものだ。

また、Win + →Win + ←のような、ウィンドウを画面の左右半面に展開するといった動作も実現できない。

さらに、macOSの「ウィンドウ最大化」は言うなれば「ウィンドウ最適化」であり、画面全体にウィンドウが広がらない。Ctrl + Command + Fでフルスクリーンにはなるものの、今度はメニューバーが隠れてしまうなど、どうも思ったような挙動をしてくれない。

Hammerspoon を導入

上記のような問題を解決するために、Hammerspoonというアプリを導入した。
Hammerspoonは、設定をLuaによって記述できる、macOSの動作を自動化するためのツール。
アプリケーションやウィンドウ、ファイル、オーディオデバイス、クリップボードなど様々なものを制御できるらしいが、今回はショートカットキーによってウィンドウを操作するスクリプトを作った。

local prefix = {"cmd", "ctrl"}

-- Command + Ctrl + ↑ : フルスクリーン
hs.hotkey.bind(prefix, "Up", function()
    local win = hs.window.focusedWindow()
    local f = win:frame()
    local screen = win:screen()
    local max = screen:frame()

    f.x = max.x
    f.y = max.y
    f.w = max.w
    f.h = max.h

    win:setFrame(f)
end)

-- Command + Ctrl + ← : ウィンドウ左寄せ
hs.hotkey.bind(prefix, "Left", function()
    local win = hs.window.focusedWindow()
    local f = win:frame()
    local screen = win:screen()
    local max = screen:frame()

    f.x = max.x
    f.y = max.y
    f.w = max.w / 2
    f.h = max.h

    win:setFrame(f)
end)

-- Command + Ctrl + ← : ウィンドウ右寄せ
hs.hotkey.bind(prefix, "Right", function()
    local win = hs.window.focusedWindow()
    local f = win:frame()
    local screen = win:screen()
    local max = screen:frame()

    f.x = max.x + (max.w / 2)
    f.y = max.y
    f.w = max.w / 2
    f.h = max.h

    win:setFrame(f)
end)

-- Alt + Tab : ウィンドウ切り替え
hs.hotkey.bind("alt", "tab", function()
    hs.window.switcher.nextWindow()
end)

-- Alt + Tab : ウィンドウ切り替え(逆)
hs.hotkey.bind({"alt", "shift"}, "tab", function()
    hs.window.switcher.previousWindow()
end)

上記スクリプト~/.hammerspoon/init.luaにコピペし、Reload Configすると、コメントに書いてある通りの動作が実現できた。
ウィンドウの切り換えも、Windowsのように全てのアプリウィンドウを選択できるようになった。
アクティブなアプリによって挙動を変えるといったことも可能なようなので、今後も色々と試していきたい。

参考