How do I run a substitution without displacing my marks?
Answer
:keepmarks %s/pattern/replacement/g
Explanation
The :keepmarks modifier prevents Vim from adjusting mark positions when a buffer-modifying command runs. Normally, a global substitution shifts marks on affected lines to account for inserted or deleted characters. Prefixing the command with :keepmarks freezes all marks at their original positions regardless of what the substitution changes.
How it works
:keepmarksis a command modifier that applies to the Ex command that follows it- Without it, a substitution that changes line lengths will update mark column positions to keep them on the same character
- With it, every mark (
'a,'b,`[,`], etc.) stays at its exact line and column from before the command ran - This is especially valuable inside scripts, functions, or complex macros where you set marks, transform the buffer, and need marks to remain at the pre-change positions
Example
Set mark a on a line, run a substitution, then check if the mark moved:
" Without keepmarks: mark adjusts with text changes
:%s/short/a much longer replacement/g
" 'a may now point to a different column
" With keepmarks: mark stays put
:keepmarks %s/short/a much longer replacement/g
" 'a still points to the original position
Tips
- Combine with
:keepjumpsto also preserve the jump list::keepjumps keepmarks %s/.../.../g - Commonly used in plugin code and autoload functions that reformat buffers
:help :keepmarksfor the full specification