my personal dotfiles managed by dotbot, zinit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

395 lines
12 KiB

--- === ClipShow ===
---
--- Show the content of system clipboard
---
--- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/ClipShow.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/ClipShow.spoon.zip)
local obj={}
obj.__index = obj
-- Metadata
obj.name = "ClipShow"
obj.version = "1.0"
obj.author = "ashfinal <[email protected]>"
obj.homepage = "https://github.com/Hammerspoon/Spoons"
obj.license = "MIT - https://opensource.org/licenses/MIT"
obj.canvas = nil
obj.ccount = nil
obj.lastsession = nil
function obj:init()
obj.canvas = hs.canvas.new({x=0, y=0, w=0, h=0})
obj.canvas[1] = {
type = "rectangle",
action = "fill",
fillColor = {hex="#000000", alpha=0.75}
}
obj.canvas[2] = {
type = "segments",
strokeColor = {hex = "#FFFFFF", alpha = 0.1},
coordinates = {
{x="1%", y="72%"},
{x="72%", y="72%"}
}
}
obj.canvas[3] = {
type = "segments",
strokeColor = {hex = "#FFFFFF", alpha = 0.1},
coordinates = {
{x="72%", y="1%"},
{x="72%", y="99%"}
}
}
obj.canvas[4] = {type = "text", text = ""}
obj.canvas[5] = {type = "text"}
obj.canvas:level(hs.canvas.windowLevels.tornOffMenu)
end
local function isFileKinds(val, tbl)
for _, v in ipairs(tbl) do
if val == v then
return true
end
end
return false
end
-- Resize the ClipShow canvas
function obj:adjustCanvas()
local cscreen = hs.screen.mainScreen()
local cres = cscreen:fullFrame()
obj.canvas:frame({
x = cres.x+cres.w*0.15/2,
y = cres.y+cres.h*0.25/2,
w = cres.w*0.85,
h = cres.h*0.75
})
end
-- Fill clipshowM's keybindings in sidebar
function obj:fillModalKeys()
if #obj.canvas < 6 then
local modal = spoon.ModalMgr.modal_list["clipshowM"]
if modal then
local keys_pool = {}
for _, v in ipairs(modal.keys) do
table.insert(keys_pool, v.msg)
end
for idx, val in ipairs(keys_pool) do
obj.canvas[idx + 5] = {
type = "text",
text = val,
textFont = "Courier-Bold",
textSize = 16,
textColor = {hex = "#2390FF", alpha = 1},
frame = {
x = "74%",
y = tostring(idx * 30 / (obj.canvas:frame().h - 60)),
w = "24%",
h = tostring(30 / (obj.canvas:frame().h - 60))
}
}
end
end
end
end
--- ClipShow:toggleShow()
--- Method
--- Process the content of system clipboard and show/hide the canvas
---
function obj:processClipboard()
local clip_type = hs.pasteboard.typesAvailable()
if clip_type.image then
if clip_type.URL then
local urltbl = hs.pasteboard.readURL()
if urltbl.filePath then
-- local file
local fex = urltbl.filePath:match(".*%.(%w+)$") or ""
local image_ex = {"jpeg", "jpg", "gif", "png", "bmp", "tiff", "icns"}
local text_ex = {"", "txt", "md", "markdown", "mkd", "rst", "org", "sh", "zsh", "json", "yml", "mk", "config", "conf", "pub", "gitignore"}
if isFileKinds(fex:lower(), image_ex) then
local imagedata = hs.image.imageFromPath(urltbl.filePath)
obj.canvas[4] = {
type = "image",
image = imagedata,
frame = {
x = "1%",
y = "1%",
w = "70%",
h = "70%"
}
}
elseif isFileKinds(fex:lower(), text_ex) then
-- text file format
local file_handler = io.open(urltbl.filePath)
if file_handler then
local file_content = file_handler:read(1000)
if file_content then
obj.canvas[4] = {
type = "text",
text = file_content,
textSize = 20,
frame = {
x = "1%",
y = "1%",
w = "70%",
h = "70%"
}
}
file_handler:close()
else
-- Maybe directory
local dir_name = urltbl.filePath
obj.canvas[4] = {
type = "text",
text = dir_name,
frame = {
x = "1%",
y = "1%",
w = "70%",
h = "70%"
}
}
end
else
print("-- ClipShow: No access to this file!")
end
else
local stringdata = table.concat(hs.pasteboard.readString(nil, true))
obj.canvas[4] = {
type = "text",
text = stringdata,
frame = {
x = "1%",
y = "1%",
w = "70%",
h = "70%"
}
}
end
else
-- Remote image
local imagedata = hs.pasteboard.readImage()
obj.canvas[4] = {
type = "image",
image = imagedata,
frame = {
x = "1%",
y = "1%",
w = "70%",
h = "70%"
}
}
end
else
-- Image fragement
local imagedata = hs.pasteboard.readImage()
obj.canvas[4] = {
type = "image",
image = imagedata,
frame = {
x = "1%",
y = "1%",
w = "70%",
h = "70%"
}
}
end
obj:adjustCanvas()
obj:fillModalKeys()
obj.canvas:show()
elseif clip_type.URL then
local urltbl = hs.pasteboard.readURL(nil, true)
if urltbl then
if #urltbl > 1 then
local stringdata = table.concat(hs.pasteboard.readString(nil, true))
obj.canvas[4] = {
type = "text",
text = stringdata,
frame = {
x = "1%",
y = "1%",
w = "70%",
h = "70%"
}
}
obj:adjustCanvas()
obj:fillModalKeys()
obj.canvas:show()
else
local browser = hs.urlevent.getDefaultHandler("http")
hs.urlevent.openURLWithBundle(urltbl[1].url, browser)
end
else
local browser = hs.urlevent.getDefaultHandler("http")
hs.urlevent.openURLWithBundle(urltbl[1].url, browser)
end
elseif clip_type.string then
local stringdata = table.concat(hs.pasteboard.readString(nil, true))
obj.canvas[4] = {
type = "text",
text = stringdata,
frame = {
x = "1%",
y = "1%",
w = "70%",
h = "70%"
}
}
obj:adjustCanvas()
obj:fillModalKeys()
obj.canvas:show()
end
end
function obj:toggleShow()
if obj.canvas:isShowing() then
obj.canvas:hide()
else
local change_count = hs.pasteboard.changeCount()
-- Only if content of the clipboard changed then we redraw the canvas
if change_count ~= obj.ccount then
obj:processClipboard()
obj.ccount = change_count
else
obj:adjustCanvas()
obj.canvas:show()
end
end
end
--- ClipShow:openInBrowserWithRef(refstr)
--- Method
--- Open content of the clipboard in default browser with specific refstr.
---
--- Parameters:
--- * refstr - A optional string specifying which refstr to use. If nil, then open this content in browser directly. The "refstr" could be something like this: `https://www.bing.com/search?q=`.
local function acquireText()
if obj.canvas:isShowing() then
if obj.canvas[4].type == "text" then
return obj.canvas[4].text
else
return hs.pasteboard.readString() or ""
end
else
return hs.pasteboard.readString() or ""
end
end
function obj:openInBrowserWithRef(refstr)
local querystr = acquireText()
if refstr then
local encoded_query = hs.http.encodeForQuery(refstr .. querystr)
local defaultbrowser = hs.urlevent.getDefaultHandler("http")
hs.urlevent.openURLWithBundle(encoded_query, defaultbrowser)
else
local defaultbrowser = hs.urlevent.getDefaultHandler("http")
hs.urlevent.openURLWithBundle(querystr, defaultbrowser)
end
end
--- ClipShow:saveToSession()
--- Method
--- Save clipboard session so we can restore it later
---
function obj:saveToSession()
obj.lastsession = hs.pasteboard.readAllData()
if obj.canvas:isShowing() then
if obj.canvas[4].type == "text" then
local cdraw = obj.canvas[4].text
hs.pasteboard.writeObjects(cdraw)
obj.canvas[5] = {
type = "text",
text = cdraw,
textSize = 16,
textAlignment = "center",
frame = {
x = "1%",
y = "73%",
w = "70%",
h = "26%"
}
}
elseif obj.canvas[4].type == "image" then
local cdraw = obj.canvas[4].image
hs.pasteboard.writeObjects(cdraw)
obj.canvas[5] = {
type = "image",
image = cdraw,
frame = {
x = "1%",
y = "73%",
w = "70%",
h = "26%"
}
}
end
end
end
--- ClipShow:restoreLastSession()
--- Method
--- Restore the lastsession of system clipboard
---
function obj:restoreLastSession()
if obj.lastsession then
hs.pasteboard.writeAllData(obj.lastsession)
obj:processClipboard()
obj.ccount = change_count
end
end
--- ClipShow:saveToFile()
--- Method
--- Save content of current canvas to a file, the default location is `~/Desktop/`.
---
function obj:saveToFile()
if obj.canvas:isShowing() then
if obj.canvas[4].type == "image" then
local cdraw = obj.canvas[4].image
local file_name = os.date("%Y-%m-%d %H:%M:%S")
cdraw:saveToFile("~/Desktop/" .. file_name .. ".png", true)
elseif obj.canvas[4].type == "text" then
local ctext = obj.canvas[4].text
local file_name = os.date("%Y-%m-%d %H:%M:%S")
local full_path = os.getenv("HOME") .. "/Desktop/" .. file_name .. ".txt"
local file_handler = io.open(full_path, "w")
file_handler:write(ctext)
file_handler:close()
end
end
end
--- ClipShow:openWithCommand(command)
--- Method
--- Open local file with specific command.
---
--- Parameters:
--- * command - A string specifying which command to use. The "command" is something like this: `/usr/local/bin/mvim`.
function obj:openWithCommand(command)
if obj.canvas:isShowing() then
if obj.canvas[4].type == "text" then
local urltbl = hs.pasteboard.readURL()
if urltbl then
if urltbl.filePath then
os.execute(command .. " " .. urltbl.filePath)
else
os.execute(command)
end
else
os.execute(command)
end
end
end
end
return obj