Skip to content

Commit 2d61b8b

Browse files
committed
feat!: update
1 parent 9d2adbf commit 2d61b8b

14 files changed

+740
-34
lines changed

init.lua

+6-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ vim.loader.enable()
22

33
_G.settings = {
44
ui = {
5-
border = 'solid',
5+
border = 'shadow',
66
border_preview = 'solid',
77
border_input = 'rounded',
88
background = 'dark',
@@ -121,15 +121,16 @@ _G.icons = {
121121
ArrowUp = '',
122122
Branch = '',
123123
Calculator = '󰃬 ',
124-
CircleFilled = '',
125-
CircleOutline = '',
124+
CircleDots = '󱥸 ',
125+
Copilot = '',
126+
CopilotError = '',
127+
CopilotWarning = '',
126128
Cmd = '󰞷 ',
127129
Cross = '󰅖 ',
128130
Ok = '󰄬 ',
129131
Diamond = '',
130-
Dot = '',
131-
DotLarge = '',
132132
Ellipsis = '',
133+
Ghost = '󱙝 ',
133134
GitSignAdd = '',
134135
GitSignChange = '',
135136
GitSignChangedelete = '',

lua/configs/catppuccin.lua

+4-4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ require('catppuccin').setup({
2828
indent_blankline = { enabled = true, scope_color = 'surface1' },
2929
markdown = true,
3030
mini = { enabled = true },
31+
noice = true,
3132
semantic_tokens = true,
3233
telescope = { enabled = true, style = 'nvchad' },
3334
treesitter_context = true,
@@ -38,11 +39,10 @@ require('catppuccin').setup({
3839
keywords = { 'italic' },
3940
},
4041
highlight_overrides = {
41-
all = function(colors)
42+
all = function(c)
4243
return {
43-
FloatBorder = { bg = colors.mantle, fg = colors.mantle },
44-
CursorLineNr = { fg = colors.mauve, style = { 'bold' } },
45-
WinSeparator = { fg = colors.surface1 },
44+
FloatBorder = { bg = c.mantle, fg = c.mantle },
45+
StatusLine = { bg = c.mantle, fg = c.subtext1 },
4646
}
4747
end,
4848
},

lua/configs/lazy.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ local config = {
1919
import = icons.ui.ArrowLeft,
2020
keys = icons.ui.Keyboard,
2121
lazy = ' ' .. icons.ui.Lazy .. ' ',
22-
loaded = icons.ui.CircleFilled,
23-
not_loaded = icons.ui.CircleOutline,
22+
loaded = icons.kinds.Package,
23+
not_loaded = icons.ui.Ghost,
2424
plugin = icons.kinds.Module,
2525
runtime = icons.kinds.File,
2626
require = icons.ui.Lua,

lua/core/_internal/statuscolumn.lua

+331
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
local ffi = require('ffi')
2+
local utils = require('utils')
3+
4+
---Wrapper around `utils.stl.hl()` that forces apply hlgroup even in tty
5+
---@param str? string sign symbol
6+
---@param hl? string name of the highlight group
7+
---@param restore? boolean restore highlight after the sign, default true
8+
local function make_hl(str, hl, restore)
9+
return utils.stl.hl(str, hl, restore, true)
10+
end
11+
12+
---@type table<integer, integer>
13+
local lnumw_cache = {}
14+
15+
---@class stc_shared_data_t
16+
---@field win integer
17+
---@field wp ffi.cdata* winpos_T C struct for window attributes
18+
---@field display_tick? integer display tick
19+
---@field buf_tick? integer b:changedtick
20+
---@field buf? integer
21+
---@field lnumw? integer number of digits of the largest line number
22+
---@field nu? boolean &number
23+
---@field rnu? boolean &relativenumber
24+
---@field nuw? integer &numberwidth
25+
---@field scl? string &signcolumn
26+
---@field fdc? string &foldcolumn
27+
---@field show_nu? boolean whether to show line number (either &nu or &rnu is true)
28+
---@field show_scl? boolean whether to show sign column
29+
---@field show_fdc? boolean whether to show fold column
30+
---@field cur? integer[] cursor position
31+
---@field cul? boolean &cursorline
32+
---@field culopt? string &cursorlineopt
33+
---@field culhl? boolean whether to use cursorline highlight at current line
34+
---@field lnumabovehl? boolean whether to use LineNrAbove at current line in number column
35+
---@field lnumbelowhl? boolean whether to use LineNrBelow at current line in number column
36+
---@field foldopen? string fold open sign
37+
---@field foldclose? string fold close sign
38+
---@field foldsep? string fold separator sign
39+
---@field extsigns? extmark_sign_t[] extmark signs, see `:h extmarks`
40+
---@field lnum? integer v:lnum
41+
---@field relnum? integer v:relnum
42+
---@field virtnum? integer v:virtnum
43+
44+
---@class extmark_sign_t
45+
---@field [1] integer extmark_id
46+
---@field [2] integer row, 0-indexed
47+
---@field [3] integer col, 0-indexed
48+
---@field [4] extmark_sign_details_t details
49+
50+
---@class extmark_sign_details_t: vim.api.keyset.set_extmark
51+
---@field sign_name string? only set when sign is defined using legacy `sign_define()`
52+
---@field ns_id integer
53+
54+
---Shared data in each window
55+
---@type table<string, stc_shared_data_t>
56+
local shared = {}
57+
58+
---@type table<string, fun(data: stc_shared_data_t, ...): string>
59+
local builders = {}
60+
61+
ffi.cdef([[
62+
typedef struct {} Error;
63+
typedef struct {} win_T;
64+
typedef struct {
65+
int start; // line number where deepest fold starts
66+
int level; // fold level, when zero other fields are N/A
67+
int llevel; // lowest level that starts in v:lnum
68+
int lines; // number of lines from v:lnum to end of closed fold
69+
} foldinfo_T;
70+
foldinfo_T fold_info(win_T* wp, int lnum);
71+
win_T *find_window_by_handle(int Window, Error *err);
72+
73+
// Display tick, incremented for each call to update_screen()
74+
uint64_t display_tick;
75+
]])
76+
77+
---Returns the string representation of sign column to be shown
78+
---@param data stc_shared_data_t
79+
---@param filter fun(sign: extmark_sign_t, data: stc_shared_data_t): boolean
80+
---@param virtual boolean whether to draw sign in virtual line
81+
---@return string
82+
function builders.signcol(data, filter, virtual)
83+
if not data.show_scl then
84+
return ''
85+
end
86+
if data.virtnum ~= 0 and not virtual then
87+
goto signcol_ret_default
88+
end
89+
do
90+
---@type extmark_sign_details_t?
91+
local sign_details
92+
for _, sign in ipairs(data.extsigns) do
93+
local lnum = sign[2] + 1 -- 0-indexed to 1-indexed
94+
local current_sign_details = sign[4]
95+
if lnum > data.lnum then
96+
break
97+
end
98+
if
99+
lnum == data.lnum
100+
and filter(sign, data)
101+
and current_sign_details.sign_text
102+
and (
103+
not sign_details
104+
or current_sign_details.priority > sign_details.priority
105+
)
106+
then
107+
sign_details = current_sign_details
108+
end
109+
end
110+
if sign_details then
111+
return make_hl(
112+
vim.trim(sign_details.sign_text),
113+
data.culhl and sign_details.cursorline_hl_group
114+
or sign_details.sign_hl_group --[[@as string]]
115+
)
116+
end
117+
end
118+
::signcol_ret_default::
119+
return make_hl(' ', data.culhl and 'CursorLineSign' or 'SignColumn')
120+
end
121+
122+
---@param data stc_shared_data_t
123+
---@return string
124+
function builders.lnum(data)
125+
local result = '' ---@type string|integer
126+
if not data.show_nu then
127+
return ''
128+
end
129+
if data.virtnum ~= 0 then -- Drawing virtual line
130+
goto lnum_ret_default
131+
end
132+
if not data.nu then
133+
result = data.relnum
134+
goto lnum_ret_default
135+
end
136+
if not data.rnu then
137+
result = data.lnum
138+
goto lnum_ret_default
139+
end
140+
if data.relnum == 0 then
141+
return string.format(
142+
'%%=%-' .. math.max(data.nuw - 1, data.lnumw or 0) .. 'd ',
143+
data.lnum
144+
)
145+
end
146+
result = data.relnum
147+
148+
::lnum_ret_default::
149+
return string.format(
150+
'%%=%' .. math.max(data.nuw - 1, data.lnumw or 0) .. 's ',
151+
result
152+
)
153+
end
154+
155+
---@param data stc_shared_data_t
156+
---@return string
157+
function builders.foldcol(data)
158+
if not data.show_fdc then
159+
return ''
160+
end
161+
local lnum = data.lnum --[[@as integer]]
162+
local foldinfo = ffi.C.fold_info(data.wp, lnum)
163+
local foldchar = (data.virtnum ~= 0 or foldinfo.start ~= lnum)
164+
and data.foldsep
165+
or foldinfo.lines == 0 and data.foldopen
166+
or data.foldclose
167+
return make_hl(foldchar, data.culhl and 'CursorLineFold' or 'FoldColumn')
168+
end
169+
170+
---Get a valid name of an extmark sign
171+
---@param sign extmark_sign_t
172+
---@return string
173+
local function extsign_get_name(sign)
174+
local details = sign[4]
175+
return details.sign_name or details.sign_hl_group or '' --[[@as string]]
176+
end
177+
178+
---@param sign extmark_sign_t
179+
---@param data stc_shared_data_t
180+
---@return boolean
181+
local function gitsigns_filter(sign, data)
182+
local name = extsign_get_name(sign)
183+
if not name:find('^Git') then
184+
return false
185+
end
186+
if data.virtnum ~= 0 then -- virtual lines, not showing git delete signs
187+
return not name:find('[Dd]elete$')
188+
end
189+
return true
190+
end
191+
192+
---@param sign extmark_sign_t
193+
---@return boolean
194+
local function nongitsigns_filter(sign)
195+
return not extsign_get_name(sign):find('^Git')
196+
end
197+
198+
---Get number of digits of a decimal integer
199+
---@param number integer
200+
---@return integer
201+
local function numdigits(number)
202+
local result = 0
203+
while number >= 1 do
204+
number = number / 10
205+
result = result + 1
206+
end
207+
return result
208+
end
209+
210+
---@return string
211+
function _G._stc()
212+
local win = vim.g.statusline_winid
213+
local display_tick = ffi.C.display_tick --[[@as uinteger]]
214+
if not shared[win] then -- Initialize shared data
215+
shared[win] = {
216+
win = win,
217+
wp = ffi.C.find_window_by_handle(win, ffi.new('Error')),
218+
}
219+
end
220+
221+
local data = shared[win]
222+
if not data.display_tick or data.display_tick < display_tick then -- Update shared data
223+
local wo = vim.wo[win]
224+
local fcs = vim.opt_local.fillchars:get()
225+
local buf = vim.api.nvim_win_get_buf(win)
226+
local wininfo = vim.fn.getwininfo(win)[1]
227+
data.display_tick = display_tick
228+
data.buf = buf
229+
data.cur = vim.api.nvim_win_get_cursor(win)
230+
data.cul = wo.cul
231+
data.culopt = wo.culopt
232+
data.nu = wo.nu
233+
data.rnu = wo.rnu
234+
data.nuw = wo.nuw
235+
data.scl = wo.scl
236+
data.fdc = wo.fdc
237+
data.show_nu = data.nu or data.rnu
238+
data.show_scl = data.scl ~= 'no'
239+
data.show_fdc = data.fdc ~= '0'
240+
data.foldopen = fcs.foldopen or '-'
241+
data.foldclose = fcs.foldclose or '+'
242+
data.foldsep = fcs.foldsep or '|'
243+
data.extsigns = vim.api.nvim_buf_get_extmarks(
244+
buf,
245+
-1,
246+
{ wininfo.topline - 1, 0 },
247+
{ wininfo.botline - 1, -1 },
248+
{
249+
type = 'sign',
250+
details = true,
251+
}
252+
)
253+
254+
-- lnum width is only needed when both &nu and &rnu are enabled
255+
if data.nu and data.rnu then
256+
local buf_tick = vim.api.nvim_buf_get_changedtick(buf)
257+
if not data.buf_tick or data.buf_tick < buf_tick then
258+
lnumw_cache[buf] = numdigits(vim.api.nvim_buf_line_count(buf))
259+
data.buf_tick = buf_tick
260+
end
261+
-- Cache could be nil after BufDelete
262+
data.lnumw = lnumw_cache[buf] or data.lnumw
263+
end
264+
end
265+
266+
data.lnum = vim.v.lnum
267+
data.relnum = vim.v.relnum
268+
data.virtnum = vim.v.virtnum
269+
270+
data.culhl = data.cul
271+
and data.culopt:find('[ou]')
272+
and data.lnum == data.cur[1]
273+
274+
return builders.signcol(data, nongitsigns_filter)
275+
.. (data.show_scl and ' ' or '')
276+
.. builders.lnum(data)
277+
.. builders.signcol(data, gitsigns_filter, true)
278+
.. builders.foldcol(data)
279+
.. (data.show_fdc and ' ' or '')
280+
end
281+
282+
---@return nil
283+
local function setup()
284+
if vim.g.loaded_statuscolumn ~= nil then
285+
return
286+
end
287+
vim.g.loaded_statuscolumn = true
288+
289+
---Attach statuscolumn to current window
290+
local function _attach()
291+
if
292+
vim.bo.bt == ''
293+
and vim.wo.stc == ''
294+
and vim.fn.win_gettype() == ''
295+
and not vim.b.bigfile
296+
then
297+
vim.opt_local.stc = '%!v:lua._stc()'
298+
end
299+
end
300+
301+
for _, win in ipairs(vim.api.nvim_list_wins()) do
302+
vim.api.nvim_win_call(win, _attach)
303+
end
304+
305+
local augroup = vim.api.nvim_create_augroup('StatusColumn', {})
306+
vim.api.nvim_create_autocmd({ 'BufWritePost', 'BufWinEnter' }, {
307+
group = augroup,
308+
desc = 'Set statuscolumn for each window.',
309+
callback = function()
310+
_attach()
311+
end,
312+
})
313+
vim.api.nvim_create_autocmd('WinClosed', {
314+
group = augroup,
315+
desc = 'Clear per window shared data cache.',
316+
callback = function(info)
317+
shared[tonumber(info.match)] = nil
318+
end,
319+
})
320+
vim.api.nvim_create_autocmd('BufDelete', {
321+
group = augroup,
322+
desc = 'Clear per buffer lnum width cache.',
323+
callback = function(info)
324+
lnumw_cache[info.buf] = nil
325+
end,
326+
})
327+
end
328+
329+
return {
330+
setup = setup,
331+
}

0 commit comments

Comments
 (0)