Skip to content

Commit 8edc19a

Browse files
committed
feat(image_handler): add mention for pasted_image and mention restore
1 parent 5fac7a8 commit 8edc19a

3 files changed

Lines changed: 77 additions & 5 deletions

File tree

lua/opencode/image_handler.lua

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local context = require('opencode.context')
44
local state = require('opencode.state')
55

66
local M = {}
7+
local cached_temp_dir = nil
78

89
--- Check if a file exists and has content
910
--- @param path string
@@ -137,11 +138,25 @@ local function try_base64_clipboard(temp_dir, timestamp)
137138
return success, success and image_path or nil
138139
end
139140

141+
--- Restore full path of a pasted image by its name
142+
--- @param name string
143+
--- @return string?
144+
function M.restore_img_path(name)
145+
if not cached_temp_dir or not name:find('^pasted_image_') then
146+
return nil
147+
end
148+
local path = cached_temp_dir .. '/' .. name
149+
return is_valid_file(path) and path or nil
150+
end
151+
140152
--- Handle clipboard image data by saving it to a file and adding it to context
141153
--- @return boolean success True if image was successfully handled
142154
function M.paste_image_from_clipboard()
143-
local temp_dir = vim.fn.tempname()
144-
vim.fn.mkdir(temp_dir, 'p')
155+
if not cached_temp_dir then
156+
cached_temp_dir = vim.fn.tempname()
157+
vim.fn.mkdir(cached_temp_dir, 'p')
158+
end
159+
local temp_dir = cached_temp_dir
145160
local timestamp = os.date('%Y%m%d_%H%M%S')
146161
local image_path = string.format('%s/pasted_image_%s.png', temp_dir, timestamp)
147162

@@ -156,7 +171,12 @@ function M.paste_image_from_clipboard()
156171
end
157172

158173
if success then
159-
context.add_file(image_path)
174+
require('opencode.ui.mention').mention(function(mention_cb)
175+
local name = vim.fn.fnamemodify(image_path, ':t')
176+
mention_cb(name)
177+
context.add_file(image_path)
178+
end)
179+
160180
vim.notify('Image saved and added to context: ' .. vim.fn.fnamemodify(image_path, ':t'), vim.log.levels.INFO)
161181
return true
162182
end

lua/opencode/ui/mention.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ function M.restore_mentions(buf)
143143
require('opencode.context').add_file(name)
144144
return
145145
end
146+
if name:find('^pasted_image_') then
147+
local restored_path = require('opencode.image_handler').restore_img_path(name)
148+
if restored_path then
149+
require('opencode.context').add_file(restored_path)
150+
end
151+
end
146152
end)
147153
end
148154

tests/unit/image_handler_spec.lua

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ describe('image_handler', function()
4040
wsl_distro = 0,
4141
added_files = {},
4242
notifications = {},
43+
existing_files = {},
4344
}
4445

4546
vim.fn = setmetatable({
@@ -50,8 +51,13 @@ describe('image_handler', function()
5051
return mocks.temp_dir
5152
end,
5253
mkdir = function() end,
53-
getfsize = function(_)
54-
return 100 -- Simulating non-empty file
54+
getfsize = function(path)
55+
for _, f in ipairs(mocks.existing_files) do
56+
if f == path then
57+
return 100
58+
end
59+
end
60+
return 0
5561
end,
5662
has = function(feature)
5763
if feature == 'win32' then
@@ -124,6 +130,7 @@ describe('image_handler', function()
124130
it('handles Darwin clipboard with osascript', function()
125131
mocks.os_name = 'Darwin'
126132
mocks.executable['osascript'] = 1
133+
table.insert(mocks.existing_files, '/tmp/test_dir/pasted_image_20240101_120000.png')
127134

128135
local success = image_handler.paste_image_from_clipboard()
129136

@@ -139,6 +146,7 @@ describe('image_handler', function()
139146
mocks.os_name = 'Linux'
140147
mocks.executable['wl-paste'] = 1
141148
mocks.executable['xclip'] = 0
149+
table.insert(mocks.existing_files, '/tmp/test_dir/pasted_image_20240101_120000.png')
142150

143151
local success = image_handler.paste_image_from_clipboard()
144152

@@ -151,6 +159,7 @@ describe('image_handler', function()
151159
mocks.os_name = 'Linux'
152160
mocks.executable['wl-paste'] = 0
153161
mocks.executable['xclip'] = 1
162+
table.insert(mocks.existing_files, '/tmp/test_dir/pasted_image_20240101_120000.png')
154163

155164
local success = image_handler.paste_image_from_clipboard()
156165

@@ -162,6 +171,7 @@ describe('image_handler', function()
162171
it('handles Windows clipboard', function()
163172
mocks.os_name = 'Windows_NT'
164173
mocks.executable['powershell.exe'] = 1
174+
table.insert(mocks.existing_files, '/tmp/test_dir/pasted_image_20240101_120000.png')
165175

166176
local success = image_handler.paste_image_from_clipboard()
167177

@@ -176,6 +186,7 @@ describe('image_handler', function()
176186
mocks.os_name = 'Linux'
177187
mocks.wsl_distro = 1
178188
mocks.executable['powershell.exe'] = 1
189+
table.insert(mocks.existing_files, '/tmp/test_dir/pasted_image_20240101_120000.png')
179190

180191
local success = image_handler.paste_image_from_clipboard()
181192

@@ -195,6 +206,7 @@ describe('image_handler', function()
195206
mocks.os_name = 'Darwin'
196207
mocks.executable['osascript'] = 0 -- Force failure of system tool
197208
mocks.clipboard_content = 'data:image/png;base64,fakebasedata'
209+
table.insert(mocks.existing_files, '/tmp/test_dir/pasted_image_20240101_120000.png')
198210

199211
local success = image_handler.paste_image_from_clipboard()
200212

@@ -228,4 +240,38 @@ describe('image_handler', function()
228240
assert.is_false(success)
229241
assert.equals(0, #mocks.added_files)
230242
end)
243+
244+
it('restores image path when file exists and name is valid', function()
245+
mocks.os_name = 'Darwin'
246+
mocks.executable['osascript'] = 1
247+
-- Initialize cached_temp_dir
248+
image_handler.paste_image_from_clipboard()
249+
250+
local img_name = 'pasted_image_test.png'
251+
local expected_path = mocks.temp_dir .. '/' .. img_name
252+
table.insert(mocks.existing_files, expected_path)
253+
254+
local restored_path = image_handler.restore_img_path(img_name)
255+
assert.equals(expected_path, restored_path)
256+
end)
257+
258+
it('returns nil when restoring image path with invalid name', function()
259+
mocks.os_name = 'Darwin'
260+
mocks.executable['osascript'] = 1
261+
image_handler.paste_image_from_clipboard()
262+
263+
local restored_path = image_handler.restore_img_path('not_a_pasted_image.png')
264+
assert.is_nil(restored_path)
265+
end)
266+
267+
it('returns nil when restoring image path and file does not exist', function()
268+
mocks.os_name = 'Darwin'
269+
mocks.executable['osascript'] = 1
270+
image_handler.paste_image_from_clipboard()
271+
272+
local img_name = 'pasted_image_missing.png'
273+
274+
local restored_path = image_handler.restore_img_path(img_name)
275+
assert.is_nil(restored_path)
276+
end)
231277
end)

0 commit comments

Comments
 (0)