Skip to content

Commit 285fa75

Browse files
committed
refactor(ui): extract window option helpers and winbar highlighting
1 parent 760b404 commit 285fa75

6 files changed

Lines changed: 105 additions & 107 deletions

File tree

lua/opencode/ui/context_bar.lua

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ local icons = require('opencode.ui.icons')
55
local state = require('opencode.state')
66
local config = require('opencode.config')
77
local prompt_guard_indicator = require('opencode.ui.prompt_guard_indicator')
8+
local winbar = require('opencode.ui.winbar')
89

910
local function get_current_file_info(ctx)
1011
local current_file = ctx.current_file
@@ -151,24 +152,6 @@ local function format_winbar_text(segments)
151152
return left .. right_align .. table.concat(parts, '')
152153
end
153154

154-
local function update_winbar_highlights(win_id)
155-
local current = vim.api.nvim_get_option_value('winhighlight', { win = win_id })
156-
local parts = vim.split(current, ',')
157-
158-
parts = vim.tbl_filter(function(part)
159-
return not part:match('^WinBar:') and not part:match('^WinBarNC:')
160-
end, parts)
161-
162-
if not vim.tbl_contains(parts, 'Normal:OpencodeNormal') then
163-
table.insert(parts, 'Normal:OpencodeNormal')
164-
end
165-
166-
table.insert(parts, 'WinBar:OpencodeContextBar')
167-
table.insert(parts, 'WinBarNC:OpencodeContextBar')
168-
169-
vim.api.nvim_set_option_value('winhighlight', table.concat(parts, ','), { win = win_id })
170-
end
171-
172155
function M.setup()
173156
state.store.subscribe(
174157
{ 'current_context_config', 'current_code_buf', 'is_opencode_focused', 'context_updated_at', 'user_message_count' },
@@ -188,7 +171,7 @@ function M.render(windows)
188171
local segments = create_winbar_segments()
189172

190173
vim.wo[win].winbar = format_winbar_text(segments)
191-
update_winbar_highlights(win)
174+
winbar.update_highlights(win, 'OpencodeContextBar')
192175
end)
193176
end
194177

lua/opencode/ui/input_window.lua

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
local M = {}
2+
13
local state = require('opencode.state')
24
local config = require('opencode.config')
3-
local M = {}
5+
local window_options = require('opencode.ui.window_options')
46

57
-- Track hidden state
68
M._hidden = false
@@ -246,40 +248,30 @@ M._execute_slash_command = function(command)
246248
end
247249
end
248250

249-
local function set_win_option(option, value, windows)
250-
windows = windows or state.windows
251-
vim.api.nvim_set_option_value(option, value, { win = windows.input_win, scope = 'local' })
252-
end
253-
254-
local function set_buf_option(option, value, windows)
255-
windows = windows or state.windows
256-
vim.api.nvim_set_option_value(option, value, { buf = windows.input_buf })
257-
end
258-
259251
function M.setup(windows)
260252
if config.ui.input.text.wrap then
261-
set_win_option('wrap', true, windows)
262-
set_win_option('linebreak', true, windows)
253+
window_options.set_window_option('wrap', true, windows.input_win)
254+
window_options.set_window_option('linebreak', true, windows.input_win)
263255
end
264256

265-
set_buf_option('filetype', 'opencode', windows)
266-
set_win_option('winhighlight', config.ui.window_highlight, windows)
257+
window_options.set_buffer_option('filetype', 'opencode', windows.input_buf)
258+
window_options.set_window_option('winhighlight', config.ui.window_highlight, windows.input_win)
267259

268260
-- Apply user-configurable window options
269261
local win_opts = config.ui.input.win_options or {}
270262
for opt, value in pairs(win_opts) do
271-
pcall(set_win_option, opt, value, windows)
263+
pcall(window_options.set_window_option, opt, value, windows.input_win)
272264
end
273265

274-
set_buf_option('buftype', 'nofile', windows)
275-
set_buf_option('bufhidden', 'hide', windows)
276-
set_buf_option('buflisted', false, windows)
277-
set_buf_option('swapfile', false, windows)
266+
window_options.set_buffer_option('buftype', 'nofile', windows.input_buf)
267+
window_options.set_buffer_option('bufhidden', 'hide', windows.input_buf)
268+
window_options.set_buffer_option('buflisted', false, windows.input_buf)
269+
window_options.set_buffer_option('swapfile', false, windows.input_buf)
278270

279271
if config.ui.position ~= 'current' then
280-
set_win_option('winfixbuf', true, windows)
272+
window_options.set_window_option('winfixbuf', true, windows.input_win)
281273
end
282-
set_win_option('winfixwidth', true, windows)
274+
window_options.set_window_option('winfixwidth', true, windows.input_win)
283275

284276
M.update_dimensions(windows)
285277
M.refresh_placeholder(windows)

lua/opencode/ui/output_window.lua

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local state = require('opencode.state')
22
local config = require('opencode.config')
3+
local window_options = require('opencode.ui.window_options')
34

45
local M = {}
56
M.namespace = vim.api.nvim_create_namespace('opencode_output')
@@ -105,56 +106,26 @@ function M.is_at_bottom(win)
105106
return cursor[1] >= line_count
106107
end
107108

108-
---Helper to set window option and save original value for position='current'
109-
---@param opt_name string The option name
110-
---@param value any The value to set
111-
---@param win integer The window ID
112-
local function set_win_option(opt_name, value, win)
113-
-- Save original value if using position = 'current'
114-
if config.ui.position == 'current' then
115-
if not state.saved_window_options then
116-
state.ui.set_saved_window_options({})
117-
end
118-
-- Only save if not already saved (in case this function is called multiple times)
119-
if state.saved_window_options[opt_name] == nil then
120-
local ok, original = pcall(vim.api.nvim_get_option_value, opt_name, { win = win })
121-
if ok then
122-
state.saved_window_options[opt_name] = original
123-
end
124-
end
125-
end
126-
127-
vim.api.nvim_set_option_value(opt_name, value, { win = win, scope = 'local' })
128-
end
129-
130-
---Helper to set buffer option (no saving needed)
131-
---@param opt_name string The option name
132-
---@param value any The value to set
133-
---@param buf integer The buffer ID
134-
local function set_buf_option(opt_name, value, buf)
135-
vim.api.nvim_set_option_value(opt_name, value, { buf = buf })
136-
end
137-
138109
function M.setup(windows)
139-
set_win_option('winhighlight', config.ui.window_highlight, windows.output_win)
140-
set_win_option('wrap', true, windows.output_win)
141-
set_win_option('linebreak', true, windows.output_win)
142-
set_win_option('number', false, windows.output_win)
143-
set_win_option('relativenumber', false, windows.output_win)
144-
set_buf_option('modifiable', false, windows.output_buf)
145-
set_buf_option('buftype', 'nofile', windows.output_buf)
146-
set_buf_option('bufhidden', 'hide', windows.output_buf)
147-
set_buf_option('buflisted', false, windows.output_buf)
148-
set_buf_option('swapfile', false, windows.output_buf)
110+
window_options.set_window_option('winhighlight', config.ui.window_highlight, windows.output_win, { save_original = true })
111+
window_options.set_window_option('wrap', true, windows.output_win, { save_original = true })
112+
window_options.set_window_option('linebreak', true, windows.output_win, { save_original = true })
113+
window_options.set_window_option('number', false, windows.output_win, { save_original = true })
114+
window_options.set_window_option('relativenumber', false, windows.output_win, { save_original = true })
115+
window_options.set_buffer_option('modifiable', false, windows.output_buf)
116+
window_options.set_buffer_option('buftype', 'nofile', windows.output_buf)
117+
window_options.set_buffer_option('bufhidden', 'hide', windows.output_buf)
118+
window_options.set_buffer_option('buflisted', false, windows.output_buf)
119+
window_options.set_buffer_option('swapfile', false, windows.output_buf)
149120

150121
if config.ui.position ~= 'current' then
151-
set_win_option('winfixbuf', true, windows.output_win)
122+
window_options.set_window_option('winfixbuf', true, windows.output_win, { save_original = true })
152123
end
153-
set_win_option('winfixheight', true, windows.output_win)
154-
set_win_option('winfixwidth', true, windows.output_win)
155-
set_win_option('signcolumn', 'yes', windows.output_win)
156-
set_win_option('list', false, windows.output_win)
157-
set_win_option('statuscolumn', '', windows.output_win)
124+
window_options.set_window_option('winfixheight', true, windows.output_win, { save_original = true })
125+
window_options.set_window_option('winfixwidth', true, windows.output_win, { save_original = true })
126+
window_options.set_window_option('signcolumn', 'yes', windows.output_win, { save_original = true })
127+
window_options.set_window_option('list', false, windows.output_win, { save_original = true })
128+
window_options.set_window_option('statuscolumn', '', windows.output_win, { save_original = true })
158129

159130
M.update_dimensions(windows)
160131
M.setup_keymaps(windows)

lua/opencode/ui/topbar.lua

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local config = require('opencode.config')
22
local util = require('opencode.util')
3+
local winbar = require('opencode.ui.winbar')
34

45
local M = {}
56

@@ -53,25 +54,6 @@ local function create_winbar_text(description, token_info, win_width)
5354
return left_content .. desc_formatted .. right_content
5455
end
5556

56-
local function update_winbar_highlights(win_id)
57-
local current = vim.api.nvim_get_option_value('winhighlight', { win = win_id })
58-
local parts = vim.split(current, ',')
59-
60-
-- Remove any existing winbar highlights
61-
parts = vim.tbl_filter(function(part)
62-
return not part:match('^WinBar:') and not part:match('^WinBarNC:')
63-
end, parts)
64-
65-
if not vim.tbl_contains(parts, 'Normal:OpencodeNormal') then
66-
table.insert(parts, 'Normal:OpencodeNormal')
67-
end
68-
69-
table.insert(parts, 'WinBar:OpencodeSessionDescription')
70-
table.insert(parts, 'WinBarNC:OpencodeSessionDescription')
71-
72-
vim.api.nvim_set_option_value('winhighlight', table.concat(parts, ','), { win = win_id })
73-
end
74-
7557
local function get_session_desc()
7658
if state.is_opening then
7759
return 'Loading...'
@@ -106,7 +88,7 @@ function M.render()
10688
local winbar_str = create_winbar_text(desc, token_info, vim.api.nvim_win_get_width(win))
10789
vim.wo[win].winbar = winbar_str
10890

109-
update_winbar_highlights(win)
91+
winbar.update_highlights(win, 'OpencodeSessionDescription')
11092
end)
11193
end
11294

lua/opencode/ui/winbar.lua

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
local M = {}
2+
3+
---@param win_id integer
4+
---@param highlight string
5+
function M.update_highlights(win_id, highlight)
6+
local current = vim.api.nvim_get_option_value('winhighlight', { win = win_id })
7+
local parts = vim.split(current, ',')
8+
9+
parts = vim.tbl_filter(function(part)
10+
return not part:match('^WinBar:') and not part:match('^WinBarNC:')
11+
end, parts)
12+
13+
if not vim.tbl_contains(parts, 'Normal:OpencodeNormal') then
14+
table.insert(parts, 'Normal:OpencodeNormal')
15+
end
16+
17+
table.insert(parts, 'WinBar:' .. highlight)
18+
table.insert(parts, 'WinBarNC:' .. highlight)
19+
20+
vim.api.nvim_set_option_value('winhighlight', table.concat(parts, ','), { win = win_id })
21+
end
22+
23+
return M

lua/opencode/ui/window_options.lua

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
local M = {}
2+
3+
local config = require('opencode.config')
4+
local state = require('opencode.state')
5+
6+
---@param opt_name string
7+
---@param win integer
8+
local function save_original_window_option(opt_name, win)
9+
if config.ui.position ~= 'current' then
10+
return
11+
end
12+
13+
if not state.saved_window_options then
14+
state.ui.set_saved_window_options({})
15+
end
16+
17+
if state.saved_window_options[opt_name] ~= nil then
18+
return
19+
end
20+
21+
local ok, original = pcall(vim.api.nvim_get_option_value, opt_name, { win = win })
22+
if ok then
23+
state.saved_window_options[opt_name] = original
24+
end
25+
end
26+
27+
---@param opt_name string
28+
---@param value any
29+
---@param win integer
30+
---@param opts? { save_original?: boolean }
31+
function M.set_window_option(opt_name, value, win, opts)
32+
opts = opts or {}
33+
if opts.save_original then
34+
save_original_window_option(opt_name, win)
35+
end
36+
37+
vim.api.nvim_set_option_value(opt_name, value, { win = win, scope = 'local' })
38+
end
39+
40+
---@param opt_name string
41+
---@param value any
42+
---@param buf integer
43+
function M.set_buffer_option(opt_name, value, buf)
44+
vim.api.nvim_set_option_value(opt_name, value, { buf = buf })
45+
end
46+
47+
return M

0 commit comments

Comments
 (0)