nvim-window-picker
nvim-window-picker copied to clipboard
Options for custom user logic
hint.pre_assign_chars: this started out as an experiment of unifying the familiar HJKL window navigation hints with the amazing features this plugin has to offer, and evolved into this generalized option.
process_unknown_char: this is required in order to handle (control-) chars not available as hints. The original intention was to quickly switch between the last 2 windows using <C-w><C-w>, but in its general form could cover more potential use-cases.
This is the lazy.nvim config I'm using with the current branch and it's working really well for me so far.
function winid_from_winnr(arg)
local nr
if arg then
nr = vim.fn.winnr(arg)
else
nr = vim.fn.winnr()
end
if nr then
return vim.fn.win_getid(nr)
else
return nil
end
end
return {
's1n7ax/nvim-window-picker',
branch = 'release/2.0',
keys = {
"<C-w>"
},
opts = {
hint = {
-- Get a chance to assign keys to windows based on user-defined logic
-- before window-picker assigns them from available selection_chars.
-- windowlist: sparse list winid -> char (char initialized as false)
-- Should return the updated windowlist with pre-assigned chars.
pre_assign_chars = function(windowlist)
-- Show H/J/K/L hints where you would expect them
local keys = { 'h', 'j', 'k', 'l', }
for _, k in ipairs(keys) do
local winid = winid_from_winnr(k)
if winid and windowlist[winid] ~= nil then
windowlist[winid] = k:upper()
end
end
return windowlist
end,
},
-- Get a last chance to match a window when user presses a key not assigned in
-- windowlist.
-- Returns winid for the unknown char (doesn't have to be a winid present on the
-- windowlist - the windowlist arg is provided for completeness). Alternatively, user
-- can return nil and run nvim_set_current_win or any custom logic.
process_unknown_char = function(char, windowlist)
vim.print(windowlist)
local cw = vim.api.nvim_replace_termcodes("<C-w>", true, true, true)
if char == cw then
-- always go to last window
return winid_from_winnr("#")
else
-- could also nvim_set_current_win here as long as we return nil
return nil
end
end,
autoselect_one = true,
include_current_win = false,
selection_chars = 'FDG' .. 'UI' .. 'RET' .. 'VN' .. 'MC' .. 'WOQP',
},
config = function(_, opts)
local picker = require("window-picker")
picker.setup(opts)
vim.keymap.set("n", "<C-w>", function()
local win = picker.pick_window(opts)
if (win) then
api.nvim_set_current_win(win)
end
end, { desc = "Pick a window" })
end
}
I understand the api for 2.0 is still in flux and things are bound to change, so please re-arrange as you see fit, as long as we maintain enough flexibility to cover use-cases like the ones outlined above.
As a separate suggestion, it would be nice if pick_window() would also return the char pressed along with the window id like so:
{
char = "f",
winid = 1005
}
Example use-case: neo-tree has integration commands like split_with_window_picker and vsplit_with_window_picker. It would be nice if we could differentiate between f/F so we know to open the split before or after the targeted window.
@nkgm Hi, super late but I don't quite understand the feature. How is this different from selection_chars = 'FJDKSLA;CMRUEIWOQP' configuration value?
Hi @s1n7ax, apologies for the late response!
pre_assign_chars will work in harmony with selection_chars, except pre_assign_chars will be assigned with higher priority. The logic by which they will be assigned is left to the user config. My config listed above will assign HJKL to their "natural" position ie H will be used as a hint to the left of the current window, L to the right and so on. My user config pre-assigns windows in a similar way with <C-w>{H,J,K,L}. This pre-assigned mapping of winid -> char is then returned to the plugin and the remaining windows are assigned hints from selection_chars in the usual way.
process_unknown_char is a generalization of this concept, so for example, you can have a hook that looks for when the user pressed w and switch to the last window like <C-w>w. Using these options, you could use <C-w> as your main picker key, and still maintain most default functionality of the "nnoremapped" <C-w>.
As for my second comment about pick_window(), consider this example: you are currently in a Neotree window and you want to open the selected file as a split to the left or right of the picked window. If pick_window() would also return the actual key pressed by the user, you could eg differentiate between f/F to open the split before/after the targeted window.
Please note, all opinionated behavior listed above is implemented in user config. This PR merely adds enough flexibility to the core, so the opinionated parts may reside in the user's config, and should be backwards compatible with the existing config options.