Vim Tips Wiki

Modified undo behavior

1,624pages on
this wiki
Add New Page
Talk0 Share

Duplicate tip

This tip is very similar to the following:

These tips need to be merged – see the merge guidelines.

Tip 1054 Printable Monobook Previous Next

created 2005 · complexity intermediate · author Nigeria · version 6.0

I was getting frustrated with the default undo behavior in Vim because sometimes one of my "changes" would be very long (many lines), and I would want to undo one line at a time. So I came up with the idea to change the behavior with the following code that can be inserted into your vimrc:

function! EnterStuff()
  let theLine = getline(line("."))
  let pos = col("'^")
  execute "normal mqu\<C-r>`q"
  if(pos > len(theLine))
    if(pos > 1)
      normal l

function! ChangeUndoMode(theNum)
  if(a:theNum == 1)
    inoremap <C-w> <C-w>^O^[
    inoremap <CR> <Esc>:call EnterStuff()<CR><CR>
  elseif(a:theNum == 2)
    inoremap <C-w> <C-w>^O^[
    inoremap <BS> <BS>^O^[
    inoremap <DEL> <DEL>^O^[
    inoremap <CR> <Esc>:call EnterStuff()<CR><CR>
    iunmap <C-w>
    iunmap <BS>
    iunmap <DEL>
    iunmap <CR>
call ChangeUndoMode(1)
nmap \sun :call ChangeUndoMode(1)<CR>
nmap \gun :call ChangeUndoMode(2)<CR>
nmap \bun :call ChangeUndoMode(3)<CR>

Be sure to write "^O^[" as two characters: ctrl-o and ESC.

So the above code works fairly well. <C-w>, <BS>, <DEL>, <CR> all add to the undo list. The <CR> one took me a long time to figure out. The way it is done in the above code is the only way I know that doesn't mess up indentation. ^O^[ automatically screws up indentation.


You can use <c-g>u to break the undo chain:

inoremap <BS> <c-g>u<BS>
inoremap <CR> <c-g>u<CR>
inoremap <del> <c-g>u<del>
inoremap <c-w> <c-g>u<c-w>

should have the same effects.

One more thing you can do is hit <End> while typing a sentence to end the undo sequence. The only reason <C-g>u is needed in the above example is because it doesn't screw up auto-indentation. Normally though, hitting <End> is a great way to end the undo sequence.

My <End> does not break the undo chain. I had to explicitly imap it to do so:

inoremap <End> <C-g>u<End>

The <C-G>u trick seems not to be mentioned in gvim 6.1 docs and does not work either with this version.

Be careful: "<C-g>u<Space>" breaks abbreviations induced by a <Space>

Very odd. Try

:imap <Space> <Space><C-g>u

to make abbrevs work. Do not try

:imap <Space> <C-g>u<Space>

Vim will hang after using Space (use <C-c> to stop).

Ad blocker interference detected!

Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Also on Fandom

Random Wiki