diff --git a/lua/opencode/ui/output_window.lua b/lua/opencode/ui/output_window.lua index c4b98535..a9b8d0db 100644 --- a/lua/opencode/ui/output_window.lua +++ b/lua/opencode/ui/output_window.lua @@ -132,6 +132,11 @@ function M.update_dimensions(windows) if config.ui.position == 'current' then return end + + if not windows or not windows.output_win or not vim.api.nvim_win_is_valid(windows.output_win) then + return + end + local total_width = vim.api.nvim_get_option_value('columns', {}) local width_ratio @@ -145,8 +150,17 @@ function M.update_dimensions(windows) end local width = math.floor(total_width * width_ratio) + local ok, win_config = pcall(vim.api.nvim_win_get_config, windows.output_win) + if not ok then + return + end + + if win_config.relative == '' then + pcall(vim.api.nvim_win_set_width, windows.output_win, width) + return + end - vim.api.nvim_win_set_config(windows.output_win, { width = width }) + pcall(vim.api.nvim_win_set_config, windows.output_win, { width = width }) end function M.get_buf_line_count() diff --git a/lua/opencode/ui/reference_picker.lua b/lua/opencode/ui/reference_picker.lua index 632d664f..9c618fa3 100644 --- a/lua/opencode/ui/reference_picker.lua +++ b/lua/opencode/ui/reference_picker.lua @@ -239,7 +239,7 @@ function M.setup() end) end - state.subscribe('messages', function() + state.store.subscribe('messages', function() M._parse_session_messages() end) end diff --git a/tests/unit/zoom_spec.lua b/tests/unit/zoom_spec.lua index 2ec50c6e..a6ee11ed 100644 --- a/tests/unit/zoom_spec.lua +++ b/tests/unit/zoom_spec.lua @@ -228,6 +228,68 @@ describe('ui zoom state', function() assert.equals(80, state.pre_zoom_width) end) + + it('does not error when focused window is floating and output window is split', function() + local split_buf = vim.api.nvim_create_buf(false, true) + local focus_buf = vim.api.nvim_create_buf(false, true) + local split_win + local focus_win + + local normal_win + for _, win in ipairs(vim.api.nvim_list_wins()) do + if vim.api.nvim_win_is_valid(win) and vim.api.nvim_win_get_config(win).relative == '' then + normal_win = win + break + end + end + + assert.is_not_nil(normal_win) + vim.api.nvim_set_current_win(normal_win) + vim.cmd('vsplit') + split_win = vim.api.nvim_get_current_win() + vim.api.nvim_win_set_buf(split_win, split_buf) + + focus_win = vim.api.nvim_open_win(focus_buf, true, { + relative = 'editor', + width = 20, + height = 5, + row = 1, + col = 1, + style = 'minimal', + }) + + assert.has_no.errors(function() + output_window.update_dimensions({ output_win = split_win, output_buf = split_buf }) + end) + + local expected_width = math.floor(config.ui.window_width * vim.o.columns) + assert.equals(expected_width, vim.api.nvim_win_get_width(split_win)) + + pcall(vim.api.nvim_win_close, focus_win, true) + pcall(vim.api.nvim_win_close, split_win, true) + pcall(vim.api.nvim_buf_delete, focus_buf, { force = true }) + pcall(vim.api.nvim_buf_delete, split_buf, { force = true }) + end) + + it('does not error when output window is invalid', function() + local invalid_buf = vim.api.nvim_create_buf(false, true) + local invalid_win = vim.api.nvim_open_win(invalid_buf, false, { + relative = 'editor', + width = 20, + height = 5, + row = 2, + col = 2, + style = 'minimal', + }) + + vim.api.nvim_win_close(invalid_win, true) + + assert.has_no.errors(function() + output_window.update_dimensions({ output_win = invalid_win, output_buf = invalid_buf }) + end) + + pcall(vim.api.nvim_buf_delete, invalid_buf, { force = true }) + end) end) describe('zoom state persistence', function()