plugins/dropbar: init

This commit is contained in:
Gaetan Lepage 2025-01-08 13:35:16 +01:00 committed by nix-infra-bot
parent 592e9eaff0
commit 2054094544
3 changed files with 1446 additions and 0 deletions

View file

@ -0,0 +1,51 @@
{ lib, ... }:
lib.nixvim.plugins.mkNeovimPlugin {
name = "dropbar";
packPathName = "dropbar.nvim";
package = "dropbar-nvim";
maintainers = [ lib.maintainers.GaetanLepage ];
description = ''
A polished, IDE-like, highly-customizable winbar for Neovim with drop-down menu support and
multiple backends.
'';
settingsOptions = import ./settings-options.nix lib;
settingsExample = {
bar = {
enable = true;
sources.__raw = ''
function(buf, _)
local sources = require('dropbar.sources')
return {
require('dropbar.utils').source.fallback({
sources.lsp,
sources.treesitter,
sources.markdown,
})
}
end
'';
};
menu.keymaps = {
h = "<C-w>q";
l.__raw = ''
function()
local dropbar = require('dropbar')
local utils = require('dropbar.utils')
local menu = utils.menu.get_current()
if not menu then
return
end
local cursor = vim.api.nvim_win_get_cursor(menu.win)
local component = menu.entries[cursor[1]]:first_clickable(cursor[2])
if component then
menu:click_on(component, nil, 1, 'l')
end
end
'';
};
};
}

View file

@ -0,0 +1,619 @@
lib:
let
inherit (lib) types;
inherit (lib.nixvim) defaultNullOpts literalLua mkNullOrOption;
mkPadding =
defaultNullOpts.mkNullable
(types.submodule {
options = lib.genAttrs [ "left" "right" ] (
side:
lib.mkOption {
type = types.ints.unsigned;
description = "Padding for the ${side} side.";
}
);
})
{
left = 1;
right = 1;
};
in
{
bar = {
enable =
defaultNullOpts.mkBool
(literalLua ''
function(buf, win, _)
if
not vim.api.nvim_buf_is_valid(buf)
or not vim.api.nvim_win_is_valid(win)
or vim.fn.win_gettype(win) ~= ""
or vim.wo[win].winbar ~= ""
or vim.bo[buf].ft == 'help'
then
return false
end
local stat = vim.uv.fs_stat(vim.api.nvim_buf_get_name(buf))
if stat and stat.size > 1024 * 1024 then
return false
end
return vim.bo[buf].ft == 'markdown'
or pcall(vim.treesitter.get_parser, buf)
or not vim.tbl_isempty(vim.lsp.get_clients({
bufnr = buf,
method = 'textDocument/documentSymbol',
}))
end
'')
''
Controls whether to enable the plugin for the current buffer and window.
If a function is provided, it will be called with the current `bufnr` and `winid` and
should return a boolean.
'';
attach_events =
defaultNullOpts.mkListOf types.str
[
"OptionSet"
"BufWinEnter"
"BufWritePost"
]
''
Controls when to evaluate the `enable()` function and attach the plugin to corresponding
buffer or window.
'';
update_debounce = defaultNullOpts.mkUnsignedInt 0 ''
Wait for a short time before updating the winbar, if another update request is received within
this time, the previous request will be cancelled.
This improves the performance when the user is holding down a key (e.g. `'j'`) to scroll the
window.
If you encounter performance issues when scrolling the window, try setting this option to a
number slightly larger than `1000 / key_repeat_rate`.
'';
update_events = {
win =
defaultNullOpts.mkListOf types.str
[
"CursorMoved"
"WinEnter"
"WinResized"
]
''
List of events that should trigger an update on the dropbar attached to a single window.
'';
buf =
defaultNullOpts.mkListOf types.str
[
"BufModifiedSet"
"FileChangedShellPost"
"TextChanged"
"ModeChanged"
]
''
List of events that should trigger an update on all dropbars attached to a buffer.
'';
global =
defaultNullOpts.mkListOf types.str
[
"DirChanged"
"VimResized"
]
''
List of events that should trigger an update on all dropbars in the current nvim
session.
'';
};
hover = defaultNullOpts.mkBool true ''
Whether to highlight the symbol under the cursor.
This feature requires 'mousemoveevent' to be enabled.
'';
sources =
defaultNullOpts.mkListOf
(types.submodule {
freeformType = with types; attrsOf anything;
options = {
get_symbols = mkNullOrOption types.rawLua ''
```lua
fun(buf: integer, win: integer, cursor: integer[]): dropbar_symbol_t[]
```
'';
};
})
(literalLua ''
function(buf, _)
local sources = require('dropbar.sources')
local utils = require('dropbar.utils')
if vim.bo[buf].ft == 'markdown' then
return {
sources.path,
sources.markdown,
}
end
if vim.bo[buf].buftype == 'terminal' then
return {
sources.terminal,
}
end
return {
sources.path,
utils.source.fallback({
sources.lsp,
sources.treesitter,
}),
}
end
'')
''
List of sources to show in the winbar.
If a function is provided, it will be called with the current `bufnr` and `winid` and
should return a list of sources.
For more information about sources, see `|dropbar-developers-classes-dropbar_source_t|`.
'';
padding = mkPadding ''
Padding to use between the winbar and the window border.
'';
pick = {
pivots = defaultNullOpts.mkStr "abcdefghijklmnopqrstuvwxyz" ''
Pivots to use in pick mode.
'';
};
truncate = defaultNullOpts.mkBool true ''
Whether to truncate the winbar if it doesnt fit in the window.
'';
};
menu = {
quick_navigation = defaultNullOpts.mkBool true ''
When on, automatically set the cursor to the closest previous/next clickable component in the
direction of cursor movement on `|CursorMoved|`.
'';
entry = {
padding = mkPadding ''
Padding to use between the menu entry and the menu border.
'';
};
preview = defaultNullOpts.mkBool true ''
Whether to enable previewing for menu entries.
'';
keymaps = mkNullOrOption (with types; attrsOf (either str (attrsOf (maybeRaw str)))) ''
Buffer-local keymaps in the menu.
Use `<key> = <function|string>` to map a key in normal mode in the menu buffer, or use
`<key> = table<mode, function|string>` to map a key in specific modes.
See `:h dropbar-configuration-options-menu` for the default value.
'';
scrollbar =
defaultNullOpts.mkAttrsOf types.bool
{
enable = true;
background = true;
}
''
Scrollbar configuration for the menu.
'';
win_configs = mkNullOrOption (with types; attrsOf anything) ''
Window configurations for the menu, see `:h nvim_open_win()`.
Each config key in `menu.win_configs` accepts either a plain value which will be passed
directly to `nvim_open_win()`, or a function that takes the current `menu` (see
`|dropbar-developers-classes-dropbar_menu_t|`) as an argument and returns a value to be
passed to `nvim_open_win()`.
See `:h dropbar-configuration-options-menu` for the default value.
'';
};
fzf = {
keymaps = mkNullOrOption (with types; attrsOf (maybeRaw str)) ''
The keymaps that will apply in insert mode, in the fzf prompt buffer.
See `:h dropbar-configuration-options-fzf` for the default value.
'';
win_configs = mkNullOrOption (with types; attrsOf anything) ''
Options passed to `:h nvim_open_win`.
The fuzzy finder will use its parent window's config by default, but options set here will
override those.
Same config as `menu.win_configs`
See `:h dropbar-configuration-options-fzf` for the default value.
'';
prompt = defaultNullOpts.mkStr "%#htmlTag# " ''
Prompt string that will be displayed in the `statuscolumn` of the fzf input window.
Can include highlight groups
'';
char_pattern = defaultNullOpts.mkStr "[%w%p]" ''
Character pattern.
'';
retain_inner_spaces = defaultNullOpts.mkBool true ''
Whether to retain inner spaces.
'';
fuzzy_find_on_click = defaultNullOpts.mkBool true ''
When opening an entry with a submenu via the fuzzy finder, open the submenu in fuzzy finder
mode.
'';
};
icons = {
enable = defaultNullOpts.mkBool true ''
Whether to enable icons.
'';
kinds = {
dir_icon =
defaultNullOpts.mkStr
(literalLua ''
function(_)
return M.opts.icons.kinds.symbols.Folder, 'DropBarIconKindFolder'
end
'')
''
Directory icon and highlighting getter, set to empty string to disable.
'';
file_icon =
defaultNullOpts.mkStr
(literalLua ''
function(path)
return M.opts.icons.kinds.symbols.File, 'DropBarIconKindFile'
end
'')
''
File icon and highlighting getter, set to empty string to disable.
'';
symbols = mkNullOrOption (with types; attrsOf str) ''
Table mapping the different kinds of symbols to their corresponding icons.
See `:h dropbar-configuration-options-icons` for the default value.
'';
};
ui = {
bar =
defaultNullOpts.mkAttrsOf types.str
{
separator = " ";
extends = "";
}
''
Controls the icons used in the winbar UI.
'';
menu =
defaultNullOpts.mkAttrsOf types.str
{
separator = " ";
indicator = " ";
}
''
Controls the icons used in the menu UI.
'';
};
};
symbol = {
on_click = mkNullOrOption (with types; maybeRaw (enum [ false ])) ''
function called when clicking or pressing `<CR>` on the symbol.
See `:h dropbar-configuration-options-symbol` for the default value.
'';
preview = {
reorient =
defaultNullOpts.mkRaw
''
function(_, range)
local invisible = range['end'].line - vim.fn.line('w$') + 1
if invisible > 0 then
local view = vim.fn.winsaveview() --[[@as vim.fn.winrestview.dict]]
view.topline = math.min(
view.topline + invisible,
math.max(1, range.start.line - vim.wo.scrolloff + 1)
)
vim.fn.winrestview(view)
end
end
''
''
Function to reorient the source window when previewing symbol given the source window
`win` and the range of the symbol `range`.
'';
};
jump = {
reorient =
defaultNullOpts.mkRaw
''
function(win, range)
local view = vim.fn.winsaveview()
local win_height = vim.api.nvim_win_get_height(win)
local topline = range.start.line - math.floor(win_height / 4)
if
topline > view.topline
and topline + win_height < vim.fn.line('$')
then
view.topline = topline
vim.fn.winrestview(view)
end
end
''
''
Function to reorient the source window when jumping to symbol given the source window
`win` and the range of the symbol `range`.
'';
};
};
sources = {
path = {
max_depth = defaultNullOpts.mkUnsignedInt 16 ''
Maximum number of symbols to return.
A smaller number can help to improve performance in deeply nested paths.
'';
relative_to =
defaultNullOpts.mkStr
(literalLua ''
function(_, win)
-- Workaround for Vim:E5002: Cannot find window number
local ok, cwd = pcall(vim.fn.getcwd, win)
return ok and cwd or vim.fn.getcwd()
end
'')
''
The path to use as the root of the relative path.
If a function is provided, it will be called with the current buffer number and window
id as arguments and should return a string to be used as the root of the relative path.
Notice: currently does not support `..` relative paths.
'';
path_filter = defaultNullOpts.mkRaw "function(_) return true end" ''
A function that takes a file name and returns whether to include it in the results shown in
the drop-down menu.
'';
modified = defaultNullOpts.mkRaw "function(sym) return sym end" ''
A function that takes the last symbol in the result got from the path source and returns an
alternative symbol to show if the current buffer is modified.
For information about dropbar symbols, see `|dropbar-developers-classes-dropbar_symbol_t|`.
To set a different icon, name, or highlights when the buffer is modified, you can change the
corresponding fields in the returned symbol:
```lua
function(sym)
return sym:merge({
name = sym.name .. ' [+]',
icon = ' ',
name_hl = 'DiffAdded',
icon_hl = 'DiffAdded',
-- ...
})
end
```
'';
preview =
defaultNullOpts.mkBool
(literalLua ''
function(path)
local stat = vim.uv.fs_stat(path)
if not stat or stat.type ~= 'file' then
return false
end
if stat.size > 524288 then
vim.notify(
string.format(
'[dropbar.nvim] file "%s" too large to preview',
path
),
vim.log.levels.WARN
)
return false
end
return true
end
'')
''
A boolean or a function that takes a file path and returns whether to preview the file
under cursor.
'';
};
treesitter = {
max_depth = defaultNullOpts.mkUnsignedInt 16 ''
Maximum number of symbols to return.
A smaller number can help to improve performance in deeply nested trees (e.g. in big nested
json files).
'';
name_regex = defaultNullOpts.mkStr "[=[[#~!@\*&.]*[[:keyword:]]\+!\?\(\(\(->\)\+\|-\+\|\.\+\|:\+\|\s\+\)\?[#~!@\*&.]*[[:keyword:]]\+!\?\)*]=]" ''
Vim regex used to extract a short name from the node text.
'';
valid_types =
defaultNullOpts.mkListOf types.str
[
"array"
"boolean"
"break_statement"
"call"
"case_statement"
"class"
"constant"
"constructor"
"continue_statement"
"delete"
"do_statement"
"element"
"enum"
"enum_member"
"event"
"for_statement"
"function"
"h1_marker"
"h2_marker"
"h3_marker"
"h4_marker"
"h5_marker"
"h6_marker"
"if_statement"
"interface"
"keyword"
"macro"
"method"
"module"
"namespace"
"null"
"number"
"operator"
"package"
"pair"
"property"
"reference"
"repeat"
"rule_set"
"scope"
"specifier"
"struct"
"switch_statement"
"type"
"type_parameter"
"unit"
"value"
"variable"
"while_statement"
"declaration"
"field"
"identifier"
"object"
"statement"
]
''
A list of treesitter node types to include in the results.
'';
};
lsp = {
max_depth = defaultNullOpts.mkUnsignedInt 16 ''
Maximum number of symbols to return.
A smaller number can help to improve performance when the language server returns huge list
of nested symbols.
'';
valid_symbols =
defaultNullOpts.mkListOf types.str
[
"File"
"Module"
"Namespace"
"Package"
"Class"
"Method"
"Property"
"Field"
"Constructor"
"Enum"
"Interface"
"Function"
"Variable"
"Constant"
"String"
"Number"
"Boolean"
"Array"
"Object"
"Keyword"
"Null"
"EnumMember"
"Struct"
"Event"
"Operator"
"TypeParameter"
]
''
A list of LSP document symbols to include in the results.
'';
request = {
ttl_init = defaultNullOpts.mkUnsignedInt 60 ''
Number of times to retry a request before giving up.
'';
interval = defaultNullOpts.mkUnsignedInt 1000 ''
Number of milliseconds to wait between retries.
'';
};
};
markdown = {
max_depth = defaultNullOpts.mkUnsignedInt 6 ''
Maximum number of symbols to return.
'';
parse = {
look_ahead = defaultNullOpts.mkUnsignedInt 200 ''
Number of lines to update when cursor moves out of the parsed range.
'';
};
};
terminal = {
icon =
defaultNullOpts.mkStr
(literalLua ''
function(_)
return M.opts.icons.kinds.symbols.Terminal or ' '
end
'')
''
Icon to show before terminal names.
'';
name = defaultNullOpts.mkStr (literalLua "vim.api.nvim_buf_get_name") ''
Name for the current terminal buffer.
'';
show_current = defaultNullOpts.mkBool true ''
Show the current terminal buffer in the menu.
'';
};
};
}

View file

@ -0,0 +1,776 @@
{
empty = {
plugins.dropbar.enable = true;
};
example = {
plugins.dropbar = {
enable = true;
settings = {
bar = {
enable = true;
sources.__raw = ''
function(buf, _)
local sources = require('dropbar.sources')
return {
require('dropbar.utils').source.fallback({
sources.lsp,
sources.treesitter,
sources.markdown,
})
}
end
'';
};
menu.keymaps = {
h = "<C-w>q";
l.__raw = ''
function()
local dropbar = require('dropbar')
local utils = require('dropbar.utils')
local menu = utils.menu.get_current()
if not menu then
return
end
local cursor = vim.api.nvim_win_get_cursor(menu.win)
local component = menu.entries[cursor[1]]:first_clickable(cursor[2])
if component then
menu:click_on(component, nil, 1, 'l')
end
end
'';
};
};
};
};
defaults = {
plugins.dropbar = {
enable = true;
settings = {
bar = {
enable.__raw = ''
function(buf, win, _)
if
not vim.api.nvim_buf_is_valid(buf)
or not vim.api.nvim_win_is_valid(win)
or vim.fn.win_gettype(win) ~= ""
or vim.wo[win].winbar ~= ""
or vim.bo[buf].ft == 'help'
then
return false
end
local stat = vim.uv.fs_stat(vim.api.nvim_buf_get_name(buf))
if stat and stat.size > 1024 * 1024 then
return false
end
return vim.bo[buf].ft == 'markdown'
or pcall(vim.treesitter.get_parser, buf)
or not vim.tbl_isempty(vim.lsp.get_clients({
bufnr = buf,
method = 'textDocument/documentSymbol',
}))
end
'';
attach_events = [
"OptionSet"
"BufWinEnter"
"BufWritePost"
];
update_debounce = 0;
update_events = {
win = [
"CursorMoved"
"WinEnter"
"WinResized"
];
buf = [
"BufModifiedSet"
"FileChangedShellPost"
"TextChanged"
"ModeChanged"
];
global = [
"DirChanged"
"VimResized"
];
};
hover = true;
sources.__raw = ''
function(buf, _)
local sources = require('dropbar.sources')
local utils = require('dropbar.utils')
if vim.bo[buf].ft == 'markdown' then
return {
sources.path,
sources.markdown,
}
end
if vim.bo[buf].buftype == 'terminal' then
return {
sources.terminal,
}
end
return {
sources.path,
utils.source.fallback({
sources.lsp,
sources.treesitter,
}),
}
end
'';
padding = {
left = 1;
right = 1;
};
pick = {
pivots = "abcdefghijklmnopqrstuvwxyz";
};
truncate = true;
};
menu = {
quick_navigation = true;
entry = {
padding = {
left = 1;
right = 1;
};
};
preview = true;
keymaps = {
q = "<C-w>q";
"<Esc>" = "<C-w>q";
"<LeftMouse>".__raw = ''
function()
local menu = utils.menu.get_current()
if not menu then
return
end
local mouse = vim.fn.getmousepos()
local clicked_menu = utils.menu.get({ win = mouse.winid })
-- If clicked on a menu, invoke the corresponding click action,
-- else close all menus and set the cursor to the clicked window
if clicked_menu then
clicked_menu:click_at({
mouse.line,
mouse.column - 1
}, nil, 1, 'l')
return
end
utils.menu.exec('close')
utils.bar.exec('update_current_context_hl')
if vim.api.nvim_win_is_valid(mouse.winid) then
vim.api.nvim_set_current_win(mouse.winid)
end
end
'';
"<CR>".__raw = ''
function()
local menu = utils.menu.get_current()
if not menu then
return
end
local cursor = vim.api.nvim_win_get_cursor(menu.win)
local component = menu.entries[cursor[1]]:first_clickable(cursor[2])
if component then
menu:click_on(component, nil, 1, 'l')
end
end
'';
"<MouseMove>".__raw = ''
function()
local menu = utils.menu.get_current()
if not menu then
return
end
local mouse = vim.fn.getmousepos()
utils.menu.update_hover_hl(mouse)
if M.opts.menu.preview then
utils.menu.update_preview(mouse)
end
end
'';
i.__raw = ''
function()
local menu = utils.menu.get_current()
if not menu then
return
end
menu:fuzzy_find_open()
end
'';
};
scrollbar = {
enable = true;
background = true;
};
win_configs = {
border = "none";
style = "minimal";
row.__raw = ''
function(menu)
return menu.prev_menu
and menu.prev_menu.clicked_at
and menu.prev_menu.clicked_at[1] - vim.fn.line('w')
or 0
end
'';
col.__raw = ''
---@param menu dropbar_menu_t
function(menu)
if menu.prev_menu then
return menu.prev_menu._win_configs.width
+ (menu.prev_menu.scrollbar and 1 or 0)
end
local mouse = vim.fn.getmousepos()
local bar = utils.bar.get({ win = menu.prev_win })
if not bar then
return mouse.wincol
end
local _, range = bar:get_component_at(math.max(0, mouse.wincol - 1))
return range and range.start or mouse.wincol
end
'';
relative = "win";
win.__raw = ''
function(menu)
return menu.prev_menu and menu.prev_menu.win
or vim.fn.getmousepos().winid
end
'';
height.__raw = ''
function(menu)
return math.max(
1,
math.min(
#menu.entries,
vim.go.pumheight ~= 0 and vim.go.pumheight
or math.ceil(vim.go.lines / 4)
)
)
end
'';
width.__raw = ''
function(menu)
local min_width = vim.go.pumwidth ~= 0 and vim.go.pumwidth or 8
if vim.tbl_isempty(menu.entries) then
return min_width
end
return math.max(
min_width,
math.max(unpack(vim.tbl_map(function(entry)
return entry:displaywidth()
end, menu.entries)))
)
end
'';
zindex.__raw = ''
function(menu)
if menu.prev_menu then
if menu.prev_menu.scrollbar and menu.prev_menu.scrollbar.thumb then
return vim.api.nvim_win_get_config(menu.prev_menu.scrollbar.thumb).zindex
end
return vim.api.nvim_win_get_config(menu.prev_win).zindex
end
end
'';
};
};
fzf = {
keymaps = {
# TODO
};
win_configs = {
relative = "win";
anchor = "NW";
height = 1;
win.__raw = ''
function(menu)
return menu.win
end
'';
width.__raw = ''
function(menu)
local function border_width(border)
if type(border) == 'string' then
if border == 'none' or border == 'shadow' then
return 0
end
return 2 -- left and right border
end
local left, right = 1, 1
if
(#border == 1 and border[1] == "")
or (#border == 4 and border[4] == "")
or (#border == 8 and border[8] == "")
then
left = 0
end
if
(#border == 1 and border[1] == "")
or (#border == 4 and border[4] == "")
or (#border == 8 and border[4] == "")
then
right = 0
end
return left + right
end
local menu_width = menu._win_configs.width
+ border_width(menu._win_configs.border)
local self_width = menu._win_configs.width
local self_border = border_width(
(
M.opts.fzf.win_configs
and M.eval(M.opts.fzf.win_configs.border, menu)
)
or (menu.fzf_win_configs and M.eval(
menu.fzf_win_configs.border,
menu
))
or menu._win_configs.border
)
if self_width + self_border > menu_width then
return self_width - self_border
else
return menu_width - self_border
end
end
'';
row.__raw = ''
function(menu)
local menu_border = menu._win_configs.border
if
type(menu_border) == 'string'
and menu_border ~= 'shadow'
and menu_border ~= 'none'
then
return menu._win_configs.height + 1
elseif menu_border == 'none' then
return menu._win_configs.height
end
local len_menu_border = #menu_border
if
len_menu_border == 1 and menu_border[1] ~= ""
or (len_menu_border == 2 or len_menu_border == 4) and menu_border[2] ~= ""
or len_menu_border == 8 and menu_border[8] ~= ""
then
return menu._win_configs.height + 1
else
return menu._win_configs.height
end
end
'';
col.__raw = ''
function(menu)
local menu_border = menu._win_configs.border
if
type(menu_border) == 'string'
and menu_border ~= 'shadow'
and menu_border ~= 'none'
then
return -1
end
if
type(menu_border) == 'table' and menu_border[#menu_border] ~= ""
then
return -1
end
return 0
end
'';
};
prompt = "%#htmlTag# ";
char_pattern = "[%w%p]";
retain_inner_spaces = true;
fuzzy_find_on_click = true;
};
icons = {
enable = true;
kinds = {
dir_icon.__raw = ''
function(_)
return M.opts.icons.kinds.symbols.Folder, 'DropBarIconKindFolder'
end
'';
file_icon.__raw = ''
function(path)
return M.opts.icons.kinds.symbols.File, 'DropBarIconKindFile'
end
'';
symbols = {
Array = "󰅪 ";
Boolean = " ";
BreakStatement = "󰙧 ";
Call = "󰃷 ";
CaseStatement = "󱃙 ";
Class = " ";
Color = "󰏘 ";
Constant = "󰏿 ";
Constructor = " ";
ContinueStatement = " ";
Copilot = " ";
Declaration = "󰙠 ";
Delete = "󰩺 ";
DoStatement = "󰑖 ";
Element = "󰅩 ";
Enum = " ";
EnumMember = " ";
Event = " ";
Field = " ";
File = "󰈔 ";
Folder = "󰉋 ";
ForStatement = "󰑖 ";
Function = "󰊕 ";
H1Marker = "󰉫 ";
H2Marker = "󰉬 ";
H3Marker = "󰉭 ";
H4Marker = "󰉮 ";
H5Marker = "󰉯 ";
H6Marker = "󰉰 ";
Identifier = "󰀫 ";
IfStatement = "󰇉 ";
Interface = " ";
Keyword = "󰌋 ";
List = "󰅪 ";
Log = "󰦪 ";
Lsp = " ";
Macro = "󰁌 ";
MarkdownH1 = "󰉫 ";
MarkdownH2 = "󰉬 ";
MarkdownH3 = "󰉭 ";
MarkdownH4 = "󰉮 ";
MarkdownH5 = "󰉯 ";
MarkdownH6 = "󰉰 ";
Method = "󰆧 ";
Module = "󰏗 ";
Namespace = "󰅩 ";
Null = "󰢤 ";
Number = "󰎠 ";
Object = "󰅩 ";
Operator = "󰆕 ";
Package = "󰆦 ";
Pair = "󰅪 ";
Property = " ";
Reference = "󰦾 ";
Regex = " ";
Repeat = "󰑖 ";
RuleSet = "󰅩 ";
Scope = "󰅩 ";
Snippet = "󰩫 ";
Specifier = "󰦪 ";
Statement = "󰅩 ";
String = "󰉾 ";
Struct = " ";
SwitchStatement = "󰺟 ";
Terminal = " ";
Text = " ";
Type = " ";
TypeParameter = "󰆩 ";
Unit = " ";
Value = "󰎠 ";
Variable = "󰀫 ";
WhileStatement = "󰑖 ";
};
};
ui = {
bar = {
separator = " ";
extends = "";
};
menu = {
separator = " ";
indicator = " ";
};
};
};
symbol = {
on_click.__raw = ''
function(symbol)
-- Update current context highlights if the symbol
-- is shown inside a menu
if symbol.entry and symbol.entry.menu then
symbol.entry.menu:update_current_context_hl(symbol.entry.idx)
elseif symbol.bar then
symbol.bar:update_current_context_hl(symbol.bar_idx)
end
-- Determine menu configs
local prev_win = nil ---@type integer?
local entries_source = nil ---@type dropbar_symbol_t[]?
local init_cursor = nil ---@type integer[]?
local win_configs = {}
if symbol.bar then -- If symbol inside a dropbar
prev_win = symbol.bar.win
entries_source = symbol.opts.siblings
init_cursor = symbol.opts.sibling_idx
and { symbol.opts.sibling_idx, 0 }
if symbol.bar.in_pick_mode then
---@param tbl number[]
local function tbl_sum(tbl)
local sum = 0
for _, v in ipairs(tbl) do
sum = sum + v
end
return sum
end
win_configs.relative = 'win'
win_configs.win = vim.api.nvim_get_current_win()
win_configs.row = 0
win_configs.col = symbol.bar.padding.left
+ tbl_sum(vim.tbl_map(
function(component)
return component:displaywidth()
+ symbol.bar.separator:displaywidth()
end,
vim.tbl_filter(function(component)
return component.bar_idx < symbol.bar_idx
end, symbol.bar.components)
))
end
elseif symbol.entry and symbol.entry.menu then -- If inside a menu
prev_win = symbol.entry.menu.win
entries_source = symbol.opts.children
end
-- Toggle existing menu
if symbol.menu then
symbol.menu:toggle({
prev_win = prev_win,
win_configs = win_configs,
})
return
end
-- Create a new menu for the symbol
if not entries_source or vim.tbl_isempty(entries_source) then
return
end
local menu = require('dropbar.menu')
local configs = require('dropbar.configs')
symbol.menu = menu.dropbar_menu_t:new({
prev_win = prev_win,
cursor = init_cursor,
win_configs = win_configs,
---@param sym dropbar_symbol_t
entries = vim.tbl_map(function(sym)
local menu_indicator_icon = configs.opts.icons.ui.menu.indicator
local menu_indicator_on_click = nil
if not sym.children or vim.tbl_isempty(sym.children) then
menu_indicator_icon =
string.rep(' ', vim.fn.strdisplaywidth(menu_indicator_icon))
menu_indicator_on_click = false
end
return menu.dropbar_menu_entry_t:new({
components = {
sym:merge({
name = "",
icon = menu_indicator_icon,
icon_hl = 'dropbarIconUIIndicator',
on_click = menu_indicator_on_click,
}),
sym:merge({
on_click = function()
local current_menu = symbol.menu
while current_menu and current_menu.prev_menu do
current_menu = current_menu.prev_menu
end
if current_menu then
current_menu:close(false)
end
sym:jump()
end,
}),
},
})
end, entries_source),
})
symbol.menu:toggle()
end
'';
preview = {
reorient.__raw = ''
function(_, range)
local invisible = range['end'].line - vim.fn.line('w$') + 1
if invisible > 0 then
local view = vim.fn.winsaveview() --[[@as vim.fn.winrestview.dict]]
view.topline = math.min(
view.topline + invisible,
math.max(1, range.start.line - vim.wo.scrolloff + 1)
)
vim.fn.winrestview(view)
end
end
'';
};
jump = {
reorient.__raw = ''
function(win, range)
local view = vim.fn.winsaveview()
local win_height = vim.api.nvim_win_get_height(win)
local topline = range.start.line - math.floor(win_height / 4)
if
topline > view.topline
and topline + win_height < vim.fn.line('$')
then
view.topline = topline
vim.fn.winrestview(view)
end
end
'';
};
};
sources = {
path = {
max_depth = 16;
relative_to.__raw = ''
function(_, win)
-- Workaround for Vim:E5002: Cannot find window number
local ok, cwd = pcall(vim.fn.getcwd, win)
return ok and cwd or vim.fn.getcwd()
end
'';
path_filter.__raw = "function(_) return true end";
modified.__raw = "function(sym) return sym end";
preview.__raw = ''
function(path)
local stat = vim.uv.fs_stat(path)
if not stat or stat.type ~= 'file' then
return false
end
if stat.size > 524288 then
vim.notify(
string.format(
'[dropbar.nvim] file "%s" too large to preview',
path
),
vim.log.levels.WARN
)
return false
end
return true
end
'';
};
treesitter = {
max_depth = 16;
name_regex = "[=[[#~!@\*&.]*[[:keyword:]]\+!\?\(\(\(->\)\+\|-\+\|\.\+\|:\+\|\s\+\)\?[#~!@\*&.]*[[:keyword:]]\+!\?\)*]=]";
valid_types = [
"array"
"boolean"
"break_statement"
"call"
"case_statement"
"class"
"constant"
"constructor"
"continue_statement"
"delete"
"do_statement"
"element"
"enum"
"enum_member"
"event"
"for_statement"
"function"
"h1_marker"
"h2_marker"
"h3_marker"
"h4_marker"
"h5_marker"
"h6_marker"
"if_statement"
"interface"
"keyword"
"macro"
"method"
"module"
"namespace"
"null"
"number"
"operator"
"package"
"pair"
"property"
"reference"
"repeat"
"rule_set"
"scope"
"specifier"
"struct"
"switch_statement"
"type"
"type_parameter"
"unit"
"value"
"variable"
"while_statement"
"declaration"
"field"
"identifier"
"object"
"statement"
];
};
lsp = {
max_depth = 16;
valid_symbols = [
"File"
"Module"
"Namespace"
"Package"
"Class"
"Method"
"Property"
"Field"
"Constructor"
"Enum"
"Interface"
"Function"
"Variable"
"Constant"
"String"
"Number"
"Boolean"
"Array"
"Object"
"Keyword"
"Null"
"EnumMember"
"Struct"
"Event"
"Operator"
"TypeParameter"
];
request = {
ttl_init = 60;
interval = 1000;
};
};
markdown = {
max_depth = 6;
parse = {
look_ahead = 200;
};
};
terminal = {
icon.__raw = ''
function(_)
return M.opts.icons.kinds.symbols.Terminal or ' '
end
'';
name.__raw = "vim.api.nvim_buf_get_name";
show_current = true;
};
};
};
};
};
}