@@ -1223,7 +1223,7 @@ function M:_handle_server_content(params)
12231223 -- IMPORTANT: Return immediately - do NOT display anything for toolCallPrepare
12241224 return
12251225 elseif content .type == " toolCalled" then
1226- local tool_text = " "
1226+ local tool_text = nil
12271227
12281228 -- Add diff to current tool call if present in toolCalled content
12291229 if self ._current_tool_call and content .details then
@@ -1254,7 +1254,7 @@ function M:_handle_server_content(params)
12541254
12551255 tool_text_completed = tool_text_completed .. (content .summary or content .name or " Tool call completed" )
12561256
1257- if not self :_replace_text (tool_text , tool_text_completed ) then
1257+ if tool_text == nil or not self :_replace_text (tool_text or " " , tool_text_completed ) then
12581258 self :_add_message (" assistant" , tool_text_completed )
12591259 end
12601260
@@ -1559,7 +1559,7 @@ end
15591559
15601560--- @return string tool text
15611561function M :_display_tool_call ()
1562- if not self ._current_tool_call then return " " end
1562+ if not self ._current_tool_call then return nil end
15631563
15641564 local diff = " "
15651565 local tool_text = " 🔧 " .. (self ._current_tool_call .summary or " Tool call prepared" )
@@ -1586,8 +1586,9 @@ end
15861586
15871587--- @param target string
15881588--- @param replacement string
1589+ --- @param opts ? table | nil Optional search options : { max_search_lines = number , start_line = number }
15891590--- @return boolean changed True if any replacement was made
1590- function M :_replace_text (target , replacement )
1591+ function M :_replace_text (target , replacement , opts )
15911592 local chat = self .containers .chat
15921593
15931594 if not chat or not vim .api .nvim_buf_is_valid (chat .bufnr ) then
@@ -1608,14 +1609,31 @@ function M:_replace_text(target, replacement)
16081609 local changed = false
16091610
16101611 self :_safe_buffer_update (chat .bufnr , function ()
1611- local lines = vim .api .nvim_buf_get_lines (chat .bufnr , 0 , - 1 , false )
1612+ local total_lines = vim .api .nvim_buf_line_count (chat .bufnr )
1613+ opts = opts or {}
1614+
1615+ -- Limit how many lines to search for performance with large buffers
1616+ local max_search_lines = tonumber (opts .max_search_lines ) or 500
1617+
1618+ -- If a start line is provided, start searching from there (useful for targeted replacement)
1619+ local start_line = tonumber (opts .start_line ) or total_lines
1620+ if start_line < 1 then start_line = 1 end
1621+ if start_line > total_lines then start_line = total_lines end
1622+
1623+ -- Determine the search window [end_line, start_line]
1624+ local end_line = math.max (1 , start_line - max_search_lines + 1 )
1625+
1626+ -- Fetch only the relevant range once (0-based indices for nvim API)
1627+ local range_lines = vim .api .nvim_buf_get_lines (chat .bufnr , end_line - 1 , start_line , false )
16121628
1613- for i = # lines , 1 , - 1 do
1614- local line = lines [i ] or " "
1629+ -- Iterate from bottom to top within the range
1630+ for idx = # range_lines , 1 , - 1 do
1631+ local line = range_lines [idx ] or " "
16151632 local s_idx , e_idx = line :find (target , 1 , true )
16161633 if s_idx then
16171634 local new_line = (line :sub (1 , s_idx - 1 )) .. replacement .. (line :sub (e_idx + 1 ))
1618- vim .api .nvim_buf_set_lines (chat .bufnr , i - 1 , i , false , { new_line })
1635+ local absolute_line = end_line + idx - 1 -- convert to absolute 1-based line
1636+ vim .api .nvim_buf_set_lines (chat .bufnr , absolute_line - 1 , absolute_line , false , { new_line })
16191637 changed = true
16201638 break
16211639 end
0 commit comments