Skip to content

Commit

Permalink
refactor(symbol): extract default on_click() from `dropbar_symbol_t…
Browse files Browse the repository at this point in the history
…:new()`
  • Loading branch information
bekaboo committed Dec 7, 2023
1 parent 2b7c2d5 commit 5ca5e7f
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 104 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1875,6 +1875,7 @@ basic element of [`dropbar_t`](#dropbar_t) and [`dropbar_menu_entry_t`](#dropbar
| `sibling_idx` | `integer?` | index of the symbol in the siblings |
| `range` | `{start: {line: integer, character: integer}, end: {line: integer, character: integer}}` | range of the symbol in the source window |
| `on_click` | `fun(this: dropbar_symbol_t, min_width: integer?, n_clicks: integer?, button: string?, modifiers: string?)\|false?` | callback to invoke when the symbol is clicked, force disable `on_click` when the value if set to `false` |
| `opts` | `dropbar_symbol_opts_t?` | options passed to `winbar_symbol_t:new()` when the symbols is created |
| `data` | `table?` | any extra data associated with the symbol |
Expand Down
7 changes: 7 additions & 0 deletions doc/dropbar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,13 @@ dropbar_symbol_t.on_click *dropbar_symbol_t.on_click*
about the execute function label in the help page for
'statusline'.

dropbar_symbol_t.opts *dropbar_symbol_t.opts*

Options passed to `dropbar_symbol_t:new()` when the symbols is created

Type ~
`dropbar_symbol_opts_t`?

dropbar_symbol_t.data *dropbar_symbol_t.data*

Any extra data associated with the symbol
Expand Down
210 changes: 106 additions & 104 deletions lua/dropbar/bar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ end
---@field sibling_idx integer? index of the symbol in its siblings
---@field range dropbar_symbol_range_t?
---@field on_click fun(this: dropbar_symbol_t, min_width: integer?, n_clicks: integer?, button: string?, modifiers: string?)|false|nil force disable on_click when false
---@field opts dropbar_symbol_opts_t? options passed to `dropbar_symbol_t:new()` when the symbols is created
---@field data table? any data associated with the symbol
---@field cache table caches string representation, length, etc. for the symbol
local dropbar_symbol_t = {}
Expand Down Expand Up @@ -95,6 +96,109 @@ end
---@field data table? any data associated with the symbol
---@field cache table? caches string representation, length, etc. for the symbol

---Default `on_click()` callback for dropbar symbols
---@param symbol dropbar_symbol_t
---@return nil
local function default_on_click(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 }
---@param tbl number[]
local function _sum(tbl)
local sum = 0
for _, v in ipairs(tbl) do
sum = sum + v
end
return sum
end
if symbol.bar.in_pick_mode then
win_configs.relative = 'win'
win_configs.win = vim.api.nvim_get_current_win()
win_configs.row = 0
win_configs.col = symbol.bar.padding.left
+ _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')
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

---Create a dropbar symbol instance
---@param opts dropbar_symbol_opts_t? dropbar symbol structure
---@return dropbar_symbol_t
Expand All @@ -105,110 +209,8 @@ function dropbar_symbol_t:new(opts)
name = '',
icon = '',
cache = {},
on_click = opts
---@param this dropbar_symbol_t
and function(this, _, _, _, _)
-- Update current context highlights if the symbol
-- is shown inside a menu
if this.entry and this.entry.menu then
this.entry.menu:update_current_context_hl(this.entry.idx)
elseif this.bar then
this.bar:update_current_context_hl(this.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 this.bar then -- If symbol inside a winbar
prev_win = this.bar.win
entries_source = opts.siblings
init_cursor = opts.sibling_idx and { opts.sibling_idx, 0 }
---@param tbl number[]
local function _sum(tbl)
local sum = 0
for _, v in ipairs(tbl) do
sum = sum + v
end
return sum
end
if this.bar.in_pick_mode then
win_configs.relative = 'win'
win_configs.win = vim.api.nvim_get_current_win()
win_configs.row = 0
win_configs.col = this.bar.padding.left
+ _sum(vim.tbl_map(
function(component)
return component:displaywidth()
+ this.bar.separator:displaywidth()
end,
vim.tbl_filter(function(component)
return component.bar_idx < this.bar_idx
end, this.bar.components)
))
end
elseif this.entry and this.entry.menu then -- If inside a menu
prev_win = this.entry.menu.win
entries_source = opts.children
end

-- Toggle existing menu
if this.menu then
this.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')
this.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 = this.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),
})
this.menu:toggle()
end,
opts = opts,
on_click = opts and default_on_click,
}, opts or {}),
getmetatable(opts or {})
),
Expand Down

0 comments on commit 5ca5e7f

Please sign in to comment.