Skip to content

Commit a3ee9d2

Browse files
committed
refactor: move full session loading to renderer
also: - move settings lines / extmarks into output_window - loading_animation subscribes for states now
1 parent 2a42ed7 commit a3ee9d2

File tree

12 files changed

+169
-117
lines changed

12 files changed

+169
-117
lines changed

lua/opencode/api.lua

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -574,16 +574,17 @@ function M.undo()
574574
return
575575
end
576576

577-
ui.render_output(true)
577+
-- ui.render_output(true)
578578
state.api_client
579579
:revert_message(state.active_session.id, {
580580
messageID = last_user_message.id,
581581
})
582582
:and_then(function(response)
583583
state.active_session.revert = response.revert
584584
vim.schedule(function()
585+
-- FIXME: shouldn't require a full re-render
585586
vim.notify('Last message undone successfully', vim.log.levels.INFO)
586-
require('opencode.ui.renderer').reset_and_render()
587+
require('opencode.ui.renderer').render_full_session()
587588
end)
588589
end)
589590
:catch(function(err)
@@ -605,8 +606,9 @@ function M.redo()
605606
:and_then(function(response)
606607
state.active_session.revert = response.revert
607608
vim.schedule(function()
608-
vim.notify('Last message rerterted successfully', vim.log.levels.INFO)
609-
require('opencode.ui.renderer').reset_and_render()
609+
-- FIXME: shouldn't require a full re-render
610+
vim.notify('Last message reverted successfully', vim.log.levels.INFO)
611+
require('opencode.ui.renderer').render_full_session()
610612
end)
611613
end)
612614
:catch(function(err)

lua/opencode/core.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ function M.open(opts)
5454
state.active_session = nil
5555
state.last_sent_context = nil
5656
state.active_session = M.create_new_session()
57+
58+
-- FIXME: shouldn't need to clear_output here, setting the session should
59+
-- do that
5760
ui.clear_output()
5861
else
5962
if not state.active_session then

lua/opencode/ui/footer.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ local icons = require('opencode.ui.icons')
55
local output_window = require('opencode.ui.output_window')
66
local snapshot = require('opencode.snapshot')
77
local config_file = require('opencode.config_file')
8+
local loading_animation = require('opencode.ui.loading_animation')
89

910
local M = {}
1011

@@ -89,6 +90,8 @@ function M.setup(windows)
8990
-- to show C-c message
9091
state.subscribe('job_count', on_job_count_changed)
9192
state.subscribe('restore_points', on_change)
93+
94+
loading_animation.setup()
9295
end
9396

9497
function M.close()
@@ -100,6 +103,8 @@ function M.close()
100103
state.unsubscribe('current_model', on_change)
101104
state.unsubscribe('job_count', on_job_count_changed)
102105
state.unsubscribe('restore_points', on_change)
106+
107+
loading_animation.teardown()
103108
end
104109

105110
function M.mounted(windows)

lua/opencode/ui/formatter.lua

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,15 @@ function M.format_session(session)
2828
state.last_user_message = nil
2929
return require('opencode.session').get_messages(session):and_then(function(msgs)
3030
vim.notify('formatting session', vim.log.levels.WARN)
31-
return M._format_messages(session, msgs)
31+
state.messages = msgs
32+
return M._format_messages(session)
3233
end)
3334
end
3435

35-
function M._format_messages(session, messages)
36-
state.messages = messages
37-
36+
function M._format_messages(session)
3837
M.output:clear()
3938

40-
-- M.output:add_line('')
41-
-- M.output:add_line('')
39+
M.output:add_line('')
4240

4341
for i, msg in ipairs(state.messages) do
4442
M.output:add_lines(M.separator)
@@ -77,8 +75,7 @@ function M._format_messages(session, messages)
7775
end
7876
end
7977

80-
-- M.output:add_empty_line()
81-
return M.output:get_lines()
78+
return M.output
8279
end
8380

8481
function M._handle_permission_request(part)

lua/opencode/ui/loading_animation.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ local function on_running_change(_, new_value)
117117
end
118118
end
119119

120-
function M.setup_subscription()
120+
function M.setup()
121121
state.subscribe('job_count', on_running_change)
122122
end
123123

lua/opencode/ui/output_renderer.lua

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -57,28 +57,32 @@ M.render = vim.schedule_wrap(function(windows, force)
5757
end)
5858

5959
function M.setup_subscriptions(windows)
60-
M._cleanup_subscriptions()
61-
loading_animation.setup_subscription()
62-
63-
local on_change = util.debounce(function(old, new)
64-
M.render(windows, true)
65-
end, M._debounce_ms)
6660

67-
M._subscriptions.active_session = function(_, new, old)
68-
if not old then
69-
return
70-
end
71-
on_change(old, new)
72-
end
73-
state.subscribe('active_session', M._subscriptions.active_session)
61+
-- NOTE: output_renderer no longer renders automatically
62+
-- only leaving this code for now, in case we want to use
63+
-- this old pathway. will be removed in the near future
64+
65+
-- M._cleanup_subscriptions()
66+
67+
-- local on_change = util.debounce(function(old, new)
68+
-- M.render(windows, true)
69+
-- end, M._debounce_ms)
70+
--
71+
-- M._subscriptions.active_session = function(_, new, old)
72+
-- if not old then
73+
-- return
74+
-- end
75+
-- on_change(old, new)
76+
-- end
77+
-- state.subscribe('active_session', M._subscriptions.active_session)
7478
end
7579

7680
function M._cleanup_subscriptions()
77-
for key, cb in pairs(M._subscriptions) do
78-
state.unsubscribe(key, cb)
79-
end
80-
M._subscriptions = {}
81-
loading_animation.teardown()
81+
-- for key, cb in pairs(M._subscriptions) do
82+
-- state.unsubscribe(key, cb)
83+
-- end
84+
-- M._subscriptions = {}
85+
-- loading_animation.teardown()
8286
end
8387

8488
function M.teardown()
@@ -87,9 +91,9 @@ function M.teardown()
8791
end
8892

8993
function M.stop()
90-
-- FIXME: the footer should probably own this... and it may
91-
-- not even be necessary
92-
loading_animation.stop()
94+
-- -- FIXME: the footer should probably own this... and it may
95+
-- -- not even be necessary
96+
-- loading_animation.stop()
9397
end
9498

9599
function M.write_output(windows, output_lines)

lua/opencode/ui/output_window.lua

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local state = require('opencode.state')
22
local config = require('opencode.config')
33

44
local M = {}
5+
M.namespace = vim.api.nvim_create_namespace('opencode_output')
56

67
function M.create_buf()
78
local output_buf = vim.api.nvim_create_buf(false, true)
@@ -51,8 +52,9 @@ function M.setup(windows)
5152
M.update_dimensions(windows)
5253
M.setup_keymaps(windows)
5354
state.subscribe('restore_points', function(_, new_val, old_val)
54-
local outout_renderer = require('opencode.ui.output_renderer')
55-
outout_renderer.render(state.windows, true)
55+
-- FIXME: restore points
56+
-- local outout_renderer = require('opencode.ui.output_renderer')
57+
-- outout_renderer.render(state.windows, true)
5658
end)
5759
end
5860

@@ -63,21 +65,74 @@ function M.update_dimensions(windows)
6365
vim.api.nvim_win_set_config(windows.output_win, { width = width })
6466
end
6567

66-
function M.set_content(lines)
68+
function M.get_buf_line_count()
69+
if not M.mounted() then
70+
return 0
71+
end
72+
73+
return vim.api.nvim_buf_line_count(state.windows.output_buf)
74+
end
75+
76+
---Set the output buffer contents
77+
---@param lines string[] The lines to set
78+
---@param start_line? integer The starting line to set, defaults to 0
79+
---@param end_line? integer The last line to set, defaults to -1
80+
function M.set_lines(lines, start_line, end_line)
6781
if not M.mounted() then
6882
return
6983
end
7084

85+
start_line = start_line or 0
86+
end_line = end_line or -1
87+
7188
local windows = state.windows
7289
if not windows or not windows.output_buf then
7390
return
7491
end
92+
7593
vim.api.nvim_set_option_value('modifiable', true, { buf = windows.output_buf })
76-
local padded = vim.tbl_extend('force', {}, lines)
77-
vim.api.nvim_buf_set_lines(windows.output_buf, 0, -1, false, padded)
94+
vim.api.nvim_buf_set_lines(windows.output_buf, start_line, end_line, false, lines)
7895
vim.api.nvim_set_option_value('modifiable', false, { buf = windows.output_buf })
7996
end
8097

98+
---Clear output buf extmarks
99+
---@param start_line? integer Line to start clearing, defaults 0
100+
---@param end_line? integer Line to to clear until, defaults to -1
101+
function M.clear_extmarks(start_line, end_line)
102+
if not M.mounted() or not state.windows.output_buf then
103+
return
104+
end
105+
106+
start_line = start_line or 0
107+
end_line = end_line or -1
108+
109+
vim.api.nvim_buf_clear_namespace(state.windows.output_buf, M.namespace, start_line, end_line)
110+
end
111+
112+
---Apply extmarks to the output buffer
113+
---@param extmarks table<number, OutputExtmark> Extmarks indexed by line
114+
---@param line_offset? integer Line offset to apply to extmarks, defaults to 0
115+
function M.set_extmarks(extmarks, line_offset)
116+
if not M.mounted() or not extmarks or type(extmarks) ~= 'table' then
117+
return
118+
end
119+
120+
line_offset = line_offset or 0
121+
122+
local output_buf = state.windows.output_buf
123+
124+
for line_idx, marks in pairs(extmarks) do
125+
for _, mark in ipairs(marks) do
126+
local actual_mark = type(mark) == 'function' and mark() or mark
127+
local target_line = line_offset + line_idx - 1
128+
if actual_mark.end_row then
129+
actual_mark.end_row = actual_mark.end_row + line_offset
130+
end
131+
pcall(vim.api.nvim_buf_set_extmark, output_buf, M.namespace, target_line, 0, actual_mark)
132+
end
133+
end
134+
end
135+
81136
function M.focus_output(should_stop_insert)
82137
if should_stop_insert then
83138
vim.cmd('stopinsert')
@@ -121,11 +176,8 @@ function M.setup_autocmds(windows, group)
121176
end
122177

123178
function M.clear()
124-
if not M.mounted() then
125-
return
126-
end
127-
vim.api.nvim_buf_clear_namespace(state.windows.output_buf, -1, 0, -1)
128-
M.set_content({})
179+
M.set_lines({})
180+
M.clear_extmarks()
129181
end
130182

131183
return M

0 commit comments

Comments
 (0)