I've been trying out a few different vim plugins and features for "marks". In general I really like the idea of using marks to navigate around larger files. My previous approach was to open up the files I'm interested in and then using my open buffers to switch between the things I'm working on. This works about as well as it does in other editors, but leaves a lot to be desired.
One issue is that you frequently open a random file, make a tiny change, and
then switch to something else, but now it's cluttering your list of open buffers
unless you lose it with :bd
. Bit of a pain, but not the end of the world. The
bigger issue is that you lose all your open files when you close vim. There's
things like "vim sessions", but this all seems like a bit of a hack. My main
"solution" to this problem was to instead list the files I have unstaged with
/git. This works quite well.... up until you make a commit and then need to
edit the same files again quick.
Marks have quite a few major advantages:
- Work per line rather than per file. You can even set multiple in large files.
- Independent of vim session. You can close vim without losing your marks.
- Only added when you set one. Still works nicely with "buffers" and "oldfiles".
However, marks in vim have loads of issues:
- Per file OR global. No per project / cwd marks available by default.
- No visual "marking" to indicate where you have marks setup.
- No easy way to "list all" marks and pick one.
- No hotkey to delete (or better toggle) marks.
- Needing to assign a letter to every mark.
Solutions
Alternative mark-like systems
There are quite a few plugins, old and new, which effectively replace vim's mark system with something designed a bit better. These seems to work fairly well, but naturally the interoperability with other plugins suffers as they do not use the "default" feature.
- https://github.com/ThePrimeagen/harpoon
- https://github.com/MattesGroeger/vim-bookmarks
- https://github.com/chentoast/marks.nvim
- https://github.com/kshenoy/vim-signature
Tweaks to the standard system
I think the standard vim mark implementation is probably redeemable. It's not super ideal, but I don't think it's the worst thing ever and I'd much prefer fixing the default system than tacking on another system that doesn't quite fit correctly with the rest of vim.
Per project rather than global
In vim you can set a file-local mark with mj
where j
is any lowercase letter
of your choosing. Pressing mJ
instead sets a global mark which will always
take you to that file and location from any vim instance anywhere on your
system. It's actually quite neat if you're the type of person that keeps a
single vim instance open all day and want a hotkey to jump you into different
projects. I'm however, not that kind of person. I navigate my filesystem with
nnn or jump and then open vim when I want to edit files. As a result I
want my "global" marks to be global relative to a single project directory
rather than my whole system.
I found this reddit post:
https://libredd.it/r/vim/comments/povbkh/tip_viminfo_per_project/
Which suggests setting let &viminfofile=findfile('.viminfo','.;')
in order to
have vim create a .viminfo
file in whatever local directory you're in when you
set a mark. The .vim-info
file is where marks and file history is stored so
this seems pretty great. The big downside is that you'll now have this littered
all over your filesystem. You can setup a global git ignore and mostly
forget about it though.
The way this solution works you need to actually create the blank .viminfo
file in each "project". Not the end of the world, but I think it might be neat
if it was automatically created per .git
directory. Not a big deal though.
Perhaps I'll add a vim command to create a new "project".
Visualizing the marks
In vim by default I guess you're just meant to have a perfect memory of where every mark is located? That seems insane. There's a sign column which is perfect for this. I'm not sure if there's a plugin that only adds the sign column visualization for marks, but marks.nvim doesn't add much else so it seems kinda ideal. Plus you can disable the extra shit and it loads fast because of lua.
List (and jump to) all marks
The super popular telescope plugin has a builtin for listing marks (including
local, global, and default). This works basically perfectly. The only other
thing I'd like is being able to press [m
and ]m
to jump between marks
(global or local).
Delete and adding marks
The system of needing to assign a letter to each mark is quite in-ergonomic. I
shouldn't have to remember which letters I've already used either when assigning
or jumping to them. I think having letters be assigned is fine, good even,
because then you can be like "oh yea that was mark y" and then jump to it. I
think it would be a lot better if mm
deleted any marks on your current line
or, if there are none, created a mark with the next available letter. AFAIK
there's no plugin that does this at the moment. There should also be MM
which
does the same, but with global marks (or rather project specific per my above
note). Finally, there should be two binds for "delete all" perhaps dm
and
dM
. The first is per file and second is ALL (per project normally).
I also think I can add some binds for the telescope marks builtin to make "backspace" or something delete the selected mark.