Closed echasnovski closed 1 month ago
This is now resolved on latest main
. The final feature set of built-in bookmark support is a result of several iterations:
m<char>
and '<char>
should be enough.After having implemented the get_explorer_state()
, going full way of having a dedicated exported functionality seemed to be acceptable. The idea was to have a single set_branch()
function which can make current explorer to show a supplied branch (with custom focus level). And it indeed possible with set_branch()
. The actually implemented part of interactive experience was planned to be a single "focus on alternative" mapping (something like -
) which would act like this:
After trying it out, the result felt unintuitive and less usable than I would have liked. The main reason is that having used it once, setting completely separate pair of alternative spots was needlessly complicated (from first spot press -
(registers current spot as alt; switches to previous alt) -> navigating to a second spot should have been done from the previous alt). Hence, there needed to be at least pair of mappings ("set as alt" and "go to alt"), but at this point implementing full bookmarks approach is similar in code footprint and much more versatile.
After implementing bookmarks which save and restore whole branch, there were slight issues with enabled preview: jumping back to bookmark forced cursor at its place during bookmark creation. This is due to the fact that preview is treated as part of saved and restored branch, and restoring branch puts cursor on the entry of directory child (for easier navigation).
The solution is to save and restore only a single directory path of a focused window. As this also means less complicated data structures to store and maintain in get_explorer_state()
, this seems like a better design. Although has less "wow effect" than restoring the whole branch.
g?
) also show present bookmarks. This visibly improves usability.Small suggestion for focusing a bookmark: It would be nice for there to also be a `mark
keymap (as the familiar mark behavior has) that focuses the bookmark window (and maybe also jumps to the file where the bookmark was set).
Small suggestion for focusing a bookmark: It would be nice for there to also be a
`mark
keymap (as the familiar mark behavior has) that focuses the bookmark window (and maybe also jumps to the file where the bookmark was set).
Thanks for the suggestion!
This sounds reasonable to me only if having bookmark and built-in mark be as similar as possible. I am afraid, this is not the goal. If not accounting for that, having two mappings do the same thing sounds a bit of a stretch.
Same action under different LHS can be achieved by custom buffer-local mappings. The most robust way is to create own function to use as RHS in buffer-local mapping. Something like this:
local mark_goto = function()
local ok, id = pcall(vim.fn.getcharstr)
if not ok or id == '\27' or id == '' then return end
local data = MiniFiles.get_explorer_state().bookmarks[id]
if data == nil then return error('No bookmark with id ' .. vim.inspect(id)) end
local path = vim.is_callable(data.path) and data.path() or data.path
local state = MiniFiles.get_explorer_state()
MiniFiles.set_bookmark('`', state.branch[state.depth_focus], { desc = 'Before latest ` jump' })
MiniFiles.set_branch({ path })
end
local make_keymaps = function(args)
vim.keymap.set('n', '`', mark_goto, { buffer = args.data.buf_id, desc = 'Go to bookmark #2' })
end
vim.api.nvim_create_autocmd('User', { pattern = 'MiniFilesBufferCreate', callback = make_keymaps })
A less robust method (because there is no guarantee that 'MiniFilesBufferCreate' will be executed after built-in mappings are created) is to duplicate the existing '
mapping:
local duplicate_mark_goto = function()
local map_data = vim.fn.maparg("'", 'n', false, true)
map_data.lhs, map_data.lhsraw, map_data.desc = '`', '`', 'Go to bookmark (also)'
vim.fn.mapset(map_data)
end
vim.api.nvim_create_autocmd('User', { pattern = 'MiniFilesBufferCreate', callback = duplicate_mark_goto })
... (and maybe also jumps to the file where the bookmark was set)
This part is a bit tricky to implement on the user side, as it requires also keeping track of focused file system entry when bookmark was created. One of the bookmark iterations was with similar behavior (if preview was enabled) and I found it really confusing in action. Preserving the state just as it was before leaving seems to be the better default.
Do you have any particular workflow that makes this behavior easier?
Edit: added automatic creation of `
bookmark to point to the "before latest ` jump" path. Similar to how it is now done in built-in mark_goto
action, but keeping them separate (i.e. not setting '
bookmark when jumping with `
). Adjust this to fit personal taste.
@echasnovski Thanks for the suggestions! I understand if the `
idea goes beyond the minimality of the plugin.
Do you have any particular workflow that makes this behavior easier?
Are you referring to a case where I find bookmarking the file a better default? If so, I often deal with folders containing lots of files, often with very similar names, and scrolling through the explorer window is tedious. Bookmarking a specific file saves the scrolling, and also allows for multiple bookmarks in the same directory.
That is definitely a "nice to have" though, and I'm fine with living without it if introducing it adds unnecessary complexity to the plugin.
Are you referring to a case where I find bookmarking the file a better default? If so, I often deal with folders containing lots of files, often with very similar names, and scrolling through the explorer window is tedious. Bookmarking a specific file saves the scrolling, and also allows for multiple bookmarks in the same directory.
Ah, I see. I slightly misunderstood the scope of the suggestion. I'll think about supporting setting bookmark on a particular directory entry.
The slight problem with this feature is that it has to be done as a separate bookmark property (like fs_entry
or something). Otherwise it becomes ambiguous in case of a directory (is directory itself a bookmark or its parent with with it as entry). I'll take a look.
@MariaSolOs, after thinking about it more, it still seems to be a better compromise to suggest users to implement this themselves. The main reason for this is mostly because immediately navigating to a specific file seems to indeed be only for "try navigating to a specific part of directory" use case.
Most of the parts to implement this are present: set_branch()
to show the target directory and get_fs_entry()
to find the target file (via iterating through buffer lines; might need to be done in a vim.schedule()
d function).
@echasnovski that's fair. As said before, I don't want the suggestion to unnecessarily complicate mini.files
. Thank you for the hints on how to implement it!
Contributing guidelines
Module(s)
mini.files
Description
Consider adding functions and mappings for saving and restoring explorer branches for quick navigation to known destinations.
Common problem during file system manipulations is the need to
hhhhjjjllll
in order to navigate back and forth between two directories. This can be solved by "save current branch under identifierx
" and "restore branch under identifierx
" actions. Similar to how built-in marks work inside and across files.Saving branches (like
{ '/home/user/.config', '/home/user/.config/nvim' }
) instead of single destination directory (like'/home/user/.config/nvim'
) seems to both provide more flexibility and be more aligned with internal implementation.This can also solve the problem of #572 by saving predefined set of branches inside autocommand for
MiniFilesExplorerOpen
event.Notes:
m
and'
to mimic built-in marks.get_branch()
andset_branch()
are necessary for this.