NAME

sdif - side-by-side diff viewer for ANSI terminal

VERSION

Version 4.49

SYNOPSIS

  sdif file_1 file_2

  diff ... | sdif

OPTIONS:

  -i, --ignore-case
  -b, --ignore-space-change
  -w, --ignore-all-space
  -B, --ignore-blank-lines

  --[no]number, -n    print line number
  --digit=#           set the line number digits (default 4)
  --truncate, -t      truncate long line
  --boundary=#        line folding boundary (default word)
  --context, -c, -C#  context diff
  --unified, -u, -U#  unified diff

  --width=#, -W#      width of output (default 80)
  --margin=#          margin column number (default 0)
  --runin=#           run-in column number (default --margin)
  --runout=#          run-out column number (default --margin)
  --mark=position     mark position (right, left, center, side) or no
  --column=order      column order (default ONM)
  --view, -v          viewer mode
  --parallel[=#], -V  treat unknown text as common part (default 2)
  --ambiguous=s       ambiguous character width (detect, wide, narrow)
  --[no-]command      print diff control command (default on)
  --[no-]filename     print diff filename (default on)
  --[no-]prefix       process git --graph output (default on)
  --prefix-pattern    prefix pattern

  --color=when        'always' (default), 'never' or 'auto'
  --nocolor           --color=never
  --colormap, --cm    specify color map
  --colortable[=#]    show color table (optional #: 6, 12, 24)
  --[no-]256          on/off ANSI 256 color mode (default on)
  --[no-]cc           color command line  (default true)
  --[no-]fc                 file name     (default true)
  --[no-]lc                 line number   (default true)
  --[no-]mc                 diff mark     (default true)
  --[no-]tc                 normal text   (default true)
  --[no-]uc                 unknown text  (default true)

  --man               display manual page
  --version           show version
  --diff=s            set diff command
  --diffopts=s        set diff command options

  --[no-]lenience     suppress unexpected input warning (default on)
  --limit key=val     set limit (line, length)
  --visible xx=1      set visible chars
  --tabhead=char      set tabhead char
  --tabspace=char     set tabspace char
  --tabstyle=style    set tabstyle (dot, symbol, shade, bar, dash...)
  --tabstop=#         set tabstop width (default 8)

  --[no-]cdif         use ``cdif'' as word context diff backend
  --unit=s            pass through to cdif (word, letter, char, mecab)
  --cdifopts=s        set cdif command options

DESCRIPTION

sdif is inspired by the System V sdiff(1) command. Its basic job is to make a side-by-side listing of two different files. The whole of both files is listed, one on the left and one on the right. The center column shows how far the lines differ. No mark means no difference; added, deleted and modified lines are marked with a minus - or a plus +; a wrapped line is marked with a period ..

1 deleted  -
2 same          1 same
3 changed  -+   2 modified
  wrapped  ..     folded
4 same          3 same
            +   4 added

It also reads and formats the output of the diff command from standard input. Besides normal diff output, context diff -c and unified diff -u output are handled properly. Combined diff and conflict marker styles are supported too, though currently for no more than three files.

The current implementation also supports #ifdef and markdown custom container (using seven colons) formats on an experimental basis. This is to support the multilingual format generated by the App::Greple::xlate module.

To simply show several files side by side, without caring how they differ, use the App::ansicolumn command.

STARTUP and MODULE

sdif uses the Perl Getopt::EX module, and reads the ~/.sdifrc file at startup if there is one. You can define your own options and defaults there. To always show the line number, define it like this:

option default -n

Modules under App::sdif can be loaded by the -M option without the prefix. The next command loads the App::sdif::colors module.

$ sdif -Mcolors

Options can be defined in a module file as well. See Getopt::EX::Module for details.

COLOR

Each line is displayed in a different color by default; use the --no-color option to turn that off. Every text segment has its own label, and the color for each label can be set by the --colormap option. See Getopt::EX::Colormap for details.

The standard module -Mcolors is loaded by default, and defines several color maps for light and dark screens. To use CMY colors on a dark screen, place the next line in your ~/.sdifrc.

option default --dark-cmy

Option --autocolor is defined in the default module to call the Getopt::EX::termcolor module. It sets the --light or --dark option according to the brightness of the terminal screen. You can set your preferred colors in ~/.sdifrc like this:

option --light --cmy
option --dark  --dark-cmy

The detection is done by the Getopt::EX::termcolor module, and works with macOS Terminal.app and iTerm.app, and other XTerm compatible terminals. That module reads the environment variable TERM_BGCOLOR as the terminal background color, in the form #FFFFFF.

Option --autocolor is set by default; to disable it, override it with something that does nothing.

option --autocolor --nop

WORD DIFFERENCE

sdif itself does not care what is inside a modified line, but it can read the output of the cdif command, which shows the word context differences within each line. Invoke cdif with the --sdif option to set everything appropriately for sdif. When invoking cdif by hand, set --no-cc and --no-mc at the very least; --no-tc is preferable as well, since sdif can handle the text color itself.

Since version 4.1.0 option --cdif is set by default, so use --no-cdif to disable it. Option --unit (default word) is passed through to cdif. Other cdif options can be given with --cdifopts.

EXIT STATUS

sdif always exits with status zero unless an error occurs.

OPTIONS

--width=width, -W width

Set the width of the output listing. The default is 80. If standard error is connected to a terminal, the width is taken from it when possible.

--margin=column
--runin=column
--runout=column

Set the number of margin columns, left blank at the end of each line. This option implicitly turns on line break control, which lets prohibited characters run in and run out at the beginning and the end of a line. The margin is used for the run-in and run-out columns unless those are given explicitly. See Text::ANSI::Fold for details.

-n, --[no-]number

Print line number on each line. Default false.

--[no-]command

Print diff command control lines. Default true.

--[no-]filename

Print filename lines. Default true.

--digit=n

Line number is displayed in 4 digits by default. Use this option to change it.

-i, --ignore-case
-b, --ignore-space-change
-w, --ignore-all-space
-B, --ignore-blank-lines
-c, --context=n, -Cn
-u, --unified=n, -Un

Passed through to the back-end diff command. sdif can interpret the output of normal, context (diff -c) and unified (diff -u) diff.

-t, --[no-]truncate

Truncate lines if they are longer than printing width. Default false.

--boundary=[none,word,space]

Set the text wrap boundary. Set to word or space, text is not wrapped in the middle of an alphanumeric word or a non-space sequence. See Text::ANSI::Fold for details. Default is word.

--onword

Shortcut for --boundary=word. Its use is no longer recommended. Default true.

--[no-]cdif[=command]

Use the cdif command instead of the normal diff command. Enabled by default; use --no-cdif to turn it off explicitly. The option takes an optional parameter naming the cdif command to run.

--cdifopts=option

Specify options for back-end cdif command.

--unit=[word,letter,char,mecab]
--by=[word,letter,char,mecab]
--mecab

These options are simply passed on to the back-end cdif command. Choose a value from word (default), letter, char or mecab. Option --by is an alias for --unit, and --mecab is a shortcut for --unit=mecab. See the cdif manual for details.

Use --cdifopts to set other options.

--diff=command

Any command can be named as the diff command to use. Unless you need the whole text, piping the output into sdif is easier.

--diffopts=option

Specify options for back-end diff command.

--mark=position

Specify the position for a mark. Choose from left, right, center, side or no. Default is center.

--column=order

Specify the order of the columns with O (1: old), N (2: new) and M (3: merged). The default order is ONM, or 123. To show the new file on the left and the old file on the right:

$ sdif --column NO

The next example puts the merged file in the leftmost column for diff3 data.

$ sdif --column MON

The next two commands produce the same output.

$ git diff v1 v2 v3 | sdif --column 312

$ git diff v3 v1 v2 | sdif
--[no-]color

Use ANSI color escape sequences in the output. Default is true.

--[no-]256

Use ANSI 256 color mode. Default is true.

--colortable[=6,12,24]

Without a parameter, show a table of the 216 ANSI colors.

Given a parameter, display a 6x6, 12x12 or 24x24 color matrix respectively.

-v, --view

Viewer mode. Display each file in straightforward order. Without this option, unchanged lines are placed at the same position.

-V, --parallel
-V3, --parallel=3

sdif processes only what looks like diff output, and prints everything else to standard output as is. Option -V or --parallel makes it treat unknown text as common to the old and the new data. This is useful for reading a file that contains git(1)-compatible conflict markers.

The option takes an optional number, and 2 is assumed when it is omitted; the only other effective value is 3. The diff3(1) command can produce conflict marker style output with its -m option, so you can use it like this:

$ diff3 -m A B C | sdif -V3
--ambiguous=width_spec

Specify how to treat Unicode ambiguous width characters. The default is narrow.

detect or auto

Detect from the user's locale, choosing wide in a CJK environment.

wide or full

Treat ambiguous characters as wide.

narrow or half

Treat ambiguous characters as narrow.

--[no-]prefix

Understand a prefix in front of the diff output, such as the one git --graph produces. True by default.

--prefix-pattern=pattern

Specify the prefix pattern as a regular expression. Default pattern is:

(?:\| )*(?:  )?

This pattern matches git graph style and whitespace indented diff output.

--[no-]lenience

Suppress the warning message for unexpected input from the diff command. True by default.

--limit key=value

Set resource limits. Available keys are:

line=#

Limit the number of lines displayed for add/delete sections. When a diff section contains only additions or only deletions and the number of lines exceeds this value, only the first # lines are shown and the rest are omitted with a message indicating the number of omitted lines. This is useful for suppressing long diffs caused by large file additions or deletions, for example when browsing git log -p output.

length=#

Truncate lines longer than # characters before display processing. Default is 10000. Extremely long lines, such as SVG data with embedded base64 images, can make display processing very slow. Set to 0 to disable this limit.

--visible charname=[0,1]
--tabhead=char
--tabspace=char

Visualize characters. Currently only ht (horizontal tab) is supported. Each horizontal tab is converted to a tabhead character followed by tabspace characters, both of which can be set by the --tabhead and --tabspace options.

$ sdif --visible ht=1 --tabhead=T --tabspace=.

An option value longer than a single character is taken as a Unicode character name.

$ sdif --visible ht=1 \
       --tabhead="MEDIUM SHADE" \
       --tabspace="LIGHT SHADE"

See https://www.unicode.org/charts/charindex.html for Unicode names.

cdif makes non-space control characters visible by default. See "--visible" in cdif.

--tabstyle=[space,dot,symbol,shade,bar,dash...]
--ts=...

Option --tabstyle (or --ts) sets the --tabhead and --tabspace characters at once, according to the given style name. Select from space, dot, symbol, shade, bar, dash and others. See "tabstyle" in Text::ANSI::Fold for the available styles.

Two styles can be combined, as in symbol,space. In that case tabhead is taken from the symbol style and tabspace from space.

Setting a tabstyle implies making ht visible. To set a tabstyle by default without making tabs visible all the time, disable it explicitly.

option default --tabstyle=symbol,space --visible ht=0

You can then enable it when you run the command.

$ sdif --visible ht=1
--tabstop=n

Specify tab stop. Default is 8.

--colormap=colormap, --cm=colormap

Basic colormap format is :

FIELD=COLOR

where the FIELD is one from these :

OLD       NEW       MERGED    UNCHANGED
--------- --------- --------- ---------
OCOMMAND  NCOMMAND  MCOMMAND           : Command line
OFILE     NFILE     MFILE              : File name
OMARK     NMARK     MMARK     UMARK    : Mark
OLINE     NLINE     MLINE     ULINE    : Line number
OTEXT     NTEXT     MTEXT     UTEXT    : Text

If UMARK and/or ULINE is empty, OMARK/NMARK and/or OLINE/NLINE are used instead.

You can give several fields the same color by joining them with = :

FIELD1=FIELD2=...=COLOR

A wildcard can also be used for the field name :

*CHANGE=BDw

Multiple fields can be specified by repeating the option :

--cm FIELD1=COLOR1 --cm FIELD2=COLOR2 ...

or combined with comma (,) :

--cm FIELD1=COLOR1,FIELD2=COLOR2, ...

Color specification is a combination of single uppercase character representing 8 colors :

R  Red
G  Green
B  Blue
C  Cyan
M  Magenta
Y  Yellow
K  Black
W  White

and alternative (usually brighter) colors in lowercase :

r, g, b, c, m, y, k, w

or RGB values and 24 grey levels on an ANSI 256-color or full-color terminal :

(255,255,255)      : 24bit decimal RGB colors
#000000 .. #FFFFFF : 24bit hex RGB colors
#000    .. #FFF    : 12bit hex RGB 4096 colors
000 .. 555         : 6x6x6 RGB 216 colors
L00 .. L25         : Black (L00), 24 grey levels, White (L25)

or color names enclosed in angle brackets :

<red> <blue> <green> <cyan> <magenta> <yellow>
<aliceblue> <honeydew> <hotpink> <moccasin>
<medium_aqua_marine>

with other special effects :

D  Double-struck (boldface)
I  Italic
U  Underline
S  Stand-out (reverse video)

The above is a simplified summary; see Getopt::EX::Colormap for the complete specification.

Defaults are :

OCOMMAND => "555/010"  or "GS"
NCOMMAND => "555/010"  or "GS"
MCOMMAND => "555/010"  or "GS"
OFILE    => "551/010D" or "GDS"
NFILE    => "551/010D" or "GDS"
MFILE    => "551/010D" or "GDS"
OMARK    => "010/444"  or "G/W"
NMARK    => "010/444"  or "G/W"
MMARK    => "010/444"  or "G/W"
UMARK    => ""
OLINE    => "220"      or "Y"
NLINE    => "220"      or "Y"
MLINE    => "220"      or "Y"
ULINE    => ""
OTEXT    => "K/454"    or "G"
NTEXT    => "K/454"    or "G"
MTEXT    => "K/454"    or "G"
UTEXT    => ""

This is equivalent to :

sdif --cm '?COMMAND=555/010,?FILE=555/010D' \
     --cm '?MARK=010/444,UMARK=' \
     --cm '?LINE=220,ULINE=' \
     --cm '?TEXT=K/454,UTEXT='
--colormap=&func
--colormap=sub{...}

You can also give the name of a Perl subroutine, or its definition, to be called for the matched words. The target word is passed in the variable $_, and the return value of the subroutine is displayed.

See "FUNCTION SPEC" in Getopt::EX::Colormap for details.

--[no-]cc, --[no-]commandcolor
--[no-]fc, --[no-]filecolor
--[no-]lc, --[no-]linecolor
--[no-]mc, --[no-]markcolor
--[no-]tc, --[no-]textcolor
--[no-]uc, --[no-]unknowncolor

Enable or disable color for the corresponding field.

MODULE OPTIONS

default

default      --autocolor
--nop        do nothing

-Mcolors

The following options are available by default. Run perldoc -m App::sdif::colors to see the actual settings.

--light
--green
--cmy
--mono

--dark
--dark-green
--dark-cmy
--dark-mono

GIT

See "GIT" in App::sdif for how to use the sdif family under GIT.

ENVIRONMENT

SDIFOPTS

Environment variable SDIFOPTS is used to set default options.

LESS
LESSANSIENDCHARS

Since sdif emits the ANSI Erase Line terminal sequence, it helps to let the less command know about it.

LESS=-cR
LESSANSIENDCHARS=mK

AUTHOR

Kazumasa Utashiro
https://github.com/kaz-utashiro/sdif-tools

LICENSE

Copyright 1992-2026 Kazumasa Utashiro

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO

cdif(1), watchdiff(1)

Getopt::EX::Colormap

Getopt::EX::termcolor

App::sdif::colors

https://taku910.github.io/mecab/

App::ansicolumn

App::Greple::xlate