Skip to content

Commit 22296c0

Browse files
Copilotolimorris
andcommitted
Fine-tune spacing logic and add comprehensive tests
Co-authored-by: olimorris <[email protected]>
1 parent 3fcd62e commit 22296c0

File tree

2 files changed

+69
-26
lines changed

2 files changed

+69
-26
lines changed

lua/codecompanion/strategies/chat/ui/spacing.lua

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,14 @@ function Spacing.get_pre_content_spacing(context, message_types)
2828

2929
-- Handle new sections (when type changes but role stays the same)
3030
if context.is_new_section then
31-
-- Less spacing for section transitions within same role
31+
-- Only add spacing for LLM to Tool transitions
3232
if context.previous_type == message_types.LLM_MESSAGE
3333
and context.current_type == message_types.TOOL_MESSAGE then
3434
table.insert(lines, "")
35-
elseif context.previous_type == message_types.TOOL_MESSAGE
36-
and context.current_type == message_types.LLM_MESSAGE then
37-
table.insert(lines, "")
3835
end
3936
return lines
4037
end
4138

42-
-- For reasoning start, no extra spacing needed as header handles it
43-
if context.is_reasoning_start then
44-
return lines
45-
end
46-
4739
return lines
4840
end
4941

tests/strategies/chat/test_ui_spacing.lua

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ T = new_set({
2525

2626
T["UI Spacing Refactor"] = new_set()
2727

28-
T["UI Spacing Refactor"]["basic tool output has reduced spacing"] = function()
28+
T["UI Spacing Refactor"]["reduced spacing between LLM and tool messages"] = function()
2929
local result = child.lua([[
3030
-- Add a user message first
3131
_G.chat.builder:add_message({
@@ -47,28 +47,39 @@ T["UI Spacing Refactor"]["basic tool output has reduced spacing"] = function()
4747
4848
local lines = h.get_buf_lines(_G.chat.bufnr)
4949
50-
-- Count consecutive empty lines after tool output
51-
local consecutive_empty = 0
52-
local max_consecutive_empty = 0
50+
-- Find the position of LLM message and tool message
51+
local llm_line_idx = nil
52+
local tool_line_idx = nil
5353
for i, line in ipairs(lines) do
54-
if line == "" then
55-
consecutive_empty = consecutive_empty + 1
56-
max_consecutive_empty = math.max(max_consecutive_empty, consecutive_empty)
57-
else
58-
consecutive_empty = 0
54+
if line:match("I'll help you with that") then
55+
llm_line_idx = i
56+
elseif line:match("Tool executed successfully") then
57+
tool_line_idx = i
58+
end
59+
end
60+
61+
-- Count empty lines between LLM and tool message
62+
local empty_lines_between = 0
63+
if llm_line_idx and tool_line_idx then
64+
for i = llm_line_idx + 1, tool_line_idx - 1 do
65+
if lines[i] == "" then
66+
empty_lines_between = empty_lines_between + 1
67+
end
5968
end
6069
end
6170
6271
return {
6372
buffer_lines = lines,
64-
max_consecutive_empty = max_consecutive_empty,
65-
total_lines = #lines
73+
llm_line_idx = llm_line_idx,
74+
tool_line_idx = tool_line_idx,
75+
empty_lines_between = empty_lines_between
6676
}
6777
]])
6878

69-
-- Should have significantly fewer consecutive empty lines
70-
h.leq(result.max_consecutive_empty, 2) -- At most 2 consecutive empty lines
71-
h.neq(result.total_lines, 0) -- Should have content
79+
-- Should have at most 1 empty line between LLM message and tool output (improved from before)
80+
h.leq(result.empty_lines_between, 1)
81+
h.neq(result.llm_line_idx, nil) -- Should find LLM message
82+
h.neq(result.tool_line_idx, nil) -- Should find tool message
7283
end
7384

7485
T["UI Spacing Refactor"]["reasoning to response transition works"] = function()
@@ -93,26 +104,66 @@ T["UI Spacing Refactor"]["reasoning to response transition works"] = function()
93104
94105
local lines = h.get_buf_lines(_G.chat.bufnr)
95106
96-
-- Check for reasoning header
107+
-- Check for reasoning header and response header
97108
local has_reasoning_header = false
98109
local has_response_header = false
99-
for _, line in ipairs(lines) do
110+
local response_header_line = nil
111+
for i, line in ipairs(lines) do
100112
if line:match("### Reasoning") then
101113
has_reasoning_header = true
102114
elseif line:match("### Response") then
103115
has_response_header = true
116+
response_header_line = i
104117
end
105118
end
106119
107120
return {
108121
buffer_lines = lines,
109122
has_reasoning_header = has_reasoning_header,
110-
has_response_header = has_response_header
123+
has_response_header = has_response_header,
124+
response_header_line = response_header_line
111125
}
112126
]])
113127

114128
h.eq(result.has_reasoning_header, true)
115129
h.eq(result.has_response_header, true)
130+
h.neq(result.response_header_line, nil)
131+
end
132+
133+
T["UI Spacing Refactor"]["tool output has proper trailing spacing for folding"] = function()
134+
local result = child.lua([[
135+
-- Add tool output
136+
_G.chat.builder:add_message({
137+
role = "llm",
138+
content = "Tool executed successfully\\nWith multiple lines\\nOf output"
139+
}, { type = _G.chat.MESSAGE_TYPES.TOOL_MESSAGE })
140+
141+
local lines = h.get_buf_lines(_G.chat.bufnr)
142+
143+
-- Find the last line of tool content
144+
local last_content_line_idx = nil
145+
for i = #lines, 1, -1 do
146+
if lines[i]:match("Of output") then
147+
last_content_line_idx = i
148+
break
149+
end
150+
end
151+
152+
-- Check if there's a trailing empty line after tool content
153+
local has_trailing_empty = false
154+
if last_content_line_idx and last_content_line_idx < #lines then
155+
has_trailing_empty = lines[last_content_line_idx + 1] == ""
156+
end
157+
158+
return {
159+
buffer_lines = lines,
160+
last_content_line_idx = last_content_line_idx,
161+
has_trailing_empty = has_trailing_empty
162+
}
163+
]])
164+
165+
h.neq(result.last_content_line_idx, nil) -- Should find tool content
166+
h.eq(result.has_trailing_empty, true) -- Should have trailing empty line for folding
116167
end
117168

118169
return T

0 commit comments

Comments
 (0)