大昭Graham

Home Essays About


Hammerspoon:斗宗强者,恐怖如斯

2021-10-05

*

Hammerspoon 是一款 macOS 效率软件,开源,稳定,强悍。

我最喜欢 Hammerspoon 的,是它能自动在后台处理应用切换细节,让工作更顺畅。比如:

  • 窗口跳到微信,自动切换输入法中文,跳到词典,自动切为英文;
  • 键入 ` 符号后,输入法自动切为英文,键入 [[]] 链接符号后,自动切换为中文;
  • PDF Expert 有新窗口打开,自动调整窗口尺寸到设定大小;
  • 打开 TaskPaper,自动刷新 taskpaper-repeat 的 JavaScript 脚本
  • Google Chrome 打开 WorkFlowy 网站页面,为这一页面载入单独一套快捷键,切到别的页面或应用,再加载回正常快捷键;
  • 打开 Anki 的添加卡片窗口时,自动清除剪贴板内容格式,设置为纯文本;

…诸如此类。

都不是什么大事,自己敲键盘也可以调,但有了 Hammerspoon,这些事我慢慢就会忘记,Hammerspoon 会在后台处理好一切。从一个进程切换到下一个动作,不会被工具和流程切换干扰,没有这里那里细节上的滞涩,注意力不被打断。

这是 Hammerspoon 于我最大的意义。

以下是几个常用功能的代码实现。

*

从 AppleScript 调用 Hammerspoon:

先在 init.lua 文件,开放 AppleScript,加上 hs.allowAppleScript(true) ,再 hs reload

语法:

tell application "Hammerspoon" to execute lua code "xxx"

*

根据当前 App 自动设定输入法为中文或英文:

local function Chinese() hs.keycodes.setMethod("Squirrel") end

local function English() hs.keycodes.setLayout("U.S.") end

local appIme = {
    {'Alfred Preferences', 'en'},
    {'Anki', 'en'},
    {'CotEditor', 'zh'},
    {'Dash', 'en'},
    {'Emacs', 'en'},
    {'Eudic', 'en'},
    {'Finder', 'en'},
    {'WeChat', 'zh'}
	 -- etc.
}

function setImeForFocusedApp(appName, eventType, appObject)
    if (eventType == hs.application.watcher.activated) then
        local default = true
        for index, app in pairs(appIme) do
            if app[1] == appName then
                default = false
                if app[2] == 'zh' then
                    Chinese()
                else
                    English()
                end
            end
        end
        if default then
            English()
        end
    end
end

imeWatcher = hs.application.watcher.new(setImeForFocusedApp)
imeWatcher:start()

其中,切换输入法调的是 Hammerspoon 的 hs.keycodes 模块,设置为英文输入法调用 setLayout ,中文调的则是 setMethod ,当然也可以统一调 SourceID 来实现:

hs.keycodes.currentSourceID("com.apple.keylayout.US") 

当前输入法的 sourceID 可通过 hs.keycodes.currentSourceID() 获取,参数留空即可。

*

setFrame() 设置当前窗口位置大小:

  • 先获取窗口 object,可通过 hs.window.focusedWindow() 获取
  • 再以 : 传入自身为变量,调用 hs.geometry.rect() 设置窗口

例:

win = hs.window.focusedWindow()
win:setFrame(hs.geometry.rect(975.0,171.0,780.0,918.0))
-- OR
win:move(hs.geometry.rect(975.0,171.0,780.0,918.0))

*

通过 hs.pasteboard 将剪贴板设为纯文本。

1)调用 Hammerspoon 的 hs.pasteboard.getContents() 获取内容;
2)通过 hs.pasteboard.setContents(var),将内容自动处理为纯文本,从而清除格式。

示例:

hs.pasteboard.setContents(hs.pasteboard.getContents())