Skip to content

Commit 5fac7a8

Browse files
committed
feat(image_handler): handle WSL clipboard paths and run PowerShell in STA mode
Convert WSL paths to Windows paths using wslpath when running under WSL. Pass -STA to powershell.exe so clipboard image retrieval works reliably.
1 parent efb08e4 commit 5fac7a8

2 files changed

Lines changed: 32 additions & 5 deletions

File tree

lua/opencode/image_handler.lua

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,26 @@ local function handle_windows_clipboard(path)
7373
if vim.fn.executable('powershell.exe') ~= 1 then
7474
return false
7575
end
76+
local win_path = path
77+
if vim.fn.exists('$WSL_DISTRO_NAME') == 1 then
78+
local res = vim.system({ 'wslpath', '-w', path }):wait()
79+
if res.code == 0 then
80+
win_path = res.stdout:gsub('%s+$', '')
81+
end
82+
end
83+
7684
local script = string.format(
7785
[[
78-
Add-Type -AssemblyName System.Windows.Forms;
79-
$img = [System.Windows.Forms.Clipboard]::GetImage();
86+
$img = Get-Clipboard -Format Image;
8087
if ($img) {
8188
$img.Save('%s', [System.Drawing.Imaging.ImageFormat]::Png);
8289
} else {
8390
exit 1
8491
}
8592
]],
86-
path
93+
win_path
8794
)
88-
return run_shell_cmd({ 'powershell.exe', '-command', '-' }, { stdin = script })
95+
return run_shell_cmd({ 'powershell.exe', '-STA', '-command', '-' }, { stdin = script })
8996
end
9097

9198
local handlers = {

tests/unit/image_handler_spec.lua

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@ local image_handler = require('opencode.image_handler')
22
local context = require('opencode.context')
33

44
describe('image_handler', function()
5+
local function assert_has_sta(args)
6+
local has_sta = false
7+
for _, arg in ipairs(args) do
8+
if arg == '-STA' then
9+
has_sta = true
10+
break
11+
end
12+
end
13+
assert.is_true(has_sta)
14+
end
515
local original_fn = vim.fn
616
local original_system = vim.system
717
local original_uv = vim.uv
@@ -72,6 +82,9 @@ describe('image_handler', function()
7282
table.insert(mocks.system_calls, { cmd = cmd, opts = opts })
7383
return {
7484
wait = function()
85+
if cmd[1] == 'wslpath' then
86+
return { code = 0, stdout = 'C:\\Windows\\Path' }
87+
end
7588
return { code = 0 }
7689
end,
7790
}
@@ -156,6 +169,7 @@ describe('image_handler', function()
156169
assert.equals(1, #mocks.added_files)
157170
local cmd_args = mocks.system_calls[1].cmd
158171
assert.equals('powershell.exe', cmd_args[1])
172+
assert_has_sta(cmd_args)
159173
end)
160174

161175
it('handles WSL clipboard as Windows', function()
@@ -167,8 +181,14 @@ describe('image_handler', function()
167181

168182
assert.is_true(success)
169183
assert.equals(1, #mocks.added_files)
170-
local cmd_args = mocks.system_calls[1].cmd
184+
185+
-- First call should be wslpath
186+
assert.equals('wslpath', mocks.system_calls[1].cmd[1])
187+
188+
-- Second call should be powershell.exe with -STA
189+
local cmd_args = mocks.system_calls[2].cmd
171190
assert.equals('powershell.exe', cmd_args[1])
191+
assert_has_sta(cmd_args)
172192
end)
173193

174194
it('falls back to base64 clipboard if system command fails', function()

0 commit comments

Comments
 (0)