系统版本:macOS 10.15.7
Hammerspoon版本:0.9.81
Lua版本:5.4.0
用了一段时间的macOS后发现。有很多终端的指令需要记。常用的指令一般都不会忘。但是,一些不常用的指令,例如scp指令。所以就想要一个功能帮我记录这些常用指令的。后来引申到了想要记录一些常用的注释代码片段。
当然,我是知道这些备忘完全可以随便记录在macOS提供的备忘录中或者是写在博客里,但是,操作了一段时间后就发现了一个很大的弊端:记录、查找、修改备忘都要先打开某个应用后才能操作,往往要经过很多步骤。同时我在用的另外一个macOS神级应用Alfred里也有一个片段功能。似乎也能满足我的需求。但是,我不满意的地方是新增修改删除备忘的时候,不是很方便。需要进入设置界面才能操作。第二个问题是多台mac数据同步的问题,官方推荐Dropbox,网络问题就不说了,真心不想装多一个没用的软件。理论上是能通过git来同步配置文件的,不过不想试了,就想自己手动写一个:-)。控制权在自己手上,想怎么改就怎么改。
https://github.com/sugood/hammerspoon
│ history.json
│ init.lua
│ README.md
│ README_zh-CN.md
└─modules
│ hotkey.lua
——│ launcher.lua
——│ reload.lua
——│ snippet.lua
——│ system.lua
——│ windows.lua
在init.lua文件中插入以下代码
require "modules/snippet"
-- 添加片段(按下快捷键时做一个复制操作,并记录复制的内容到片段列表中)
hs.hotkey.bind({"ctrl", "cmd"}, "A", function ()
-- TODO
end)
-- 选取片段内容(按下快捷键时显示片段列表,点击选中的快捷键将自动粘贴)
hs.hotkey.bind({ "ctrl", "cmd" }, "V", function ()
--TODO
end)
hs.eventtap.keyStroke({ "cmd" }, "C")
-- 将备忘插入备忘录列表中
table.insert(history, 1, item)
-- 将备忘列表保存到json文件中
hs.json.write(history,historyPath, true, true)
-- 创建一个选择器
hs.chooser.new(completionFn)
:choices(history)
:rightClickCallback(menuFn)
:searchSubText(true)
:show()
-- 粘贴选中的片段
local completionFn = function(result)
if result then
hs.pasteboard.setContents(result.text)
hs.eventtap.keyStroke({ "cmd" }, "V")
print("keywords:"..result.text)
end
end
-- 右键弹出菜单
local menuFn = function(index)
menubar = hs.menubar.new(false)
menubar:setTitle("Hidden Menu")
menubar:setMenu( {
{ title = "菜单", fn = function() print("you clicked my menu item!") end },
{ title = "-" },
{ title = "修改片段内容", fn = function()
result,text = hs.dialog.textPrompt("修改片段内容", "请输入新的内容", history[index].text, "确定", "取消")
if result == "确定" then
modifyHistory(text,history[index].subText,true,index)
end
end },
{ title = "修改片段说明", fn = function()
result,subText = hs.dialog.textPrompt("修改片段说明", "请输入新的说明", history[index].subText, "确定", "取消")
if result == "确定" then
modifyHistory(history[index].text,subText,false,index)
end
end },
{ title = "-" },
{ title = "删除当前片段", fn = function()
if hs.dialog.blockAlert("确定删除以下片段?",history[index].text,"确定","取消","informational") == "确定" then
table.remove(history,index)
hs.json.write(history,historyPath, true, true)
hs.alert.show("成功删除片段")
end
end },
})
menubar:popupMenu(hs.mouse.getAbsolutePosition(), true)
end
使用github或者是gitee。具体的操作就不详细说了。
我把快速入门放最后,主要的原因就是,编程学习主要还是要多写多练。基础语法这些只要知道个大概就可以了。特别是脚本语言,本身设计的时候都已经简化了很多语法,只要有一定的编程基础,基本拿来就能用了。不懂的地方再查资料就好。当然,如果你要做个大项目,请一定要打好基础。咱们快速入门就直接开干就好。
因为Hammerspoon 使用Lua脚本。所以,我们一部分是介绍Lua脚本的一些语法,一部分是介绍Hammerspoon API的。
Hammerspoon API文档:https://www.hammerspoon.org/docs/index.html
Lua 参考文档:http://www.lua.org/manual/5.4/
如果使用的Hammerspoon和我的版本不同,可能Lua的版本也不同。那你可能要找对应的Lua版本的文档来看。在脚本中通过以下指令可以打印出Lua版本
print(_VERSION)
基础语法大家可以看文档,这里只说一些文档没有写的,或者是我觉得比较实用的。
Lua是一种动态类型语言,因此语言中没有类型的定义,不需要声明变量类型,每个变量自己保存了类型。有8种基本类型:nil、布尔值(boolean)、数字体(number)、字符串型(string)、用户自定义类型(userdata)、函数(function)、线程(thread)和表(table)。
print(type(nil)) -- 输出 nil
print(type(99.7+12*9)) -- 输出 number
print(type(true)) -- 输出 boolean
print(type("Hello Wikipedia")) -- 输出 string
print(type(print)) -- 输出 function
print(type{1, 2, test = "test"}) -- 输出 table
我们用的比较多的类型是 nil 、 string 、 table
if str == nil then
print("字符串为nil")
else
print("字符串不为nil")
end
-- 字符串拼接,使用..
str = "Hello".." World"
print(str) -- 输出的结果就是 Hello World
-- 查看字符串长度使用 #
str = "Hello World"
print(#str) --输出11
--字符串判空,所谓的空字符串一般是指字符串是nil或者字符串没有内容,所以我们可以封装成一个方法
local function isEmpty(s)
return s == nil or s == ''
end
if isEmpty(s) then
print("字符串为空")
end
local history = {
{
["text"] = "First Choice",
["subText"] = "This is the subtext of the first choice"
},
{ ["text"] = "Second Choice",
["subText"] = "This is the subtext of the second choice"
},
{ ["text"] = "three Choice",
["subText"] = "This is the subtext of the three choice"
},
}
--插入一条数据
local item = {}
item.text = "Fourth Choice"
item.subText = "This is the subtext of the fourth choice"
table.insert(history, 1, item)
--删除第一条数据,table索引是从1开始的
table.remove(history,1)
--修改第一条数据
history[index].text = "First Choice change"
history[index].subText = "This is the subtext of the first choice change"
--查看第一条的数据
print("text:"..history[1].text)
print("subText:"..history[1].subText)
-- 排序,手动选择一个子项来排序,这里选择subText
table.sort(history,function(a,b) return a.subText<b.subText end )
--查看table的长度,也使用#这个符号
print(#history)
hs.hotkey.bind({ "ctrl", "shift" }, "T", function ()
hs.application.launchOrFocus('Terminal')
end)
-- 触发复制事件
hs.eventtap.keyStroke({ "cmd" }, "C")
-- 触发粘贴事件
hs.eventtap.keyStroke({ "cmd" }, "V")
local historyPath= "~/.hammerspoon/history.json"
-- 读取本地文件
history = hs.json.read(historyPath)
-- 写入本地文件
hs.json.write(history,historyPath, true, true)
-- 最好配合rightClickCallback 监听右键,鼠标右键时才弹出菜单
menubar = hs.menubar.new(false)
menubar:setTitle("Hidden Menu")
menubar:setMenu( {
{ title = "菜单", fn = function() print("you clicked my menu item!") end },
{ title = "-" },
menubar:popupMenu(hs.mouse.getAbsolutePosition(), true)
写这篇文章就是自己做个总结。同时推荐下Hammerspoon,真的很好用:-)