Skip to content

Commit 3f640d1

Browse files
committed
feat(output): add toggle for maximum rendered messages
Add a workflow action and command to toggle ui.output.max_messages between a finite number and nil (no limit). Wire the action into the API, keymaps (<leader>otm), types, and UI so users can enable/disable the message limit from the output notice or via command. The toggle notifies the user of the current state. Also ensure render_output returns its promise/value so callers can await rendering when requested.
1 parent 4fd943c commit 3f640d1

File tree

7 files changed

+56
-11
lines changed

7 files changed

+56
-11
lines changed

lua/opencode/api.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ local action_groups = {
8989
debug_session = workflow.debug_session,
9090
toggle_tool_output = workflow.toggle_tool_output,
9191
toggle_reasoning_output = workflow.toggle_reasoning_output,
92+
toggle_max_messages = workflow.toggle_max_messages,
9293
submit_input_prompt = workflow.submit_input_prompt,
9394
run = workflow.run,
9495
run_new_session = workflow.run_new_session,

lua/opencode/commands/handlers/workflow.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,22 @@ function M.actions.toggle_reasoning_output()
283283
ui.render_output()
284284
end
285285

286+
local original_max_messages = config.ui.output.max_messages
287+
function M.actions.toggle_max_messages()
288+
local current = config.ui.output.max_messages
289+
local next_val
290+
if type(current) == 'number' and current > 0 then
291+
next_val = nil
292+
else
293+
next_val = original_max_messages or 20
294+
end
295+
296+
local action_text = next_val == nil and 'Disabling' or 'Enabling'
297+
local val_text = next_val == nil and 'none' or tostring(next_val)
298+
vim.notify(action_text .. ' message limit to ' .. val_text, vim.log.levels.INFO)
299+
config.values.ui.output.max_messages = next_val
300+
end
301+
286302
M.actions.review = Promise.async(function(args)
287303
local new_session = core.create_new_session('Code review checklist for diffs and PRs'):await()
288304
if not new_session then
@@ -453,6 +469,10 @@ M.command_defs = {
453469
desc = 'Toggle reasoning output visibility in the output window',
454470
execute = M.actions.toggle_reasoning_output,
455471
},
472+
toggle_max_messages = {
473+
desc = 'Toggle maximum number of rendered messages',
474+
execute = M.actions.toggle_max_messages,
475+
},
456476
paste_image = {
457477
desc = 'Paste image from clipboard and add to context',
458478
execute = M.actions.paste_image,

lua/opencode/config.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ M.defaults = {
5656
['<leader>ox'] = { 'swap_position', desc = 'Swap window position' },
5757
['<leader>otr'] = { 'toggle_reasoning_output', desc = 'Toggle reasoning output' },
5858
['<leader>ott'] = { 'toggle_tool_output', desc = 'Toggle tool output' },
59+
['<leader>otm'] = { 'toggle_max_messages', desc = 'Toggle max messages' },
5960
['<leader>o/'] = { 'quick_chat', mode = { 'n', 'x' }, desc = 'Quick chat with current context' },
61+
6062
},
6163
output_window = {
6264
['<esc>'] = { 'close', desc = 'Close Opencode windows' },

lua/opencode/types.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@
499499

500500
---@class OutputAction
501501
---@field text string Action text
502-
---@field type 'diff_revert_all'|'diff_revert_selected_file'|'diff_open'|'diff_restore_snapshot_file'|'diff_restore_snapshot_all'|'select_child_session' Type of action
502+
---@field type 'diff_revert_all'|'diff_revert_selected_file'|'diff_open'|'diff_restore_snapshot_file'|'diff_restore_snapshot_all'|'select_child_session'|'toggle_max_messages'
503503
---@field args? string[] Optional arguments for the command
504504
---@field key string keybinding for the action
505505
---@field display_line number Line number to display the action

lua/opencode/ui/formatter.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ function M._format_hidden_messages_notice(hidden_count)
106106
local message_text = hidden_count == 1 and 'message is' or 'messages are'
107107

108108
output:add_line(string.format('> %d older %s not displayed.', hidden_count, message_text))
109+
output:add_action({
110+
text = 'Show [A]ll messages',
111+
type = 'toggle_max_messages',
112+
args = {},
113+
key = 'A',
114+
display_line = output:get_line_count() - 1,
115+
range = { from = output:get_line_count() - 1, to = output:get_line_count() - 1 },
116+
})
109117
output:add_empty_line()
110118

111119
return output

lua/opencode/ui/renderer.lua

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,31 @@ local function upsert_hidden_messages_notice(hidden_count)
141141

142142
if not existing_message then
143143
ensure_message_rendered(notice_message)
144-
return
144+
else
145+
local existing_part = ctx.render_state:get_part(HIDDEN_MESSAGES_NOTICE_PART_ID)
146+
if not existing_part or not existing_part.part then
147+
hide_rendered_message(HIDDEN_MESSAGES_NOTICE_MESSAGE_ID)
148+
ensure_message_rendered(notice_message)
149+
else
150+
ctx.render_state:set_message(notice_message, existing_message.line_start, existing_message.line_end)
151+
ctx.render_state:set_part(notice_message.parts[1], existing_part.line_start, existing_part.line_end)
152+
end
145153
end
146154

147-
local existing_part = ctx.render_state:get_part(HIDDEN_MESSAGES_NOTICE_PART_ID)
148-
if not existing_part or not existing_part.part then
149-
hide_rendered_message(HIDDEN_MESSAGES_NOTICE_MESSAGE_ID)
150-
ensure_message_rendered(notice_message)
151-
return
155+
local part_data = ctx.render_state:get_part(HIDDEN_MESSAGES_NOTICE_PART_ID)
156+
if part_data then
157+
ctx.render_state:add_actions(HIDDEN_MESSAGES_NOTICE_PART_ID, {
158+
{
159+
text = 'Toggle Max Messages',
160+
type = 'toggle_max_messages',
161+
args = {},
162+
key = 'm',
163+
range = { from = part_data.line_start, to = part_data.line_end },
164+
display_line = part_data.line_start,
165+
},
166+
})
167+
flush.mark_part_dirty(HIDDEN_MESSAGES_NOTICE_PART_ID, HIDDEN_MESSAGES_NOTICE_MESSAGE_ID)
152168
end
153-
154-
ctx.render_state:set_message(notice_message, existing_message.line_start, existing_message.line_end)
155-
ctx.render_state:set_part(notice_message.parts[1], existing_part.line_start, existing_part.line_end)
156-
flush.mark_part_dirty(HIDDEN_MESSAGES_NOTICE_PART_ID, HIDDEN_MESSAGES_NOTICE_MESSAGE_ID)
157169
end
158170

159171
---@param message_id string

lua/opencode/ui/ui.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,12 +473,14 @@ end
473473
---from opencode
474474
---@param synchronous? boolean If true, waits until session is fully rendered
475475
---@param opts? {force_scroll?: boolean}
476+
---@return Promise<OpencodeMessage[]> | OpencodeMessage[] | nil
476477
function M.render_output(synchronous, opts)
477478
local ret = renderer.render_full_session(opts)
478479

479480
if ret and synchronous then
480481
ret:wait()
481482
end
483+
return ret
482484
end
483485

484486
---@param lines string[]

0 commit comments

Comments
 (0)