dropbar.nvim
dropbar.nvim copied to clipboard
navigating menu siblings directly from the bar.
hi. of course let me begin, thanks for creating this great plugin! i have a use case that im exploring and i wonder if im just going about it all wrong.
step one: i'd like to enter the dropbar focus using api:pick, and focus on the dropbar symbol that is relevant to my cursor position. step two: i'd like to traverse up and down in that menu (this works beautifully) step three: i'd like to traverse to the sibling top level drop bar menus. aka... if i enter pick mode and i only have 3 options (a, b, c) i get into c, by way of my keyboard shortcut, and then if i can call pick again on a relative number :pick(-1) or :pick(+1)... id like move from c => b, and then back to c
i was able to hack my way to that behavior on version 10 (commit d0c78c570db0f5941f85ba54522c0f01427cdf67) ... the commit right after that breaks my workaround.
is this behavior currently supported and im just missing it in the docs or is it within the scope of the project to support? im couped to version 10 for now to support my use cases.. thanks so much!
local initial_idx = nil
local current_bar = nil
function activate_top_level_components()
current_bar = require("dropbar.utils").bar.get_current()
if not current_bar then
return
end
for _, component in ipairs(current_bar.components) do
if component.name_hl == "DropBarFileName" then
if current_bar.components[component.bar_idx + 1] ~= nil then
current_idx = component.bar_idx + 1
else
current_idx = component.bar_idx
end
initial_idx = current_idx
break
end
end
end
function handleEnterDropBarUp()
local dropbar_t = require("dropbar.utils").bar.get_current()
if not dropbar_t then
-- send up key
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Up>", true, true, true), "n", true)
return
end
activate_top_level_components()
if not current_bar then
return
end
if not current_idx or current_bar.components[current_idx] == nil then
return
end
current_bar:pick(current_idx)
end
function handleEnterDropBarDown()
local dropbar_t = require("dropbar.utils").bar.get_current()
if not dropbar_t then
-- send up key
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Down>", true, true, true), "n", true)
return
end
activate_top_level_components()
if not current_bar then
return
end
if not current_idx or current_bar.components[current_idx] == nil then
return
end
current_bar:pick(current_idx)
end
vim.keymap.set("n", "K", handleEnterDropBarUp, { noremap = true, silent = true })
vim.keymap.set("n", "J", handleEnterDropBarDown, { noremap = true, silent = true })
vim.keymap.set("n", "H", function()
local dropbar = require("dropbar.api").get_current_dropbar()
if dropbar == nil then
local menu = require("dropbar.utils").menu.get_current()
if menu == nil or current_bar == nil or current_idx == 1 then
return
end
current_idx = current_idx - 1
menu:close()
current_bar:pick(current_idx)
return
end
if not dropbar.in_pick_mode then
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("_", true, true, true), "n", true)
return
end
end, { noremap = true, silent = true })
vim.keymap.set("n", "L", function()
local dropbar = require("dropbar.api").get_current_dropbar()
if dropbar == nil then
local menu = require("dropbar.utils").menu.get_current()
if menu == nil or current_idx + 1 > initial_idx or current_bar == nil then
return
end
current_idx = current_idx + 1
menu:close()
current_bar:pick(current_idx)
return
end
if not dropbar.in_pick_mode then
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("$", true, true, true), "n", true)
return
end
end, { noremap = true, silent = true })
I suspect commit c824f033d0e6b3a4cce550d7a767a516b99cee56 breaks this, not sure because I haven't tested it on my machine.
:pick(-1) or :pick(+1)
I will consider adding builtin support for this in the future. PR welcome ofc.
I would like to share my prefered navigation flow - which I used to use in VSCode.
It goes like this:
hcloses the dropdown menu and moves to the parent, or if there is no parent moves to the breadcrumb beforelexpands the current selected item:
A > [B] > C > D --> A > [B] > C > D
| |
|-- b1 |-- b1
|-- [b2] |-- [b2] > |
|-- b3 | |-- [b21]
| |-- b22
| |-- b23
|-- b3
<C-h>moves directly to the previous breadcrumb (closing all dropdowns)
A > [B] > C > D --> [A] > B > C > D
| |
|-- b1 |-- [a1]
|-- [b2] > | |-- a2
| |-- [b21] |-- a3
| |-- b22
| |-- b23
|-- b3
<C-l>moves directly to the next breadcrumb (closing all dialogs)
A > [B] > C > D --> A > B > [C] > D
| |
|-- b1 |-- [c1]
|-- [b2] > | |-- c2
| |-- [b21] |-- c3
| |-- b22
| |-- b23
|-- b3
I've come close to doing that with dropbar.nvim - but my naive implementation runs into problems with indexes sometimes. I believe this are reasonable motions to have.
Hey, don't know if it's of any help, but here follows what worked for me:
{
keymaps = {
["H"] = function()
local root = require("dropbar.utils").menu.get_current():root()
root:close()
local dropbar = require("dropbar.api").get_dropbar(vim.api.nvim_win_get_buf(root.prev_win), root.prev_win)
if not dropbar then
root:toggle()
return
end
local current_idx
for idx, component in ipairs(dropbar.components) do
if component.menu == root then
current_idx = idx
break
end
end
if current_idx == nil or current_idx == 0 then
root:toggle()
return
end
vim.defer_fn(function() dropbar:pick(current_idx - 1) end, 100)
end,
["L"] = function()
local root = require("dropbar.utils").menu.get_current():root()
root:close()
local dropbar = require("dropbar.api").get_dropbar(vim.api.nvim_win_get_buf(root.prev_win), root.prev_win)
if not dropbar then
dropbar = require("dropbar.utils").bar.get_current()
if not dropbar then
root:toggle()
return
end
end
local current_idx
for idx, component in ipairs(dropbar.components) do
if component.menu == root then
current_idx = idx
break
end
end
if current_idx == nil or current_idx == #dropbar.components then
root:toggle()
return
end
vim.defer_fn(function() dropbar:pick(current_idx + 1) end, 100)
end,
},
}