How to highlight all previously deleted text after an undelete
I often use a command or script to delete text and after I do an undelete (u) I want to see what has been previously deleted by the command/scri开发者_运维知识库pt.
Is it possible to highlight the previous deleted text when use the undelete command? (or even better match the previous deleted text in a find "/" command)
If you just deleted some text using d
, you can use /<CTRL-R>"
to match the text you just deleted (even if you just undid the delete with u
).
This won't work if the deleted text contains newlines or regex meta-characters (like \
or [
). If that's likely, try:
/\V<CTRL-R>=substitute(substitute(getreg('"'), "[\\/]", '\\\0', 'g'), "\n", '\\n', "g")
\V
- very nomagic - turns off most regex meta-characters<CTRL-R>=
- insert the evaluation of a vim expressionsubstitute(..., "\n", '\\n', "g")
- escape all the newlines in the given stringsubstitute(..., "[\\/]", '\\\0', 'g')
- escape all slashes and backslashes in the given stringgetreg('"')
- get the contents of the"
register, which contains the most recently yanked and/or deleted text
This is a bit wordy, so if you find yourself needing to do it often, you can bind it to a command in your ~/.vimrc
:
" use ,/ in normal mode to match the most recently deleted or yanked text
nmap ,/ /\V<C-R>=substitute(substitute(getreg('"'), "[\\/]", '\\\0', 'g'), "\n", '\\n', "g")<CR><CR><CR>
How about taking the diff from of one state of the file and compare to another?
:command! -nargs=0 DiffLastChange exe "norm! u" | vert new | set bt=nofile | r # | 0d _ | diffthis | wincmd p | exe "norm! \<c-r>" | diffthis
Now you can just run DiffLastChange
to see a diff of the last change to the file.
Explanation:
exe "norm! u"
undo the last change in the current buffervert new
vertically split a new bufferset bt=nofile
change the buffer type to a scratch bufferr #
read the contents from the alternate file i.e. the buffer we started out with0d _
clean up the new buffer by removing the blank line at the top into the black hole registerdiffthis
mark the current buffer to be a part of the diffwincmd p
switch to the last buffer (back to the buffer we started out with)exe "norm! \<c-r>"
execute a redo to restore the original buffers statediffthis
mark the original buffer to be apart of the diff
After you are done I recommend executing :diffoff!
to turn off both diffs.
Regrettably this command in its present state can not handle unsaved buffers as :read #
will read in a file. The solution is to copy the contents of the buffer into a named register and then paste it into the scratch buffer. Sadly this will clobber a named register. Refactorting the code out into a function will give more flexibility and allow the use of a variable to save the contents of the register (and register type) and restore the register at the end.
function! DiffLastChange(...)
let a = @a
let at = getregtype('a')
let c = a:0 == 1 ? a:1 : 1
let ft = &ft
try
exe "norm! " . c . "u"
sil %y a
vert new
set bt=nofile
exe "set ft=" . ft
sil pu a
0d _
diffthis
wincmd p
exe "norm! " . c . "\<c-r>"
diffthis
finally
call setreg('a', a, at)
endtry
endfunction
command! -nargs=? DiffLastChange call DiffLastChange(<f-args>)
In addition to fixing the unsaved buffer problems and clobbering issues, I have added the ability to go further back in history via a command argument e.g. :DiffLastChange 3
. The command also sets the scratch buffer's filetype to the same as the original buffers so syntax highlighting will be turned on for that buffer.
For a much more robust solution for seeing the differences between parts of history in a buffer I agree with Christian Brabandt and suggest Gundo or histwin. For more information on Gundo, see this vimcasts.
For more help see:
:h diffthis
:h diffoff
:h wincmd
:h 'bt'
:h :r
:h :d
Try the histwin or Gundo plugin. It lets you diff all undo branches and shows also shows a unified diff for the differences in the preview window.
精彩评论