Skip to content

Instantly share code, notes, and snippets.

@dulm
Last active February 14, 2020 11:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dulm/ee5ec47cfd2a71ded0e3841ee04e6ea3 to your computer and use it in GitHub Desktop.
Save dulm/ee5ec47cfd2a71ded0e3841ee04e6ea3 to your computer and use it in GitHub Desktop.
Hammerspoon config
function class(classname, super)
local superType = type(super)
local cls
if superType ~= "function" and superType ~= "table" then
superType = nil
super = nil
end
if superType == "function" or (super and super.__ctype == 1) then
-- inherited from native C++ Object
cls = {}
if superType == "table" then
-- copy fields from super
for k,v in pairs(super) do cls[k] = v end
cls.__create = super.__create
cls.super = super
else
cls.__create = super
end
cls.ctor = function() end
cls.__cname = classname
cls.__ctype = 1
function cls.new(...)
local instance = cls.__create(...)
-- copy fields from class to native object
for k,v in pairs(cls) do instance[k] = v end
instance.class = cls
instance:ctor(...)
return instance
end
else
-- inherited from Lua Object
if super then
cls = clone(super)
cls.super = super
else
cls = {ctor = function() end}
end
cls.__cname = classname
cls.__ctype = 2 -- lua
cls.__index = cls
function cls.new(...)
local instance = setmetatable({}, cls)
instance.class = cls
instance:ctor(...)
return instance
end
end
return cls
end
defaultKeyMappers = {
{{'ctrl'},'w',{{{'cmd'},'x'}}}, --剪切
{{'alt'},'w',{{{'cmd'},'c'}}}, --复制
{{'ctrl'},'y',{{{'cmd'},'v'}}}, --粘贴
{{"ctrl","shift"},'-',{{{'cmd'},'z'}}}, --撤销
{{'ctrl'},'v',{{{},'pagedown'}}}, --剪切
{{'alt'},'v',{{{},'pageup'}}}, --复制
{{'ctrl'},'s',{{{'cmd'},'f'}}}, --查找
{{'alt'},'f',{{{'alt'},'right'}}}, --前移一词
{{'alt'},'b',{{{'alt'},'left'}}}, --后移一词
{{'ctrl','shift'},'S',{{{'cmd'},'s'}}}, --保存
{{'ctrl','shift'},'A',{{{'cmd'},'a'}}}, --全选
{{'ctrl'},'g',{{nil,'escape'}}}, --取消
}
appKeyMappers = {
['印象笔记']={
{{'ctrl'},'w',{{{'cmd'},'x'}}}, --剪切
{{'alt'},'w',{{{'cmd'},'c'}}}, --复制
{{'ctrl'},'y',{{{'cmd'},'v'}}}, --粘贴
{{"ctrl","shift"},'-',{{{'cmd'},'z'}}}, --撤销
{{'ctrl'},'v',{{{},'pagedown'}}}, --剪切
{{'alt'},'v',{{{},'pageup'}}}, --复制
{{'ctrl'},'s',{{{'cmd'},'f'}}}, --查找
{{'alt'},'f',{{{'alt'},'right'}}}, --前移一词
{{'alt'},'b',{{{'alt'},'left'}}}, --后移一词
{{'ctrl','shift'},'S',{{{'cmd'},'s'}}}, --保存
{{'ctrl','shift'},'A',{{{'cmd'},'a'}}}, --全选
{{'ctrl'},'g',{{nil,'escape'}}}, --取消
{{'ctrl','shift'},'V',{{{'cmd','shift'},'v'}}}, --去格式粘贴
},
["iTerm2"] = {
{{'ctrl'},'w',{{{'cmd'},'x'}}}, --剪切
{{'alt'},'w',{{{'cmd'},'c'}}}, --复制
{{'ctrl'},'y',{{{'cmd'},'v'}}}, --粘贴
{{"ctrl","shift"},'-',{{{'cmd'},'z'}}}, --撤销
{{'ctrl'},'v',{{{},'pagedown'}}}, --剪切
{{'alt'},'v',{{{},'pageup'}}}, --复制
{{'alt','shift'},',',{{{'cmd'},'up'}}}, --文首
{{'alt','shift'},'.',{{{'cmd'},'down'}}}, --文末
{{'ctrl'},'s',{{{'cmd'},'f'}}}, --查找
{{'alt'},'f',{{nil,"escape"}, {nil,"f"}}}, --前移一词
{{'alt'},'b',{{nil,"escape"}, {nil,"b"}}}, --后移一词
{{'ctrl','shift'},'S',{{{'cmd'},'s'}}}, --保存
{{'ctrl','shift'},'A',{{{'cmd'},'a'}}}, --全选
{{'ctrl'},'g',{{nil,'escape'}}}, --取消
},
["VMware Fusion"] = "nochange",
["Sublime Text"] = "nochange",
["IntelliJ IDEA"] = "nochange",
["PyCharm"] = "nochange",
["向日葵控制端"] = "nochange",
["PyCharm-EAP"] = "nochange",
}
function bindKeyMappers(keyMappers,modal)
for i,mapper in ipairs(keyMappers) do
if modal == nil then
hs.hotkey.bind(mapper[1], mapper[2], function()
print(string.format("no modal, %s %s=>", mapper[1], mapper[2]))
target_list = mapper[3]
for i, key_pair in ipairs(target_list) do
print(string.format("%s %s", key_pair[1], key_pair[2]))
hs.eventtap.keyStroke(key_pair[1],key_pair[2])
end
end)
else
modal:bind(mapper[1], mapper[2], nil, function()
print(string.format("modal, %s %s=>", mapper[1], mapper[2]))
modal.triggered = true
target_list = mapper[3]
for i, key_pair in ipairs(target_list) do
print(string.format("%s %s", key_pair[1], key_pair[2]))
hs.eventtap.keyStroke(key_pair[1],key_pair[2])
end
end)
end
end
hs.hotkey.bind({'alt'}, 'f', function()
hs.eventtap.keyStroke(nil,"escape")
hs.eventtap.keyStroke(nil,"f")
end)
end
function initModal()
for app, keyMappers in pairs(appKeyMappers) do
if keyMappers ~= "nochange" then
spoon.ModalMgr:new(app)
bindKeyMappers(keyMappers,spoon.ModalMgr.modal_list[app])
end
end
spoon.ModalMgr:new('default')
bindKeyMappers(defaultKeyMappers,spoon.ModalMgr.modal_list['default'])
end
function applicationWatcher(appName, eventType, appObject)
--hs.alert.show(appName..eventType)
if (eventType == hs.application.watcher.activated) then
actApp(appName)
end
end
preMapper = nil
function actApp(appName, is_init)
print('\n\n')
print(appName.." activated.")
mapper = appKeyMappers[appName]
if is_init == nil then
is_init = false
end
print("preMapper:",preMapper,"mapper:",mapper)
if is_init == false and preMapper == mapper then
print('modal eq, not change.')
return
end
print('start deactivate', preMapper)
--spoon.ModalMgr:deactivateAll() --bug https://github.com/Hammerspoon/Spoons/issues/114
id_list = {}
for k,v in pairs(spoon.ModalMgr.active_list) do
table.insert(id_list, k)
end
spoon.ModalMgr:deactivate(id_list)
print('start activate', mapper)
if mapper == nil then
spoon.ModalMgr:activate({'default'}, nil, nil)
--mapper = defaultKeyMappers
elseif mapper == 'nochange' then
else
spoon.ModalMgr:activate({appName}, nil, nil)
--spoon.ModalMgr:toggleCheatsheet({appName})
end
preMapper = mapper
print('\n\n')
end
--[[
modal = hs.hotkey.modal.new({}, nil )
function actApp(appName)
print(appName.." activated.")
local isMatch = false
for app, keyMappers in pairs(appKeyMappers) do
if(appName == app) then
if keyMappers == "nochange" then
print("nochange")
modal:exit()
else
modal:exit()
bindKeyMappers(keyMappers,modal)
modal:enter()
end
isMatch = true
break
end
end
if isMatch == false then
modal:exit()
bindKeyMappers(defaultKeyMappers,modal)
modal:enter()
end
end
]]--
-- 去掉剪切板中句子内的空格后再粘贴.
hs.hotkey.bind({"ctrl", "shift"}, "y", function()
local text = hs.pasteboard.getContents()
--print(text)
local newText,_ = string.gsub(text, "%s", "")
newText,_ = string.gsub(newText, "(", "(")
newText,_ = string.gsub(newText, ")", ")")
newText,_ = string.gsub(newText, ",", ", ")
newText,_ = string.gsub(newText, "、", ", ")
newText,_ = string.gsub(newText, "。", ". ")
newText,_ = string.gsub(newText, ":", ":")
newText,_ = string.gsub(newText, "?", "?")
newText,_ = string.gsub(newText, "“", "\"")
newText,_ = string.gsub(newText, "”", "\"")
--print(newText)
hs.pasteboard.setContents(newText)
hs.eventtap.keyStroke({"cmd"},"v")
end)
--[[
local modifierHandler = function(e)
local flags = e:getFlags()
local onlyFnPressed = false
for k, v in pairs(flags) do
onlyFnPressed = v and k == "fn"
if not onlyFnPressed then break end
end
-- you must tap and hold ctrl by itself to turn this on
if onlyFnPressed
elseif not next(flags) and module.keyListener then
end
return false
endmodifierListener = hs.eventtap.new({ hs.eventtap.event.types.flagschanged }, modifierHandler):start()
]]--
hs.loadSpoon("ModalMgr")
initModal()
local appWatcher = hs.application.watcher.new(applicationWatcher)
appWatcher:start()
-- bind key after reload, because appWatcher can't capturer the event
local fw = hs.window.focusedWindow()
if fw ~= nil then
actApp(fw:application():name(), true)
end
-- Reload config when any lua file in config directory changes
function reloadConfig(files)
doReload = false
for _,file in pairs(files) do
if file:sub(-4) == '.lua' then
doReload = true
end
end
if doReload then
hs.reload()
end
end
local myWatcher = hs.pathwatcher.new(os.getenv('HOME') .. '/.hammerspoon/', reloadConfig):start()
hs.alert.show('Config loaded')
hs.hotkey.bind({"ctrl","shift"}, "R", function()
hs.reload()
end)
hs.loadSpoon("FnMate")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment