5

I have the following mappings:

nnoremap # /___<CR>ciw
imap # <Esc>:w<CR><Esc>#

And the following file that I am editing:

foo ___
goo ___
hoo ___

The idea is that I start at the beginning of the file, type # and I am editing the first ___, then while still in insert mode, I type # again, and I am editing the next ___, saving between each edit. This works fine, but the problem is that if I make a mistake, and type u, it undoes ALL the edits and reverts ALL of them back to ___ instead of just the most recent change.

How can I do these mappings in a way so that each time I save, it counts as a separate undo?

2 Answers 2

8

You can use <c-g>u in insert mode to break undo sequence and start new change. Like this:

imap # <c-g>u<Esc>:w<CR>#

(removed the second <esc>, as it is not needed.)

See :help i_CTRL-G_u

3

From :h undojoin:

One undo command normally undoes a typed command, no matter how many changes
that command makes.  This sequence of undo-able changes forms an undo block.
[...]
To do the opposite, break a change into two undo blocks, in Insert mode use
CTRL-G u.  This is useful if you want an insert command to be undoable in
parts.  E.g., for each sentence.  i_CTRL-G_u
Setting the value of 'undolevels' also breaks undo.  Even when the new value
is equal to the old value.

So, you could modify your second mapping to break the undo block (before the write):

imap # <C-G>u<Esc>:w<CR><Esc>#

Or the fist mapping to start a new block with input:

nnoremap # /___<CR>ciw<c-g>u
2
  • Looks like your answer was first, but you were missing the u at the end of <C-G>. Thank you for the response though! Jun 7, 2019 at 8:52
  • Oh, missed that.
    – muru
    Jun 7, 2019 at 8:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.