Skip to content

rickhowe/difffilter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

difffilter

Selectively compare lines as you want in diff mode

Introduction

The standard "diff" command supports "--ignore-matching-lines=regexp (-I regexp)" option to ignore hunks if all the inserted and deleted lines match regexp. This plugin provides similar functionality but tries a line-level filtering based on regexp and other matching criteria.

For example, vim will show such differences for these 3 files:

sample1

This plugin gets vim to exclude comment lines so that you can focus on seeing the differences on the "return" statement.

sample2

As a default, this plugin highlights the diff excluded lines in hl-Conceal. To hide those concealed lines, use the conceallevel and concealcursor options. Additionally, like below, you can set the t:DiffFilterConceal or g:DiffFilterConceal variable and show their filler lines with an eob(~) character to align corresponding diff compared lines between windows. Disable if not necessary,

sample3

Use :diffupdate command to reevaluate and redraw diff lines when text or option is changed.

Filter Expression

Internally, this plugin sets a function to the diffexpr option in order to:

  • evaluate if each line should be diff compared or not
  • mark the to-be-excluded lines in the buffer contents
  • call a builtin diff function to compare them
  • modify diff hunks to get vim to ignore the excluded lines

In above example, the following lambda expression is used to exclude comment lines.

{lnum -> (&commentstring[:-2] == '%s') ?
  \getline(lnum) !~ '^\s*' . escape(&commentstring, '^$.*[]~\')[:-3] :
  \synIDtrans(synID(lnum, match(getline(lnum), '\S') + 1, 0)) !=
                                                    \hlID('Comment')}

That checks a comment string at the start of each line if the commentstring option indicates it possible. Otherwise, checks a comment syntax highlighting on each line. That is a default expression in this plugin, which can be commonly used for a comment line in a lot of filetypes.

You can specify another expression in the t:DiffFilterExpr tabpage local or g:DiffFilterExpr global variable, like below.

To use the last selected Visual area:

let g:DiffFilterExpr = {lnum -> line("'<") <= lnum && lnum <= line("'>")}

To compare lines not including a multibyte character:

let g:DiffFilterExpr = {lnum -> getline(lnum) !~ '[^\x00-\x7F]'}

To filter unfolded lines:

let g:DiffFilterExpr = {lnum -> foldlevel(lnum) == 0}

To select indented lines:

let g:DiffFilterExpr = {lnum -> 0 < indent(lnum)}

It is possible to specify a function which checks a comment block for a filetype like C and C++:

let g:DiffFilterExpr = function('MyDiffFilterExpr')
function MyDiffFilterExpr(lnum)
  let [c_line, c_start, c_end] = ['//', '/*', '*/']
  let [c_line, c_start, c_end] = map([c_line, c_start, c_end],
                        \{_, v -> '^\s*' . escape(v, '/*')})
  for c in [c_line, c_start, c_end]
    if getline(a:lnum) =~ c | return 1 | endif
  endfor
  let pos = [line('.'), col('.')]
  call cursor([a:lnum, 1])
  let sline = searchpair(c_start, '', c_end, 'nW')
  call cursor(pos)
  return (0 < sline) ? 1 : 0
endfunction

Options

  • t:DiffFilterExpr, g:DiffFilterExpr

    • A boolean expression to evaluate if a line should be diff compared or not (default: see above)
  • t:DiffFilterConceal, g:DiffFilterConceal

    • Highlight the diff excluded lines in hl-Conceal (1), plus show their filler lines (2), or disable them (0) (default: 1)
  • g:DiffFilter

    • Enable (1) or disable (0) this plugin (default: 1).

Requirements

This plugin requires a builtin diff function:

  • diff() and patch-9.1.0099 in vim 9.1
  • Lua vim.diff() in nvim 0.6.0

See also

There are other diff related plugins available:

  • diffchar.vim: Highlight the exact differences, based on characters and words
  • spotdiff.vim: A range and area selectable :diffthis to compare partially
  • wrapfiller: Align each wrapped line virtually between windows

Releases

No releases published

Packages

No packages published