@@ -11,8 +11,6 @@ local scheduler = require('opencode.ui.renderer.scheduler')
1111
1212local M = {}
1313
14- local trigger_on_data_rendered
15-
1614local function with_suppressed_scroll_tracking (fn )
1715 return output_window .with_suppressed_scroll_tracking (fn )
1816end
@@ -71,32 +69,15 @@ local function apply_render_plan(render_plan, should_scroll)
7169 return true
7270 end
7371
74- trigger_on_data_rendered ()
72+ M . trigger_on_data_rendered ()
7573 return true
7674end
7775
7876-- Expose event handlers on M so tests can call them directly and subscriptions
7977-- can be stubbed cleanly (e.g. stub(renderer, '_render_full_session_data'))
8078M .on_session_updated = events .on_session_updated
8179
82- trigger_on_data_rendered = require (' opencode.util' ).debounce (function ()
83- local cb_type = type (config .ui .output .rendering .on_data_rendered )
84- if cb_type == ' boolean' then
85- return
86- end
87- if not state .windows or not state .windows .output_buf or not state .windows .output_win then
88- return
89- end
90- if cb_type == ' function' then
91- pcall (config .ui .output .rendering .on_data_rendered , state .windows .output_buf , state .windows .output_win )
92- elseif vim .fn .exists (' :RenderMarkdown' ) > 0 then
93- vim .cmd (' :RenderMarkdown' )
94- elseif vim .fn .exists (' :Markview' ) > 0 then
95- vim .cmd (' :Markview render ' .. state .windows .output_buf )
96- end
97- end , config .ui .output .rendering .markdown_debounce_ms or 250 )
98-
99- local function trigger_on_data_rendered_now ()
80+ local function invoke_on_data_rendered ()
10081 local cb_type = type (config .ui .output .rendering .on_data_rendered )
10182 if cb_type == ' boolean' then
10283 return
@@ -113,8 +94,13 @@ local function trigger_on_data_rendered_now()
11394 end
11495end
11596
97+ M .trigger_on_data_rendered =
98+ require (' opencode.util' ).debounce (invoke_on_data_rendered , config .ui .output .rendering .markdown_debounce_ms or 250 )
99+
116100--- Reset all renderer state and clear the output buffer
117- function M .reset ()
101+ --- @param opts ? { trigger_on_data_rendered ?: boolean }
102+ function M .reset (opts )
103+ opts = opts or {}
118104 ctx :reset ()
119105 output_window .clear ()
120106
@@ -127,7 +113,9 @@ function M.reset()
127113 permission_window .clear_all ()
128114 state .renderer .reset ()
129115
130- trigger_on_data_rendered_now ()
116+ if opts .trigger_on_data_rendered ~= false then
117+ invoke_on_data_rendered ()
118+ end
131119end
132120
133121--- Unsubscribe from all events and reset
@@ -154,22 +142,22 @@ function M.setup_subscriptions(subscribe)
154142 end
155143
156144 local subs = {
157- { ' session.updated' , events .on_session_updated },
158- { ' session.compacted' , events .on_session_compacted },
159- { ' session.error' , events .on_session_error },
160- { ' message.updated' , events .on_message_updated },
161- { ' message.removed' , events .on_message_removed },
162- { ' message.part.updated' , events .on_part_updated },
163- { ' message.part.removed' , events .on_part_removed },
164- { ' permission.updated' , events .on_permission_updated },
165- { ' permission.asked' , events .on_permission_updated },
166- { ' permission.replied' , events .on_permission_replied },
167- { ' question.asked' , events .on_question_asked },
168- { ' question.replied' , events .clear_question_display },
169- { ' question.rejected' , events .clear_question_display },
170- { ' file.edited' , events .on_file_edited },
171- { ' custom.restore_point.created' , events .on_restore_points },
172- { ' custom.emit_events.finished' , M .on_emit_events_finished },
145+ { ' session.updated' , events .on_session_updated },
146+ { ' session.compacted' , events .on_session_compacted },
147+ { ' session.error' , events .on_session_error },
148+ { ' message.updated' , events .on_message_updated },
149+ { ' message.removed' , events .on_message_removed },
150+ { ' message.part.updated' , events .on_part_updated },
151+ { ' message.part.removed' , events .on_part_removed },
152+ { ' permission.updated' , events .on_permission_updated },
153+ { ' permission.asked' , events .on_permission_updated },
154+ { ' permission.replied' , events .on_permission_replied },
155+ { ' question.asked' , events .on_question_asked },
156+ { ' question.replied' , events .clear_question_display },
157+ { ' question.rejected' , events .clear_question_display },
158+ { ' file.edited' , events .on_file_edited },
159+ { ' custom.restore_point.created' , events .on_restore_points },
160+ { ' custom.emit_events.finished' , M .on_emit_events_finished },
173161 }
174162
175163 for _ , sub in ipairs (subs ) do
214202--- Called after a full session fetch or when revert state changes
215203--- @param session_data OpencodeMessage[]
216204function M ._render_full_session_data (session_data )
217- M .reset ()
205+ M .reset ({ trigger_on_data_rendered = false } )
218206
219207 if not state .active_session then
220208 return
@@ -308,15 +296,13 @@ function M.scroll_to_bottom(force)
308296 local prev_line_count = ctx .prev_line_count
309297 ctx .prev_line_count = line_count
310298
311- trigger_on_data_rendered ()
312-
313299 local should_scroll = force
314300 or prev_line_count == 0
315301 or config .ui .output .always_scroll_to_bottom
316302 or (function ()
317- local ok_cursor , cursor = pcall (vim .api .nvim_win_get_cursor , output_win )
318- return ok_cursor and cursor and (cursor [1 ] >= prev_line_count or cursor [1 ] >= line_count )
319- end )()
303+ local ok_cursor , cursor = pcall (vim .api .nvim_win_get_cursor , output_win )
304+ return ok_cursor and cursor and (cursor [1 ] >= prev_line_count or cursor [1 ] >= line_count )
305+ end )()
320306
321307 if should_scroll then
322308 with_suppressed_scroll_tracking (function ()
@@ -328,7 +314,7 @@ function M.scroll_to_bottom(force)
328314 end )
329315 end
330316
331- trigger_on_data_rendered ()
317+ M . trigger_on_data_rendered ()
332318end
333319
334320--- Re-render the permission display when focus changes (updates shortcut hints)
@@ -345,11 +331,11 @@ function M.on_session_changed(_, new, old)
345331 return
346332 end
347333
348- if new and ctx .last_rendered_session_id == new .id and state .messages ~= nil then
334+ if new and ctx .last_rendered_session_id == new .id and state .messages ~= nil then
349335 return
350336 end
351337
352- M .reset ()
338+ M .reset ({ trigger_on_data_rendered = not new } )
353339 if new then
354340 M .render_full_session ()
355341 end
0 commit comments