Switching between files in Vim without fuzzy-finding everything
Source: Dev.to
Fast Navigation in Vim/Neovim
Most of the time, fuzzy‑finding isn’t what you need. You already know which file you want — you were just there. The real problem is getting back to it quickly.
Below is a progression from the fastest built‑ins to a full fuzzy picker, ordered by how much setup each requires.
1. “ – Toggle the file you were just in
Best for: jumping between exactly two files (e.g., auth.go ↔ auth_test.go).
- Switches to the alternate file, i.e. the last buffer you had open.
- No filename to type, no fuzzy search, no menu – just one keystroke back where you were.
- Example: you jump to a test file with
gd, read the implementation, then press “ to land back in the original file, cursor exactly where you left it.
Limitation: only remembers one previous file. Opening a third buffer discards the older entry. For two‑file back‑and‑forth it’s unbeatable; for broader navigation you’ll need something else.
2. Global marks – mA, 'A – Pin files you return to constantly
Best for: 2‑3 files you keep revisiting during a session (e.g., config, main_handler, test).
" Set a global mark (uppercase = global, persists across files)
mA
" Jump to it from anywhere
'A
- Uppercase marks (
mA…mZ) are global: they remember both the file and the line number. - Press
'Afrom any buffer to jump directly to that exact line. - Example: while working on a feature you frequently need
routes.go. PressmRonce on the relevant line; later'Rgets you there instantly.
Persistence: global marks survive Vim sessions (saved in ~/.viminfo or ~/.local/share/nvim/shada/main.shada). Stale marks can accumulate, so clean them occasionally:
:delmarks A-Z
3. / – Retrace your navigation history
Best for: walking back through a chain of jumps (e.g., gd → gd → search).
" jump back (older position in jump list)
" jump forward (newer position)
- Vim maintains a jump list – a history of every position you jumped to via
gd,gg,/pattern,'mark, etc. - “ steps backward through that list, crossing file boundaries (like a browser back button).
- “ moves forward again.
Tip: use :jumps to view the full list and see where you’ll land.
Caveat: the jump list records positions, not intent. If you’ve been jumping a lot, “ may step through many intermediate stops before reaching the desired spot.
4. Built‑in buffer commands – :b, ]b / [b, :ls
Best for: quick switching when you know part of a filename.
:ls " list all open buffers with numbers and names
:b partial " switch to buffer by partial filename match
:b 3 " switch to buffer number 3
]b " next buffer (requires vim‑unimpaired or a mapping)
[b " previous buffer
:btab‑completes buffer names, so:b authjumps toauth.gowithout typing the full name.:lsgives a quick overview when you’re unsure which buffers are open.]b/[bare handy for cycling through a small set of buffers sequentially (you can map them yourself if you don’t have vim‑unimpaired).
Note: :b partial matches against the full path, not just the filename, so two files with similar paths may cause ambiguous completions. Use :ls first to check buffer numbers if needed.
5. MRU buffer picker – wildmode=lastused + wildcharm
Best for: a no‑plugin “most‑recently‑used” buffer selector.
" In your vimrc/init.vim
set wildmenu
set wildmode=lastused
set wildcharm=
" Optional mapping
nnoremap b :b
wildmode=lastusedreorders buffer completions so the most recently used buffers appear first.wildcharm=tells Vim which key triggers wildmenu expansion inside mappings (Tab doesn’t work in mappings by default).- Press
band the wildmenu shows the last file you edited; hit “ again for the one before that.
Compatibility: lastused is available in Vim 9.1+ and modern Neovim. Older Vim versions lack it – check :help 'wildmode' for availability.
6. Harpoon (Neovim only) – Persistent, project‑aware slots
Best for: a curated list of 4‑6 files you work with throughout the day, surviving restarts.
" Add current file to Harpoon list
:lua require('harpoon.mark').add_file()
" Open the Harpoon quick‑menu
:lua require('harpoon.ui').toggle_quick_menu()
" Jump directly to slot 1‑4
1 2 3 4
- Global marks give you 26 slots tied to specific line numbers, but Harpoon provides a small, numbered list that stays the same across sessions.
- The list is project‑aware (scoped to the Git root), so each project gets its own set of slots.
- Example workflow: at the start of the day, add
handler.go,service.go,service_test.go, andschema.sqlto Harpoon. Throughout the day,1‑4jump to those files instantly, regardless of how many other buffers you open.
Requirements: Neovim with Lua configuration. Harpoon does not work in Vim.
Summary Table
| Feature | When to Use | Setup Required |
|---|---|---|
| “ | Toggle between two files | None |
Global marks (mA/'A) | Jump to a few specific files/lines | None (optional cleanup) |
/ | Walk back/forward through jump history | None |
:b, ]b/[b, :ls | Switch by partial name or buffer number | None |
wildmode=lastused + wildcharm | Fast MRU picker without plugins | set commands + optional mapping |
| Harpoon | Persistent, project‑wide slot list (4‑6 files) | Neovim + Lua plugin |
Pick the method that matches your workflow: start with the built‑ins (“ , marks, jump list), then graduate to MRU completion, and finally to a dedicated plugin like Harpoon when you need a stable, cross‑session shortlist of files. Happy navigating!
Fuzzy Search Over the Pinned Files – Telescope Integration
:Telescope buffers — fuzzy search over all open buffers
:Telescope buffers
Recommended binding
nnoremap fb Telescope buffers
The Telescope buffer picker shows all open buffers with their numbers and modification state ([+] for unsaved changes).
- Filter in real time – type any substring.
- Delete a buffer – press “ while the picker is open (removes the buffer from the list without leaving the picker). This is handy for trimming stale buffers during a long session.
Example
You’ve been working for three hours and have 15 buffers open. You need to get back to a migration file but can’t remember the exact name. Typemigrin the picker and it narrows immediately to the one you want.
Vim (non‑Neovim) alternative
If you’re on vanilla Vim, fzf.vim’s :Buffers command provides essentially the same picker. Neither requires you to know buffer numbers—just type enough of the name and pick.
Workflow tips
These techniques stack:
- “ – switch to the last file.
'A/'B– jump to pinned files you visit constantly.- “ – retrace after diving into definitions.
b– quick MRU‑ordered list when you have a few buffers open.:Telescope buffers– search across many buffers.
The sweet spot for most people is “ + global marks + wildmode=lastused — zero plugins, huge improvement over the default behavior.
Further reading: Full explanations are available on vimtricks.wiki.
Question: What file‑switching workflow are you currently using that still feels clunky?