@@ -11,6 +11,7 @@ M._subscriptions = {}
1111M ._prev_line_count = 0
1212M ._render_state = RenderState .new ()
1313M ._disable_auto_scroll = false
14+ M ._last_part_formatted = { part_id = nil , formatted_data = nil }
1415
1516local trigger_on_data_rendered = require (' opencode.util' ).debounce (function ()
1617 local cb_type = type (config .ui .output .rendering .on_data_rendered )
@@ -37,6 +38,7 @@ function M.reset()
3738 M ._prev_line_count = 0
3839 M ._render_state :reset ()
3940 M ._disable_auto_scroll = false
41+ M ._last_part_formatted = { part_id = nil , formatted_data = nil }
4042
4143 output_window .clear ()
4244
@@ -251,6 +253,9 @@ function M._insert_part_to_buffer(part_id, formatted_data)
251253 end
252254
253255 M ._render_state :set_part (cached .part , range .line_start , range .line_end )
256+
257+ M ._last_part_formatted = { part_id = part_id , formatted_data = formatted_data }
258+
254259 return true
255260end
256261
@@ -267,11 +272,42 @@ function M._replace_part_in_buffer(part_id, formatted_data)
267272
268273 local new_lines = formatted_data .lines
269274 local new_line_count = # new_lines
275+ -- local old_line_count = cached.line_end - cached.line_start + 1
276+
277+ local old_formatted = M ._last_part_formatted
278+ local can_optimize = old_formatted
279+ and old_formatted .part_id == part_id
280+ and old_formatted .formatted_data
281+ and old_formatted .formatted_data .lines
282+
283+ local lines_to_write = new_lines
284+ local write_start_line = cached .line_start
285+
286+ if can_optimize then
287+ local old_lines = old_formatted .formatted_data .lines
288+ local first_diff_line = nil
289+
290+ for i = 1 , math.min (# old_lines , new_line_count ) do
291+ if old_lines [i ] ~= new_lines [i ] then
292+ first_diff_line = i
293+ break
294+ end
295+ end
296+
297+ if not first_diff_line and new_line_count > # old_lines then
298+ first_diff_line = # old_lines + 1
299+ end
300+
301+ if first_diff_line then
302+ lines_to_write = vim .list_slice (new_lines , first_diff_line , new_line_count )
303+ write_start_line = cached .line_start + first_diff_line - 1
304+ end
305+ end
270306
271307 M ._render_state :clear_actions (part_id )
272308
273309 output_window .clear_extmarks (cached .line_start - 1 , cached .line_end + 1 )
274- output_window .set_lines (new_lines , cached . line_start , cached .line_end + 1 )
310+ output_window .set_lines (lines_to_write , write_start_line , cached .line_end + 1 )
275311
276312 local new_line_end = cached .line_start + new_line_count - 1
277313
@@ -283,6 +319,8 @@ function M._replace_part_in_buffer(part_id, formatted_data)
283319
284320 M ._render_state :update_part_lines (part_id , cached .line_start , new_line_end )
285321
322+ M ._last_part_formatted = { part_id = part_id , formatted_data = formatted_data }
323+
286324 return true
287325end
288326
0 commit comments