chore(clipboard): separate logic to save as base64 and files (#329)

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
This commit is contained in:
Aaron Pham 2024-08-28 11:52:12 -04:00 committed by GitHub
parent 2c450b1da3
commit 755c15c0bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 89 additions and 9 deletions

View File

@ -3,8 +3,10 @@ local Utils = require("avante.utils")
---@class AvanteClipboard ---@class AvanteClipboard
local M = {} local M = {}
---@alias DarwinClipboardCommand "pngpaste" | "osascript"
M.clip_cmd = nil M.clip_cmd = nil
---@return DarwinClipboardCommand
M.get_clip_cmd = function() M.get_clip_cmd = function()
if M.clip_cmd then if M.clip_cmd then
return M.clip_cmd return M.clip_cmd
@ -34,7 +36,31 @@ M.has_content = function()
return false return false
end end
M.get_content = function() M.save_content = function(filepath)
local cmd = M.get_clip_cmd()
---@type vim.SystemCompleted
local output
if cmd == "pngpaste" then
output = Utils.shell_run(('pngpaste - > "%s"'):format(filepath))
return output.code == 0
elseif cmd == "osascript" then
output = Utils.shell_run(
string.format(
[[osascript -e 'set theFile to (open for access POSIX file "%s" with write permission)' ]]
.. [[-e 'try' -e 'write (the clipboard as «class PNGf») to theFile' -e 'end try' ]]
.. [[-e 'close access theFile' -e 'do shell script "cat %s > %s"']],
filepath,
filepath,
filepath
)
)
return output.code == 0
end
return false
end
M.get_base64_content = function()
local cmd = M.get_clip_cmd() local cmd = M.get_clip_cmd()
---@type vim.SystemCompleted ---@type vim.SystemCompleted
local output local output

View File

@ -1,16 +1,28 @@
---NOTE: this module is inspired by https://github.com/HakonHarnes/img-clip.nvim/tree/main ---NOTE: this module is inspired by https://github.com/HakonHarnes/img-clip.nvim/tree/main
---@see https://github.com/ekickx/clipboard-image.nvim/blob/main/lua/clipboard-image/paste.lua
local Path = require("plenary.path")
local Utils = require("avante.utils") local Utils = require("avante.utils")
local Config = require("avante.config")
---@class AvanteClipboard ---@class AvanteClipboard
---@field clip_cmd string ---@field clip_cmd string
---@field get_clip_cmd fun(): string ---@field get_clip_cmd fun(): string
---@field has_content fun(): boolean ---@field has_content fun(): boolean
---@field get_content fun(): string ---@field get_base64_content fun(): string
---@field save_content fun(filename: string): boolean
--- ---
---@class avante.Clipboard: AvanteClipboard ---@class avante.Clipboard: AvanteClipboard
local M = {} local M = {}
M.paste_directory = Path:new(Config.history.storage_path):joinpath("pasted_images")
M.setup = function()
if not M.paste_directory:exists() then
M.paste_directory:mkdir({ parent = true })
end
end
return setmetatable(M, { return setmetatable(M, {
__index = function(t, k) __index = function(t, k)
local os_mapping = Utils.get_os_name() local os_mapping = Utils.get_os_name()

View File

@ -37,7 +37,22 @@ M.has_content = function()
return false return false
end end
M.get_content = function() M.save_content = function(filepath)
local cmd = M.get_clip_cmd()
---@type vim.SystemCompleted
local output
if cmd == "xclip" then
output = Utils.shell_run(('xclip -selection clipboard -o -t image/png > "%s"'):format(filepath))
return output.code == 0
elseif cmd == "wl-paste" then
output = Utils.shell_run(('wl-paste --type image/png > "%s"'):format(filepath))
return output.code == 0
end
return false
end
M.get_base64_content = function()
local cmd = M.get_clip_cmd() local cmd = M.get_clip_cmd()
---@type vim.SystemCompleted ---@type vim.SystemCompleted
local output local output

View File

@ -30,7 +30,23 @@ M.has_content = function()
return false return false
end end
M.get_content = function() M.save_content = function(filepath)
local cmd = M.get_clip_cmd()
---@type vim.SystemCompleted
local output
if cmd == "powershell.exe" then
output = Utils.shell_run(
("Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Clipboard]::GetImage().Save('%s')"):format(
filepath
)
)
return output.code == 0
end
return false
end
M.get_base64_content = function()
local cmd = M.get_clip_cmd() local cmd = M.get_clip_cmd()
---@type vim.SystemCompleted ---@type vim.SystemCompleted
local output local output

View File

@ -73,6 +73,10 @@ M.defaults = {
}, },
history = { history = {
storage_path = vim.fn.stdpath("state") .. "/avante", storage_path = vim.fn.stdpath("state") .. "/avante",
paste = {
extension = "png",
filename = "pasted-%Y-%m-%d-%H-%M-%S",
},
}, },
highlights = { highlights = {
---@type AvanteConflictHighlights ---@type AvanteConflictHighlights

View File

@ -235,6 +235,7 @@ function M.setup(opts)
require("avante.highlights").setup() require("avante.highlights").setup()
require("avante.diff").setup() require("avante.diff").setup()
require("avante.providers").setup() require("avante.providers").setup()
require("avante.clipboard").setup()
-- setup helpers -- setup helpers
H.autocmds() H.autocmds()

View File

@ -50,7 +50,7 @@ M.parse_message = function(opts)
source = { source = {
type = "base64", type = "base64",
media_type = "image/png", media_type = "image/png",
data = Clipboard.get_content(), data = Clipboard.get_base64_content(),
}, },
}) })
end end

View File

@ -61,18 +61,21 @@ M.get_user_message = function(opts)
end end
M.parse_message = function(opts) M.parse_message = function(opts)
local user_content = {} ---@type string | OpenAIMessage[]
local user_content
if Config.behaviour.support_paste_from_clipboard and Clipboard.has_content() then if Config.behaviour.support_paste_from_clipboard and Clipboard.has_content() then
user_content = {}
table.insert(user_content, { table.insert(user_content, {
type = "image_url", type = "image_url",
image_url = { image_url = {
url = "data:image/png;base64," .. Clipboard.get_content(), url = "data:image/png;base64," .. Clipboard.get_base64_content(),
}, },
}) })
table.insert(user_content, { type = "text", text = M.get_user_message(opts) })
else
user_content = M.get_user_message(opts)
end end
table.insert(user_content, { type = "text", text = M.get_user_message(opts) })
return { return {
{ role = "system", content = opts.system_prompt }, { role = "system", content = opts.system_prompt },
{ role = "user", content = user_content }, { role = "user", content = user_content },

View File

@ -16,3 +16,6 @@
--- @param opts vim.api.keyset.create_autocmd.opts --- @param opts vim.api.keyset.create_autocmd.opts
--- @return integer --- @return integer
function vim.api.nvim_create_autocmd(event, opts) end function vim.api.nvim_create_autocmd(event, opts) end
---@type boolean
vim.g.avante_login = vim.g.avante_login