183 lines
4.8 KiB
Lua
183 lines
4.8 KiB
Lua
--- ==== Seal.plugins.pasteboard ====
|
|
---
|
|
--- Visual, searchable pasteboard (ie clipboard) history
|
|
local obj = {}
|
|
obj.__index = obj
|
|
obj.__name = "seal_pasteboard"
|
|
obj.timer = nil
|
|
obj.lastItem = nil
|
|
obj.itemBuffer = {}
|
|
obj.choices = {}
|
|
|
|
--- Seal.plugins.pasteboard.historySize
|
|
--- Variable
|
|
---
|
|
--- The number of history items to keep. Defaults to 50
|
|
obj.historySize = 50
|
|
|
|
--- Seal.plugins.pasteboard.saveHistory
|
|
--- Variable
|
|
---
|
|
--- A boolean, true if Seal should automatically load/save clipboard history. Defaults to true
|
|
obj.saveHistory = true
|
|
|
|
--- Seal.plugins.pasteboard.skipUTIs
|
|
--- Variable
|
|
---
|
|
--- An array of UTIs to skip when saving to the history. Defaults to:
|
|
--- ```
|
|
--- {
|
|
--- "de.petermaurer.TransientPasteboardType",
|
|
--- "com.typeit4me.clipping",
|
|
--- "Pasteboard generator type",
|
|
--- "com.agilebits.onepassword",
|
|
--- "org.nspasteboard.TransientType",
|
|
--- "org.nspasteboard.ConcealedType",
|
|
--- "org.nspasteboard.AutoGeneratedType"
|
|
--- }
|
|
--- ```
|
|
obj.skipUTIs = {
|
|
"de.petermaurer.TransientPasteboardType",
|
|
"com.typeit4me.clipping",
|
|
"Pasteboard generator type",
|
|
"com.agilebits.onepassword",
|
|
"org.nspasteboard.TransientType",
|
|
"org.nspasteboard.ConcealedType",
|
|
"org.nspasteboard.AutoGeneratedType"
|
|
}
|
|
|
|
function obj:commands()
|
|
return {
|
|
pb = {
|
|
cmd = "pb",
|
|
fn = obj.choicesPasteboardCommand,
|
|
name = "Pasteboard",
|
|
description = "Pasteboard history",
|
|
plugin = obj.__name
|
|
}
|
|
}
|
|
end
|
|
|
|
function obj:bare()
|
|
return nil
|
|
end
|
|
|
|
function obj.choicesPasteboardCommand(query)
|
|
-- Return the choices that match the query
|
|
return hs.fnutils.filter(obj.choices, function(choice)
|
|
return string.find(string.lower(choice["text"]), string.lower(query))
|
|
end)
|
|
end
|
|
|
|
function obj.pasteboardToChoice(item)
|
|
local choice = {}
|
|
|
|
choice["uuid"] = item["uuid"]
|
|
choice["name"] = item["text"]
|
|
choice["text"] = item["text"]
|
|
choice["kind"] = kind
|
|
choice["plugin"] = obj.__name
|
|
choice["type"] = "copy"
|
|
choice["subText"] = ""
|
|
|
|
if item["uti"] then
|
|
choice["subText"] = item["uti"]
|
|
if hs.application.defaultAppForUTI then
|
|
local bundleID = hs.application.defaultAppForUTI(item["uti"])
|
|
print("Default app for " .. item["uti"] .. " :: " .. (bundleID or "(null)"))
|
|
if bundleID then
|
|
choice["image"] = hs.image.imageFromAppBundle(bundleID)
|
|
end
|
|
end
|
|
end
|
|
if item["dateTime"] then
|
|
choice["subText"] = choice["subText"] .. " :: " .. item["dateTime"]
|
|
end
|
|
|
|
return choice
|
|
end
|
|
|
|
function obj.completionCallback(rowInfo)
|
|
if rowInfo["type"] == "copy" then
|
|
hs.pasteboard.setContents(rowInfo["name"])
|
|
end
|
|
end
|
|
|
|
function obj.checkPasteboard()
|
|
local pasteboard = hs.pasteboard.getContents()
|
|
local shouldSave = false
|
|
|
|
if pasteboard == nil then
|
|
return
|
|
end
|
|
|
|
if (#obj.itemBuffer == 0) or (pasteboard ~= obj.itemBuffer[#obj.itemBuffer]["text"]) then
|
|
local currentTypes = hs.pasteboard.allContentTypes()[1]
|
|
if currentTypes == nil then
|
|
print("ERROR: NO PASTEBOARD CURRENT TYPES. Please file a bug so we can understand this:")
|
|
print(hs.inspect(pasteboard))
|
|
return
|
|
end
|
|
for _, aType in pairs(currentTypes) do
|
|
for _, uti in pairs(obj.skipUTIs) do
|
|
if uti == aType then
|
|
return
|
|
end
|
|
end
|
|
end
|
|
local item = {}
|
|
item["uuid"] = hs.host.uuid()
|
|
item["text"] = pasteboard
|
|
item["uti"] = currentTypes[1]
|
|
item["dateTime"] = os.date()
|
|
|
|
table.insert(obj.itemBuffer, item)
|
|
table.insert(obj.choices, obj.pasteboardToChoice(item))
|
|
|
|
shouldSave = true
|
|
end
|
|
if #obj.itemBuffer > obj.historySize then
|
|
table.remove(obj.itemBuffer, 1)
|
|
table.remove(obj.choices, 1)
|
|
|
|
shouldSave = true
|
|
end
|
|
|
|
if shouldSave then
|
|
obj.save()
|
|
end
|
|
end
|
|
|
|
function obj.save()
|
|
local json = hs.json.encode(obj.itemBuffer)
|
|
local file = io.open(os.getenv("HOME") .. "/.hammerspoon/pasteboard_history.json", "w")
|
|
if file then
|
|
file:write(json)
|
|
file:close()
|
|
end
|
|
end
|
|
|
|
function obj.load()
|
|
local file = io.open(os.getenv("HOME") .. "/.hammerspoon/pasteboard_history.json", "r")
|
|
if file then
|
|
local json = hs.json.decode(file:read())
|
|
if json then
|
|
obj.itemBuffer = json
|
|
|
|
-- Convert all the items to the choice buffer
|
|
for _, v in ipairs(obj.itemBuffer) do
|
|
table.insert(obj.choices, obj.pasteboardToChoice(v))
|
|
end
|
|
end
|
|
file:close()
|
|
end
|
|
end
|
|
|
|
obj.load()
|
|
if obj.timer == nil then
|
|
obj.timer = hs.timer.doEvery(1, function() obj.checkPasteboard(obj) end)
|
|
obj.timer:start()
|
|
end
|
|
|
|
return obj
|