Skip to content

Commit

Permalink
fix(menu): wrong prev_window if opened from non-current window
Browse files Browse the repository at this point in the history
1. dropbar_menu_t.prev_window is wrongly set to the current window
   i.e. the window get from vim.api.nvim_get_current_win() when the
   menu actually belongs to a non-current window
2. To reproduce:
   - Open nvim in split with dropbar.nvim attached to two windows,
     1000 and 1001
   - Keep the cursor in win 1001, open a menu in win 1000 by clicking
     a component in the winbar with mouse
   - prev_win of the menu is set to 1001 instead of 1000, and clicking
     on a symbol in the menu sets the cursor postion in 1001 instead of
     of 1000
3. Cause: dropbar_menu_t:open() will set dropbar_menu_t.prev_win to
          vim.api.nvim_get_current_win()
4. Fix: do not set prev_win explictly in dropbar_menu_t:open(), instead
        set it in the default on_click() callback function of
        dropbar_symbol_t when toggling or creating menus
  • Loading branch information
bekaboo committed Jun 6, 2023
1 parent 1e56ced commit 094f34d
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 68 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ Declared and defined in [`lua/dropbar/menu.lua`](https://github.com/Bekaboo/drop
| ------ | ------ |
| `dropbar_menu_t:new(opts: dropbar_menu_opts_t?): dropbar_menu_t` | constructor of `dropbar_menu_t` |
| `dropbar_menu_t:del()` | destructor of `dropbar_menu_t` |
| `dropbar_menu_t:eval_win_configs(win_configs: table?)` | evaluate window configurations (`dropbar_menu_t.win_configs` merged with param `win_configs`) and store the result in `dropbar_menu_t._win_configs` |
| `dropbar_menu_t:eval_win_configs()` | evaluate window configurations `dropbar_menu_t.win_configs` and store the result in `dropbar_menu_t._win_configs` |
| `dropbar_menu_t:get_component_at(pos: integer[]): dropbar_symbol_t?, { start: integer, end: integer }?` | get the component<sub>[`dropbar_symbol_t`](#dropbar_symbol_t)</sub> at position `pos` and its range it occupies in the entry it belongs to |
| `dropbar_menu_t:click_at(pos: integer[], min_width: integer?, n_clicks: integer?, button: string?, modifiers: string?)` | simulate a click at `pos` in the menu |
| `dropbar_menu_t:click_on(symbol: dropbar_symbol_t, min_width: integer?, n_clicks: integer?, button: string?, modifiers: string?)` | simulate a click at the component `symbol`<sub>[`dropbar_symbol_t`](#dropbar_symbol_t)</sub> of the menu |
Expand All @@ -1298,9 +1298,9 @@ Declared and defined in [`lua/dropbar/menu.lua`](https://github.com/Bekaboo/drop
| `dropbar_menu_t:hl_range_single(line: integer?, range: { start: integer, end: integer }?, hlgroup: string?)` | add highlight to a single range in a single line in the menu buffer; `hlgroups` defaults to `'DropBarMenuHoverSymbol'`<br> *all highlights with the same hlgroup added by this functions before will be cleared |
| `dropbar_menu_t:update_hover_hl(pos: integer[])` | update the hover highlights (`DropBarMenuHover*`) assuming the cursor/mouse is hovering at `pos` in the menu |
| `dropbar_menu_t:make_buf()` | create the menu buffer from the entries<sub>[`dropbar_menu_entry_t`](#dropbar_menu_entry_t) |
| `dropbar_menu_t:open(win_configs: table?)` | open the menu with window configurations `dropbar_menu_t.win_configs` merged with param `win_configs` |
| `dropbar_menu_t:open()` | open the menu with evaluated window configurations `dropbar_menu_t._win_configs` |
| `dropbar_menu_t:close()` | close the menu |
| `dropbar_menu_t:toggle(win_configs; table)` | toggle the menu, passing `win_configs` to `dropbar_menu_t:open()` if decide to open the menu |
| `dropbar_menu_t:toggle()` | toggle the menu |
#### `dropbar_menu_entry_t`
Expand Down
17 changes: 3 additions & 14 deletions doc/dropbar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1360,14 +1360,11 @@ dropbar_menu_t:del() *dropbar_menu_t:del()*
Destructor of `dropbar_menu_t`

*dropbar_menu_t:eval_win_configs()*
dropbar_menu_t:eval_win_configs([{win_configs}])
dropbar_menu_t:eval_win_configs()

Evaluate window configurations |dropbar_menu_t.win_configs| and store
the result in |dropbar_menu_t._win_configs|

Parameters ~
• {win_configs} (table?): window configurations to override

dropbar_menu_t:get_component_at({pos}) *dropbar_menu_t:get_component_at()*

Get the component at position `pos` and the range it occupies in the
Expand Down Expand Up @@ -1459,26 +1456,18 @@ dropbar_menu_t:make_buf() *dropbar_menu_t:make_buf()*
Create the menu buffer from the entries
|dropbar-developers-classes-dropbar_menu_entry_t|

dropbar_menu_t:open([{win_configs}]) *dropbar_menu_t:open()*
dropbar_menu_t:open() *dropbar_menu_t:open()*

Open the menu with window configurations |dropbar_menu_t.win_configs|
merged with {win_configs}

Parameters ~
• {win_configs} (table?): window configurations to override

dropbar_menu_t:close() *dropbar_menu_t:close()*

Close the menu

dropbar_menu_t:toggle([{win_configs}]) *dropbar_menu_t:toggle()*
dropbar_menu_t:toggle() *dropbar_menu_t:toggle()*

Toggle the menu

Parameters ~
• {win_configs} (table?): window configurations passing to
|dropbar_menu_t:open()|

..............................................................................
DROPBAR_MENU_ENTRY_T *dropbar-developers-classes-dropbar_menu_entry_t*
*dropbar_menu_entry_t*
Expand Down
86 changes: 46 additions & 40 deletions lua/dropbar/bar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,57 +74,63 @@ function dropbar_symbol_t:new(opts)
this.entry.menu:hl_line_single(this.entry.idx)
end

-- Called in pick mode, open the menu relative to the symbol
-- position in the winbar
local menu_win_configs = nil
if this.bar and this.bar.in_pick_mode then
local col = 0
for i, component in ipairs(this.bar.components) do
if i < this.bar_idx then
col = col
+ component:displaywidth()
+ this.bar.separator:displaywidth()
-- 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.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
menu_win_configs = {
relative = 'win',
row = 0,
col = col,
}
elseif this.entry and this.entry.menu then -- If inside a menu
prev_win = this.entry.menu.win
entries_source = opts.children
end

-- Toggle menu on click, or create one if menu don't exist:
-- 1. If symbol inside a winbar, create a menu with entries
-- containing the symbol's siblings
-- 2. Else if symbol inside a menu, create menu with entries
-- containing the symbol's children
-- Toggle existing menu
if this.menu then
this.menu:toggle(menu_win_configs)
this.menu.win_configs = vim.tbl_deep_extend(
'force',
this.menu.win_configs,
win_configs
)
this.menu.prev_win = prev_win
this.menu:toggle()
return
end

local menu_prev_win = nil ---@type integer?
local menu_entries_source = nil ---@type dropbar_symbol_t[]?
local menu_cursor_init = nil ---@type integer[]?
if this.bar then -- If symbol inside a winbar
menu_prev_win = this.bar and this.bar.win
menu_entries_source = opts.siblings
menu_cursor_init = opts.sibling_idx and { opts.sibling_idx, 0 }
elseif this.entry and this.entry.menu then -- If inside a menu
menu_prev_win = this.entry.menu.win
menu_entries_source = opts.children
end
if
not menu_entries_source or vim.tbl_isempty(menu_entries_source)
then
-- 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 = menu_prev_win,
cursor = menu_cursor_init,
win_configs = menu_win_configs,
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 =
Expand All @@ -150,7 +156,7 @@ function dropbar_symbol_t:new(opts)
}),
},
})
end, menu_entries_source),
end, entries_source),
})
this.menu:toggle()
end,
Expand Down
17 changes: 6 additions & 11 deletions lua/dropbar/menu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -220,15 +220,12 @@ end

---Evaluate window configurations
---Side effects: update self._win_configs
---@param win_configs table? window configurations to override
---@return nil
---@see vim.api.nvim_open_win
function dropbar_menu_t:eval_win_configs(win_configs)
function dropbar_menu_t:eval_win_configs()
-- Evaluate function-valued window configurations
self._win_configs = {}
for k, config in
pairs(vim.tbl_deep_extend('force', self.win_configs, win_configs or {}))
do
for k, config in pairs(self.win_configs) do
if type(config) == 'function' then
self._win_configs[k] = config(self)
else
Expand Down Expand Up @@ -509,9 +506,8 @@ end

---Open the menu
---Side effect: change self.win and self.buf
---@param win_configs table? window configurations to override
---@return nil
function dropbar_menu_t:open(win_configs)
function dropbar_menu_t:open()
if self.is_opened then
return
end
Expand All @@ -528,7 +524,7 @@ function dropbar_menu_t:open(win_configs)
self.prev_win = parent_menu.win
end

self:eval_win_configs(win_configs)
self:eval_win_configs()
self:make_buf()
self.win = vim.api.nvim_open_win(self.buf, true, self._win_configs)
self.is_opened = true
Expand Down Expand Up @@ -569,13 +565,12 @@ function dropbar_menu_t:close()
end

---Toggle the menu
---@param win_configs table? window configurations to override
---@return nil
function dropbar_menu_t:toggle(win_configs)
function dropbar_menu_t:toggle()
if self.is_opened then
self:close()
else
self:open(win_configs)
self:open()
end
end

Expand Down

0 comments on commit 094f34d

Please sign in to comment.