@@ -2,6 +2,8 @@ local M = {}
22
33local state = require (' opencode.state' )
44local config_file = require (' opencode.config_file' )
5+ local prompt_guard_indicator = require (' opencode.ui.prompt_guard_indicator' )
6+ local icons = require (' opencode.ui.icons' )
57
68local LABELS = {
79 NEW_SESSION_TITLE = ' New session' ,
@@ -40,17 +42,45 @@ local function get_mode_highlight()
4042 end
4143end
4244
43- local function create_winbar_text (description , model_info , mode_info , win_width )
44- local available_width = win_width - 2 -- 2 padding spaces
45-
46- -- If total length exceeds available width, truncate description
47- if # description + 1 + # model_info + # mode_info + 1 > available_width then
48- local space_for_desc = available_width - (# model_info + # mode_info + 1 ) - 4 -- -4 for "... "
49- description = description :sub (1 , space_for_desc ) .. ' ... '
45+ local function create_winbar_text (description , model_info , mode_info , show_guard_indicator , win_width )
46+ -- Calculate how many visible characters we have
47+ -- Format: " [GUARD] description padding model_info MODE "
48+ -- Where [GUARD] is optional (1 char + 1 space = 2 visible chars)
49+
50+ local guard_prefix = ' '
51+ local guard_visible_width = 0
52+
53+ if show_guard_indicator then
54+ local guard_icon = icons .get (' status_off' )
55+ guard_prefix = string.format (' %%#OpencodeGuardDenied#%s%%* ' , guard_icon )
56+ guard_visible_width = 2 -- icon + space
5057 end
51-
52- local padding = string.rep (' ' , available_width - # description - # model_info - # mode_info - 1 )
53- return string.format (' %s%s%s %s ' , description , padding , model_info , get_mode_highlight () .. mode_info .. ' %*' )
58+
59+ -- Total available width for all content
60+ local total_width = win_width
61+
62+ -- Calculate used width: leading space + guard + trailing space + model + mode
63+ local mode_info_str = get_mode_highlight () .. mode_info .. ' %*'
64+ local mode_visible_width = # mode_info
65+ local model_visible_width = # model_info
66+
67+ -- Reserve space: 1 (leading) + guard_visible_width + 1 (space before description) + 1 (space before model) + model + mode
68+ local reserved_width = 1 + guard_visible_width + 1 + 1 + model_visible_width + mode_visible_width
69+
70+ -- Available width for description and padding
71+ local available_for_desc = total_width - reserved_width
72+
73+ -- Truncate description if needed
74+ if # description > available_for_desc then
75+ description = description :sub (1 , math.max (1 , available_for_desc - 4 )) .. ' ...'
76+ end
77+
78+ -- Calculate padding to right-align model and mode
79+ local desc_and_padding_width = available_for_desc
80+ local padding_width = desc_and_padding_width - # description
81+ local padding = string.rep (' ' , math.max (0 , padding_width ))
82+
83+ return string.format (' %s%s%s%s %s' , guard_prefix , description , padding , model_info , mode_info_str )
5484end
5585
5686local function update_winbar_highlights (win_id )
@@ -96,8 +126,10 @@ function M.render()
96126 end
97127 -- topbar needs to at least have a value to make sure footer is positioned correctly
98128 vim .wo [win ].winbar = ' '
129+
130+ local show_guard_indicator = prompt_guard_indicator .is_denied ()
99131 vim .wo [win ].winbar =
100- create_winbar_text (get_session_desc (), format_model_info (), format_mode_info (), vim .api .nvim_win_get_width (win ))
132+ create_winbar_text (get_session_desc (), format_model_info (), format_mode_info (), show_guard_indicator , vim .api .nvim_win_get_width (win ))
101133
102134 update_winbar_highlights (win )
103135 end )
0 commit comments