forked from sudo-tee/opencode.nvim
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtopbar.lua
More file actions
136 lines (110 loc) · 3.88 KB
/
topbar.lua
File metadata and controls
136 lines (110 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
local config = require('opencode.config')
local util = require('opencode.util')
local M = {}
local state = require('opencode.state')
local config_file = require('opencode.config_file')
local LABELS = {
NEW_SESSION_TITLE = 'New session',
}
local function format_token_info()
local parts = {}
if state.current_model then
if config.ui.display_context_size then
local provider, model = state.current_model:match('^(.-)/(.+)$')
local ok, model_info = pcall(config_file.get_model_info, provider, model)
if not ok then
model_info = nil
end
local limit = state.tokens_count and model_info and model_info.limit and model_info.limit.context or 0
table.insert(parts, util.format_number(state.tokens_count) or nil)
if limit > 0 then
table.insert(parts, util.format_percentage(state.tokens_count / limit) or nil)
end
end
if config.ui.display_cost and state.cost then
table.insert(parts, util.format_cost(state.cost) or nil)
end
end
local result = table.concat(parts, ' | ')
result = result:gsub('%%', '%%%%')
return result
end
local function create_winbar_text(description, token_info, win_width)
local left_content = ''
local right_content = token_info
local desc_width = win_width - util.strdisplaywidth(left_content) - util.strdisplaywidth(right_content)
local desc_formatted
if #description >= desc_width then
local ellipsis = '... '
desc_formatted = description:sub(1, desc_width - #ellipsis) .. ellipsis
else
desc_formatted = description .. string.rep(' ', math.floor(desc_width - #description))
end
return left_content .. desc_formatted .. right_content
end
local function update_winbar_highlights(win_id)
local current = vim.api.nvim_get_option_value('winhighlight', { win = win_id })
local parts = vim.split(current, ',')
-- Remove any existing winbar highlights
parts = vim.tbl_filter(function(part)
return not part:match('^WinBar:') and not part:match('^WinBarNC:')
end, parts)
if not vim.tbl_contains(parts, 'Normal:OpencodeNormal') then
table.insert(parts, 'Normal:OpencodeNormal')
end
table.insert(parts, 'WinBar:OpencodeSessionDescription')
table.insert(parts, 'WinBarNC:OpencodeSessionDescription')
vim.api.nvim_set_option_value('winhighlight', table.concat(parts, ','), { win = win_id })
end
local function get_session_desc()
if state.is_opening then
return 'Loading...'
end
local session_title = LABELS.NEW_SESSION_TITLE
if state.active_session and state.active_session.title ~= '' then
session_title = state.active_session.title
end
if not session_title or type(session_title) ~= 'string' then
session_title = ''
end
return session_title
end
function M.render()
vim.schedule(function()
if not state.windows then
return
end
local win = state.windows.output_win
if not win or not vim.api.nvim_win_is_valid(win) then
return
end
vim.wo[win].winbar = ' '
local desc = get_session_desc()
local token_info = format_token_info()
local winbar_str = create_winbar_text(desc, token_info, vim.api.nvim_win_get_width(win))
vim.wo[win].winbar = winbar_str
update_winbar_highlights(win)
end)
end
local function on_change(_, _, _)
M.render()
end
function M.setup()
state.subscribe('current_mode', on_change)
state.subscribe('current_model', on_change)
state.subscribe('active_session', on_change)
state.subscribe('is_opencode_focused', on_change)
state.subscribe('tokens_count', on_change)
state.subscribe('cost', on_change)
state.subscribe('is_opening', on_change)
M.render()
end
function M.close()
state.unsubscribe('current_mode', on_change)
state.unsubscribe('current_model', on_change)
state.unsubscribe('active_session', on_change)
state.unsubscribe('is_opencode_focused', on_change)
state.unsubscribe('tokens_count', on_change)
state.unsubscribe('cost', on_change)
end
return M