Skip to content

Commit 70cf3f9

Browse files
committed
feat(context-completion): selections are now multiple like files
1 parent e029960 commit 70cf3f9

File tree

5 files changed

+57
-66
lines changed

5 files changed

+57
-66
lines changed

lua/opencode/context.lua

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,25 @@ function M.add_selection(selection)
110110
state.context_updated_at = vim.uv.now()
111111
end
112112

113-
function M.add_file(file)
114-
--- TODO: probably need a way to remove a file once it's been added?
115-
--- maybe a keymap like clear all context?
113+
function M.remove_selection(selection)
114+
if not M.context.selections then
115+
return
116+
end
117+
118+
for i, sel in ipairs(M.context.selections) do
119+
if sel.file.path == selection.file.path and sel.lines == selection.lines then
120+
table.remove(M.context.selections, i)
121+
break
122+
end
123+
end
124+
state.context_updated_at = vim.uv.now()
125+
end
116126

127+
function M.clear_selections()
128+
M.context.selections = nil
129+
end
130+
131+
function M.add_file(file)
117132
if not M.context.mentioned_files then
118133
M.context.mentioned_files = {}
119134
end

lua/opencode/ui/completion/context.lua

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ local icons = require('opencode.ui.icons')
55

66
local M = {}
77

8+
---@generic T
89
---@param name string
910
---@param type string
1011
---@param available boolean
1112
---@param documentation string|nil
1213
---@param icon string|nil
14+
---@param additional_data? T
1315
---@return CompletionItem
14-
local function create_context_item(name, type, available, documentation, icon)
16+
local function create_context_item(name, type, available, documentation, icon, additional_data)
1517
local label = name
1618

1719
return {
@@ -22,7 +24,7 @@ local function create_context_item(name, type, available, documentation, icon)
2224
documentation = documentation or (available and name or 'Enable ' .. name .. ' for this message'),
2325
insert_text = '',
2426
source_name = 'context',
25-
data = { type = type, name = name, available = available },
27+
data = { type = type, name = name, available = available, additional_data = additional_data },
2628
}
2729
end
2830

@@ -52,15 +54,9 @@ local function format_diagnostics(diagnostics)
5254
return table.concat(parts, ', ')
5355
end
5456

55-
local function format_selections(selections)
56-
local content = {}
57-
for _, sel in ipairs(selections or {}) do
58-
local lang = sel.file and sel.file.extension or ''
59-
local text = string.format('```%s\n%s\n```', lang, sel.content)
60-
61-
table.insert(content, text)
62-
end
63-
return table.concat(content, '\n')
57+
local function format_selection(selection)
58+
local lang = selection.file and selection.file.extension or ''
59+
return string.format('```%s\n%s\n```', lang, selection.content)
6460
end
6561

6662
---@param cursor_data? OpencodeContextCursorData
@@ -112,14 +108,24 @@ local function add_mentioned_files_items(ctx)
112108
end
113109

114110
---@param ctx OpencodeContext
115-
---@return CompletionItem
116-
local function add_selection_item(ctx)
117-
return create_context_item(
118-
'Selection',
119-
'selection',
120-
context.is_context_enabled('selection'),
121-
format_selections(ctx.selections or {})
122-
)
111+
---@return CompletionItem[]
112+
local function add_selection_items(ctx)
113+
local items = {
114+
create_context_item(
115+
'Selection' .. (ctx.selections and #ctx.selections > 0 and string.format(' (%d)', #ctx.selections) or ''),
116+
'selection',
117+
context.is_context_enabled('selection')
118+
),
119+
}
120+
121+
for i, selection in ipairs(ctx.selections or {}) do
122+
local label = 'Selection ' .. (selection.file and vim.fn.fnamemodify(selection.file.path, ':t')) or i
123+
table.insert(
124+
items,
125+
create_context_item(label, 'selection_item', true, format_selection(selection), icons.get('selection'), selection)
126+
)
127+
end
128+
return items
123129
end
124130

125131
---@param ctx OpencodeContext
@@ -176,10 +182,10 @@ local context_source = {
176182

177183
local items = {
178184
add_current_file_item(ctx),
179-
add_selection_item(ctx),
180185
add_diagnostics_item(ctx),
181186
add_cursor_data_item(ctx),
182187
}
188+
vim.list_extend(items, add_selection_items(ctx))
183189
vim.list_extend(items, add_mentioned_files_items(ctx))
184190
vim.list_extend(items, add_subagents_items(ctx))
185191

@@ -224,6 +230,8 @@ local context_source = {
224230
local subagent_name = item.data.name:gsub(' %(agent%)$', '')
225231
context.remove_subagent(subagent_name)
226232
input_win.remove_mention(subagent_name)
233+
elseif type == 'selection_item' then
234+
context.remove_selection(item.data.additional_data --[[@as OpencodeContextSelection]])
227235
end
228236

229237
vim.schedule(function()

lua/opencode/ui/context_bar.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ local function create_winbar_segments()
8383

8484
if context.is_context_enabled('selection') and has_selection(ctx) then
8585
table.insert(segments, {
86-
icon = '',
87-
text = "'<'> Sel",
86+
icon = icons.get('selection'),
87+
text = '(' .. #ctx.selections .. ')',
8888
highlight = 'OpencodeContextSelection',
8989
})
9090
end

lua/opencode/ui/highlight.lua

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ function M.setup()
2424
vim.api.nvim_set_hl(0, 'OpencodeHint', { link = 'Comment', default = true })
2525
vim.api.nvim_set_hl(0, 'OpencodeContext', { fg = '#3b4261', default = true })
2626
vim.api.nvim_set_hl(0, 'OpencodeContextBar', { fg = '#3b4261', default = true })
27-
vim.api.nvim_set_hl(0, 'OpencodeContextCurrentFile', { link = 'Comment', default = true })
28-
vim.api.nvim_set_hl(0, 'OpencodeContextAgent', { link = 'Comment', default = true })
29-
vim.api.nvim_set_hl(0, 'OpencodeContextSelection', { link = 'Visual', default = true })
30-
vim.api.nvim_set_hl(0, 'OpencodeContextError', { link = 'DiagnosticError', default = true })
27+
vim.api.nvim_set_hl(0, 'OpencodeContextCurrentFile', { link = 'OpencodeContext', default = true })
28+
vim.api.nvim_set_hl(0, 'OpencodeContextAgent', { link = '@label', default = true })
29+
vim.api.nvim_set_hl(0, 'OpencodeContextSelection', { link = '@label', default = true })
30+
vim.api.nvim_set_hl(0, 'OpencodeContextError', { link = '@label', default = true })
3131
vim.api.nvim_set_hl(0, 'OpencodeContextWarning', { link = 'DiagnosticWarn', default = true })
3232
vim.api.nvim_set_hl(0, 'OpencodeContextInfo', { link = 'DiagnosticInfo', default = true })
3333
else
@@ -51,9 +51,9 @@ function M.setup()
5151
vim.api.nvim_set_hl(0, 'OpencodeHint', { link = 'Comment', default = true })
5252
vim.api.nvim_set_hl(0, 'OpencodeContext', { fg = '#3b4261', default = true })
5353
vim.api.nvim_set_hl(0, 'OpencodeContextBar', { fg = '#3b4261', default = true })
54-
vim.api.nvim_set_hl(0, 'OpencodeContextCurrentFile', { link = 'Comment', default = true })
55-
vim.api.nvim_set_hl(0, 'OpencodeContextAgent', { link = 'Comment', default = true })
56-
vim.api.nvim_set_hl(0, 'OpencodeContextSelection', { link = 'Visual', default = true })
54+
vim.api.nvim_set_hl(0, 'OpencodeContextCurrentFile', { link = '@label', default = true })
55+
vim.api.nvim_set_hl(0, 'OpencodeContextAgent', { link = '@label', default = true })
56+
vim.api.nvim_set_hl(0, 'OpencodeContextSelection', { link = '@label', default = true })
5757
vim.api.nvim_set_hl(0, 'OpencodeContextError', { link = 'DiagnosticError', default = true })
5858
vim.api.nvim_set_hl(0, 'OpencodeContextWarning', { link = 'DiagnosticWarn', default = true })
5959
vim.api.nvim_set_hl(0, 'OpencodeContextInfo', { link = 'DiagnosticInfo', default = true })

lua/opencode/ui/icons.lua

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,6 @@ local config = require('opencode.config')
44
local M = {}
55

66
local presets = {
7-
emoji = {
8-
-- headers
9-
header_user = '▌💬',
10-
header_assistant = '🤖',
11-
-- actions/tools
12-
run = '💻',
13-
task = '🧰',
14-
read = '👀',
15-
edit = '✏️',
16-
write = '📝',
17-
plan = '📃',
18-
search = '🔍',
19-
web = '🌐',
20-
list = '📂',
21-
tool = '🔧',
22-
snapshot = '📸',
23-
restore_point = '🕛',
24-
file = '📄',
25-
attached_file = '📎',
26-
agent = '🤖',
27-
-- statuses
28-
status_on = '🟢',
29-
status_off = '',
30-
-- borders and misc
31-
border = '',
32-
-- context bar
33-
cursor_data = '📍',
34-
context = '📚 ',
35-
error = '',
36-
warning = '⚠️',
37-
info = 'ℹ️',
38-
},
397
nerdfonts = {
408
-- headers
419
header_user = '▌󰭻 ',
@@ -67,6 +35,7 @@ local presets = {
6735
error = '',
6836
warning = '',
6937
info = '',
38+
selection = '󰫙 ',
7039
},
7140
text = {
7241
-- headers
@@ -99,13 +68,12 @@ local presets = {
9968
error = '[E]',
10069
warning = '[W]',
10170
info = '[I] ',
71+
selection = "'<'> ",
10272
},
10373
}
10474

10575
local deprecated_warning_shown = false
10676

107-
local deprecated_warning_shown = false
108-
10977
---Get icon by key, honoring preset and user overrides
11078
---@param key string
11179
---@return string

0 commit comments

Comments
 (0)