Skip to content

Commit 16ea44c

Browse files
committed
feat(ui): default expr-based output folds closed and apply fold ranges immediately
- Set default foldlevel to 0 for expr-based output so folds start closed. - Replace manual window/fold manipulation with a safe window-call that triggers a fold recalc (zX) only when the output window is valid and displays the output buffer. - Persist fold ranges to buffer var opencode_folds. - Add unit tests asserting default closed folds and immediate application of fold ranges.
1 parent 50d8d23 commit 16ea44c

4 files changed

Lines changed: 33 additions & 24 deletions

File tree

lua/opencode/ui/formatter/tools/todowrite.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ function M.format(output, part)
2525
end
2626

2727
local statuses = { in_progress = '-', completed = 'x', pending = ' ' }
28-
local todos = part.state and part.state.input and part.state.input.todos or {}
28+
local todos = part.state and part.state.input and type(part.state.input.todos) == 'table' and part.state.input.todos
29+
or {}
30+
2931
for _, item in ipairs(todos) do
3032
output:add_line(string.format('- [%s] %s ', statuses[item.status], item.content))
3133
end

lua/opencode/ui/output_window.lua

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ function M.setup(windows)
189189
window_options.set_window_option('foldmethod', 'expr', windows.output_win)
190190
window_options.set_window_option('foldexpr', 'v:lua.opencode_fold_expr()', windows.output_win)
191191
window_options.set_window_option('foldenable', true, windows.output_win)
192-
window_options.set_window_option('foldlevel', 99, windows.output_win)
192+
window_options.set_window_option('foldlevel', 0, windows.output_win)
193193
window_options.set_window_option('foldcolumn', '1', windows.output_win)
194194
window_options.set_window_option('foldtext', 'v:lua.opencode_fold_text()', windows.output_win)
195195

@@ -324,32 +324,18 @@ _G.opencode_fold_text = M.fold_text
324324
---@param fold_ranges table<{from: number, to: number}>
325325
function M.set_folds(fold_ranges)
326326
local windows = state.windows
327-
local output_win = windows and windows.output_win
328327
if not windows or not windows.output_buf or not vim.api.nvim_buf_is_valid(windows.output_buf) then
329328
return
330329
end
331330

332331
local folds = fold_ranges or {}
333-
vim.api.nvim_buf_set_var(windows.output_buf, 'opencode_folds', folds)
334-
335-
if output_win and vim.api.nvim_win_is_valid(output_win) then
336-
local win = output_win
337-
local buf = windows.output_buf
338-
local folds = fold_ranges or {}
339-
vim.schedule(function()
340-
if vim.api.nvim_win_is_valid(win) and vim.api.nvim_buf_is_valid(buf) then
341-
local prev_win = vim.api.nvim_get_current_win()
342-
vim.api.nvim_set_current_win(win)
343-
local orig_foldmethod = vim.api.nvim_get_option_value('foldmethod', { win = win })
344-
vim.api.nvim_set_option_value('foldmethod', 'manual', { win = win })
345-
for _, range in ipairs(folds) do
346-
if range.from < range.to then
347-
vim.cmd(string.format('%d,%dfold', range.from, range.to))
348-
end
349-
end
350-
vim.api.nvim_set_option_value('foldmethod', orig_foldmethod, { win = win })
351-
vim.api.nvim_set_current_win(prev_win)
352-
end
332+
local buf = windows.output_buf
333+
local win = windows.output_win
334+
vim.api.nvim_buf_set_var(buf, 'opencode_folds', folds)
335+
336+
if win and vim.api.nvim_win_is_valid(win) and vim.api.nvim_win_get_buf(win) == buf then
337+
pcall(vim.api.nvim_win_call, win, function()
338+
vim.cmd('silent! normal! zX')
353339
end)
354340
end
355341
end

lua/opencode/ui/topbar.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ function M.render()
8383

8484
vim.wo[win].winbar = ' '
8585

86-
local desc = get_session_desc()
86+
local desc = get_session_desc():gsub('%%', '%%%%')
8787
local token_info = format_token_info()
8888
local winbar_str = create_winbar_text(desc, token_info, vim.api.nvim_win_get_width(win))
8989
vim.wo[win].winbar = winbar_str

tests/unit/output_window_spec.lua

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,27 @@ describe('output_window.setup', function()
143143
local cursorline = vim.api.nvim_get_option_value('cursorline', { win = win })
144144
assert.is_false(cursorline)
145145
end)
146+
147+
it('defaults folds to closed for expr-based output folds', function()
148+
output_window.setup({ output_buf = buf, output_win = win })
149+
150+
local foldlevel = vim.api.nvim_get_option_value('foldlevel', { win = win })
151+
152+
assert.equals(0, foldlevel)
153+
end)
154+
155+
it('applies closed folds immediately when fold ranges change', function()
156+
output_window.setup({ output_buf = buf, output_win = win })
157+
output_window.set_lines({ 'a', 'b', 'c', 'd' })
158+
159+
output_window.set_folds({ { from = 1, to = 3 } })
160+
161+
local foldclosed = vim.api.nvim_win_call(win, function()
162+
return vim.fn.foldclosed(1)
163+
end)
164+
165+
assert.equals(1, foldclosed)
166+
end)
146167
end)
147168

148169
describe('output_window extmarks', function()

0 commit comments

Comments
 (0)