Hammerspoon(https://www.hammerspoon.org/) 是一款基于 Lua 脚本的自动化工具,它能够让 Mac 上的各种操作变得更加智能和自动化。无论是自动化日常任务,还是创建复杂的自定义快捷操作,Hammerspoon 都能轻松实现。它通过提供对系统事件的访问、窗口管理、键盘快捷键、自定义菜单等功能,帮助我们大大提高工作效率。
Hammerspoon 的核心特点
- Lua 脚本引擎
Hammerspoon 的最强大之处在于它使用 Lua 脚本,这意味着我们可以通过编写 Lua (Lua还是比较简单易学的)代码来控制 Mac 上的几乎所有操作。无论是简单的文件操作,还是复杂的自动化任务,都可以通过 Hammerspoon 的脚本来实现。 - 高度自定义
用户可以通过 Lua 脚本编写自己想要的功能,灵活性极高。例如,可以为特定的应用程序创建快捷键、设置自动化任务、控制窗口的大小和位置等。Hammerspoon 还允许你将各种任务结合起来,以实现更为复杂的自动化流程。 - 与 macOS 深度集成
Hammerspoon 不仅可以操作系统的基本功能(如窗口管理、键盘操作),还能够与其他应用程序进行交互。比如,它可以控制 iTunes、Spotify 等音频应用的播放,或者让它与外部设备进行连接。 - 丰富的插件支持
Hammerspoon 本身并没有过多的限制,它拥有丰富的社区支持和插件库。用户可以安装各种插件来扩展功能,像是自动化桌面布局、快速启动应用程序、控制系统亮度等,几乎可以满足各种需求。
如何安装和配置 Hammerspoon?
-
安装
你可以通过 Hammerspoon 官网(hammerspoon.org)下载安装包,或者通过 Homebrew 进行安装:brew install hammerspoon
-
配置
安装完 Hammerspoon 后,你需要编辑配置文件来编写脚本。默认的配置文件位于~/.hammerspoon/init.lua。你可以通过文本编辑器打开该文件,并开始编写 Lua 脚本。 3. 加载配置
配置文件编辑完成后,你可以重新加载配置,使修改立即生效。点击 Hammerspoon 图标,在菜单中选择“Reload Config”即可。
一些使用场景分享
根据不同的应用自动切换输入法
可以写一个脚本来实现自动切换输入法,切换窗口的时候自动选择对应的输入法。
例如,我想在 kitty 这个应用中总是使用英文输入法,在微信这个应用中总是使用中文输入法,可以使用下面的代码来实现。
local changeInputMethod = function(config)
local layout = config.layout
local method = config.method
local currentLayout = hs.keycodes.currentLayout()
local currentMethod = hs.keycodes.currentMethod()
if currentLayout == layout and (currentMethod == method) then
return
end
hs.keycodes.setLayout(layout)
if method ~= nil then
hs.keycodes.setMethod(method)
end
end
-- 注意如果不知道 app 对应id 是什么,可以直接在下方监听windowFocused事件的代码中把 app 对应的 id直接打印出来
-- 输入法对应的 layout 和 method 也是同样的道理
local inputMethodConfig = {
"net.kovidgoyal.kitty"={layout="ABC","method"=nil},
"com.tencent.xinWeChat":{layout="Pinyin - Simplified","method"="Pinyin - Simplified"}
}
local getAppBundleId = function(win)
return win:application():bundleID()
end
-- 监听应用程序窗口的 windowFocused 方法, 这样当某个应用程序窗口处于 focused 状态的时候,会触发这里的回调
hs.window.filter.default:subscribe(hs.window.filter.windowFocused, function(win)
local appName = getAppBundleId(win)
print("AppName :", appName)
local config = inputMethodConfig[appName]
if config == nil then
return
end
changeInputMethod(config)
end)
tips:
mac 系统中有 layout 和 method 的概念,layout 指的是键盘的布局,例如,英文键盘,中文键盘,日文键盘,method 指的是输入法。
一个 layout 中可以安装多种输入法,所以设置的时候 layout 和 method 都要设置,不然有可能无法生效。
那么,如何获取当前的输入法的名字以及对应的 layout 呢,写个代码获取一下就好了,下面的代码中就是获取当前的 layout 和 method,然后打印在控制台上面local getCurrentInput = function () local currentLayout = hs.keycodes.currentLayout() local currentMethod = hs.keycodes.currentMethod() print("Current layout:", currentLayout, ", Current method:", currentMethod) end
hammerspoon 的控制台打开方式:点击 menu 上的 hammerspoon 图标,选择 console。
自定义快捷键
-
设置快捷键实现快速把当前应用程序的窗口移动到下一个显示器,适合多显示器用户
hs.hotkey.bind({ "cmd", "alt", "ctrl" }, "n", function() local win = hs.window.focusedWindow() local screen = win:screen() win:move(win:frame():toUnitRect(screen:frame()), screen:next(), true, 0) end)
-
当前程序全屏/取消全屏
hs.hotkey.bind({"cmd","alt","ctrl"}, "O", function() local win = hs.window.focusedWindow() if win:isFullScreen() then -- 全屏状态取消全屏 win:setFullScreen(false) else -- 进入全屏 win:setFullScreen(true) end end)
-
重新映射快捷键
mac 中 `cmd+`` 可以在同一个应用程序的不同的窗口之间互相切换,在有的键盘上面,这个快捷键不好触发,我们可以重新映射一个新的快捷键hs.hotkey.bind({"cmd","alt","ctrl"}, "i", function() hs.eventtap.keyStroke({ "cmd" }, "`") end)
-
通过快捷键快速启动应用程序
Hammerspoon 允许你设置全局快捷键,甚至是针对特定应用程序的快捷键。例如,你可以创建一个快捷键来启动特定的应用,或者为常用的命令设置快捷键。hs.hotkey.bind({"cmd", "shift"}, "N", function() hs.application.launchOrFocus("Notes") end)
-
设置vim风格的键位移动窗口
local mods = { "cmd", "alt", "ctrl" } local function left_move_window() local win = hs.window.focusedWindow() local f = win:frame() f.x = f.x - 40 win:setFrame(f) end -- 按组合键 cmd+alt+ctrl+h实现向左移动窗口 hs.hotkey.bind(mods, "H", left_move_window, nil, left_move_window) local function right_move_window() local win = hs.window.focusedWindow() local f = win:frame() f.x = f.x + 40 win:setFrame(f) end -- 向右移动窗口位置 hs.hotkey.bind(mods, "L", right_move_window, nil, right_move_window) local function down_move_window() local win = hs.window.focusedWindow() local f = win:frame() f.y = f.y + 40 win:setFrame(f) end -- 向下移动窗口位置 hs.hotkey.bind(mods, "J", down_move_window, nil, down_move_window) local function up_move_window() local win = hs.window.focusedWindow() local f = win:frame() f.y = f.y - 40 win:setFrame(f) end -- 向上移动窗口位置 hs.hotkey.bind(mods, "K", up_move_window, nil, up_move_window)