Skip to content

Commit

Permalink
feat(config)!: open menu relative to clicked symbol by default, fix #37
Browse files Browse the repository at this point in the history
  • Loading branch information
bekaboo committed Jul 2, 2023
1 parent 5ac7e53 commit a0faad2
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 21 deletions.
44 changes: 34 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,16 +444,28 @@ https://github.com/Bekaboo/dropbar.nvim/assets/76579810/e8c1ac26-0321-4762-9975-
return menu.prev_menu
and menu.prev_menu.clicked_at
and menu.prev_menu.clicked_at[1] - vim.fn.line('w0')
or 1
or 0
end,
---@param menu dropbar_menu_t
col = function(menu)
return menu.prev_menu and menu.prev_menu._win_configs.width or 0
end,
relative = function(menu)
return menu.prev_menu and 'win' or 'mouse'
if menu.prev_menu then
return menu.prev_menu._win_configs.width
end
local mouse = vim.fn.getmousepos()
local bar = require('dropbar.api').get_dropbar(
vim.api.nvim_win_get_buf(menu.prev_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 = function(menu)
return menu.prev_menu and menu.prev_menu.win
or vim.fn.getmousepos().winid
end,
height = function(menu)
return math.max(
Expand Down Expand Up @@ -919,16 +931,28 @@ menu:
return menu.prev_menu
and menu.prev_menu.clicked_at
and menu.prev_menu.clicked_at[1] - vim.fn.line('w0')
or 1
or 0
end,
---@param menu dropbar_menu_t
col = function(menu)
return menu.prev_menu and menu.prev_menu._win_configs.width or 0
end,
relative = function(menu)
return menu.prev_menu and 'win' or 'mouse'
if menu.prev_menu then
return menu.prev_menu._win_configs.width
end
local mouse = vim.fn.getmousepos()
local bar = require('dropbar.api').get_dropbar(
vim.api.nvim_win_get_buf(menu.prev_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 = function(menu)
return menu.prev_menu and menu.prev_menu.win
or vim.fn.getmousepos().winid
end,
height = function(menu)
return math.max(
Expand Down
43 changes: 37 additions & 6 deletions doc/dropbar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -508,16 +508,29 @@ the menu:
return menu.prev_menu
and menu.prev_menu.clicked_at
and menu.prev_menu.clicked_at[1] - vim.fn.line('w')
or 1
or 0
end,
---@param menu dropbar_menu_t
col = function(menu)
return menu.prev_menu and menu.prev_menu._win_configs.width or 0
end,
relative = function(menu)
return menu.prev_menu and 'win' or 'mouse'
if menu.prev_menu then
return menu.prev_menu._win_configs.width
end
local mouse = vim.fn.getmousepos()
local bar = require('dropbar.api').get_dropbar(
vim.api.nvim_win_get_buf(menu.prev_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 = function(menu)
return menu.prev_menu and menu.prev_menu.win
return menu.prev_menu and menu.prev_menu.win
or vim.fn.getmousepos().winid
end,
height = function(menu)
return math.max(
Expand Down Expand Up @@ -1111,6 +1124,24 @@ dropbar_t:pick([{idx}]) *dropbar_t:pick()*
Parameters ~
{idx} (integer?): The index of the component to pick

*dropbar_t:get_component_at()*
dropbar_t:get_component_at({col}[, {look_ahead}])

Get the component at column {col} and the range it occupies in the
menu

Parameters ~
{col} (integer): The column to look at
• {look_ahead} (boolean?):
whether to look ahead to find a component if no component is
found at {col}

Returns ~
(`dropbar_symbol_t`): the component at {col}

A table with fields `start` and `end` representing the range the
component occupies in the menu

dropbar_t:__tostring() *dropbar_t:__tostring()*

Meta method to convert dropbar_t to its string representation
Expand Down
29 changes: 29 additions & 0 deletions lua/dropbar/bar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ function dropbar_symbol_t:new(opts)
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(
Expand Down Expand Up @@ -595,6 +596,34 @@ function dropbar_t:pick(idx)
end)
end

---Get the component at the given position in the winbar
---@param col integer 0-indexed, byte-indexed
---@param look_ahead boolean? whether to look ahead for the next component if the given position does not contain a component
---@return dropbar_symbol_t?
---@return {start: integer, end: integer}? range of the component in the menu, byte-indexed, 0-indexed, start-inclusive, end-exclusive
function dropbar_t:get_component_at(col, look_ahead)
local col_offset = self.padding.left
for _, component in ipairs(self.components) do
-- Use display width instead of byte width here because
-- vim.fn.getmousepos().wincol is the display width of the mouse position
-- and also the menu window needs to be opened with relative to the
-- display position of the winbar symbol to be aligned with the symbol
-- on the screen
local component_len = component:displaywidth()
if
(look_ahead or col >= col_offset) and col < col_offset + component_len
then
return component,
{
start = col_offset,
['end'] = col_offset + component_len,
}
end
col_offset = col_offset + component_len + self.separator:displaywidth()
end
return nil, nil
end

---Get the string representation of the dropbar
---@return string
function dropbar_t:__tostring()
Expand Down
22 changes: 17 additions & 5 deletions lua/dropbar/configs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -261,16 +261,28 @@ M.opts = {
return menu.prev_menu
and menu.prev_menu.clicked_at
and menu.prev_menu.clicked_at[1] - vim.fn.line('w0')
or 1
or 0
end,
---@param menu dropbar_menu_t
col = function(menu)
return menu.prev_menu and menu.prev_menu._win_configs.width or 0
end,
relative = function(menu)
return menu.prev_menu and 'win' or 'mouse'
if menu.prev_menu then
return menu.prev_menu._win_configs.width
end
local mouse = vim.fn.getmousepos()
local bar = require('dropbar.api').get_dropbar(
vim.api.nvim_win_get_buf(menu.prev_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 = function(menu)
return menu.prev_menu and menu.prev_menu.win
or vim.fn.getmousepos().winid
end,
height = function(menu)
return math.max(
Expand Down
24 changes: 24 additions & 0 deletions tests/bar_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,30 @@ describe('[bar]', function()
winbar:pick(2)
assert.spy(agent).was_called()
end)
it('gets the component according to given position', function()
-- sym1 has width 0 and is at the beginning of the bar
-- thus cannot be picked by get_component_at()
local sep_width = winbar.separator:displaywidth()
local current_col = 0
assert.is_nil(winbar:get_component_at(current_col))
assert.are.equal(sym2, winbar:get_component_at(current_col, true))
current_col = current_col
+ winbar.padding.left
+ sym1:displaywidth()
+ sep_width
assert.are.equal(sym2, winbar:get_component_at(current_col))
current_col = current_col + sym2:displaywidth()
assert.are.equal(sym3, winbar:get_component_at(current_col, true))
current_col = current_col + sep_width
assert.are.equal(sym3, winbar:get_component_at(current_col))
current_col = current_col + sym3:displaywidth()
assert.are.equal(sym4, winbar:get_component_at(current_col, true))
current_col = current_col + sep_width
assert.are.equal(sym4, winbar:get_component_at(current_col))
current_col = current_col + sym4:displaywidth()
assert.is_nil(winbar:get_component_at(current_col, true))
assert.is_nil(winbar:get_component_at(current_col))
end)
it('deletes itself', function()
local agents = vim.tbl_map(function(component)
return spy.on(component, 'del')
Expand Down

0 comments on commit a0faad2

Please sign in to comment.