Home

Awesome

diffchar.vim

Highlight the exact differences, based on characters and words

 ____   _  ____  ____  _____  _   _  _____  ____   
|    | | ||    ||    ||     || | | ||  _  ||  _ |  
|  _  || ||  __||  __||     || | | || | | || | ||  
| | | || || |__ | |__ |   __|| |_| || |_| || |_||_ 
| |_| || ||  __||  __||  |   |     ||     ||  __  |
|     || || |   | |   |  |__ |  _  ||  _  || |  | |
|____| |_||_|   |_|   |_____||_| |_||_| |_||_|  |_|

This plugin has been developed in order to make diff mode more useful. Vim highlights all the text in between the first and last different characters on a changed line. But this plugin will find the exact differences between them, character by character - so called DiffChar.

For example, in diff mode: example1

This plugin will exactly show the changed and added units: example2

Sync with diff mode

This plugin will synchronously show/reset the highlights of the exact differences as soon as the diff mode begins/ends. And the exact differences will be kept updated while editing.

Diff unit

This plugin shows the diffs based on a g:DiffUnit. Its default is 'Word1' and it handles a \w\+ word and a \W character as a diff unit. There are other types of word provided and you can also set 'Char' to compare character by character. In addition, you can specify one or more diff unit delimiters, such as comma (','), colon (':'), tab ("\t"), and HTML tag symbols ('<' and '>'), and also specify a custom pattern in the g:DiffUnit.

Diff matching colors

In diff mode, the corresponding hl-DiffChange lines are compared between two windows. As a default, all the changed units are highlighted with hl-DiffText. You can set g:DiffColors to use more than one matching color to make it easy to find the corresponding units between two windows. The number of colors depends on the color scheme. In addition, hl-DiffAdd is always used for the added units and both the previous and next character of the deleted units are shown in bold/underline.

Diff pair visible

While showing the exact differences, when the cursor is moved on a diff unit, you can see its corresponding unit highlighted with hl-Cursor, hl-TermCursor, or similar one in another window, based on a g:DiffPairVisible. If you change its default, the corresponding unit is echoed in the command line or displayed in a popup/floating window just below the cursor position or at the mouse position. Those options take effect on :diffupdate command as well.

Jump to next/prev diff unit

You can use ]b or ]e to jump cursor to start or end position of the next diff unit, and [b or [e to the start or end position of the previous unit.

Get/put a diff unit

Like line-based :diffget/:diffput and do/dp vim commands, you can use <Leader>g and <Leader>p commands in normal mode to get and put each diff unit, where the cursor is on, between 2 buffers and undo its difference. Those keymaps are configurable in your vimrc and so on.

Check diff lines locally

When the diff mode begins, this plugin locally checks the hl-DiffChange lines in the limited range of the current visible and its upper/lower lines of a window. And each time a cursor is moved on to another range upon scrolling or searching, those diff lines will be checked in that range. Which means, independently of the file size, the number of lines to be checked and then the time consumed are always constant.

Tab page individual

This plugin works on each tab page individually. You can use a tab page variable (t:), instead of a global one (g:), to specify different options on each tab page. Note that this plugin can not handle more than two diff mode windows in a tab page. If it would happen, to prevent any trouble, all the highlighted units are to be reset in the tab page.

Follow 'diffopt' option

This plugin supports icase, iwhite, iwhiteall, and iwhiteeol in the diffopt option. In addition, when indent-heuristic is specified, positioning of the added/deleted diff units is adjusted to reduce the number of diff hunks and make them easier to read.

Comparison algorithm

To find the exact differences, this plugin uses "An O(NP) Sequence Comparison Algorithm" developed by S.Wu, et al., which always finds an optimum sequence. But it takes time to check a long and dissimilar line. To improve the performance, the algorithm is also implemented in Vim9 script. In addition, if available, this plugin uses a builtin diff function (diff() in vim patch-9.1.0071 and Lua vim.diff() in nvim 0.6.0) and makes it much faster.

See also

For a range and area selectable partial comparison, see spotdiff.vim plugin.

Options

Keymaps

MappingDefault KeyDescription
<Plug>JumpDiffCharPrevStart[bJump cursor to the start position of the previous diff unit
<Plug>JumpDiffCharNextStart]bJump cursor to the start position of the next diff unit
<Plug>JumpDiffCharPrevEnd[eJump cursor to the end position of the previous diff unit
<Plug>JumpDiffCharNextEnd]eJump cursor to the end position of the next diff unit
<Plug>GetDiffCharPair<Leader>gGet a corresponding diff unit from another buffer to undo difference
<Plug>PutDiffCharPair<Leader>pPut a corresponding diff unit to another buffer to undo difference

Demo

demo