= Highlighters

== Description

Manipulation of the displayed text is done through highlighters, which can
be added or removed with the following commands:

-----------------------------------------------------------------
add-highlighter [-override] <path>/<name> <type> <parameters> ...
-----------------------------------------------------------------

and

--------------------------------
remove-highlighter <path>/<name>
--------------------------------

*path* is the name of a highlighter group, it is expressed as a */*
separated path starting with a scope. Scopes are *global*, *buffer*,
*window* and *shared*

*name* is the name of the highlighter, if name is omitted in
`add-highlighter` (the path ends with a `/`), it will be auto-generated
from the remaining parameters.

if `-override` is specified and the given name already exists, that
highlighter is replaced with the new one.

== Convenient highlighters

*show-matching*::
    highlight matching char of the character under the selections' cursor
    using `MatchingChar` face, with the following *options*:

    *-previous*:::
        fall back to the character before the cursor when the cursor is not
        over a matching char

*show-whitespaces* [options]::
    display symbols on top of whitespaces to make them more explicit
    using the `Whitespace` face, with the following *options*:

    *-lf* <separator>:::
        a one character long separator that will replace line feeds,
        or an empty string to ignore them.

    *-spc* <separator>:::
        a one character long separator that will replace spaces,
        or an empty string to ignore them.

    *-nbsp* <separator>:::
        a one character long separator that will replace non-breakable spaces,
        or an empty string to ignore them.

    *-tab* <separator>:::
        a one character long separator that will replace tabulations,
        or an empty string to ignore them.

    *-tabpad* <separator>:::
        a one character long separator that will be appended to tabulations to honor the *tabstop* option

    *-indent* <separator>:::
        a one character long separator that will replace the first space in indentation 
        according to the *indentwidth* option, or an empty string to ignore them.
        This will use the `WhitespaceIndent` face.

    *-only-trailing*:::
        only highlight whitespaces at the end of the line

*number-lines* [options]::
    show line numbers using the `LineNumbers`, `LineNumberCursor` and `LineNumbersWrapped` faces,
    with the following *options*: 

    *-relative*:::
        show line numbers relative to the main cursor line

    *-full-relative*:::
        same as relative but show main cursor line as 0

    *-hlcursor*:::
        highlight the cursor line with a separate face

    *-separator* <separator text>:::
        specify a string to separate the line numbers column from
        the rest of the buffer (default is '|')

    *-cursor-separator* <separator text>:::
        identical to *-separator* but applies only to the line of the cursor
        (default is the same value passed to *-separator*)

    *-min-digits* <num>:::
        always reserve room for at least *num* digits,
        so text doesn't jump around as lines are added or removed
        (default is 2)

*wrap* [options]::
    soft wrap buffer text at window width, with the following *options*:

    *-word*:::
        wrap at word boundaries instead of codepoint boundaries.

    *-indent*:::
        preserve line indent when wrapping.

    *-width <max_width>*:::
        wrap text at *max_width* if the window is wider.

    *-marker <marker_text>*:::
        prefix wrapped lines with *marker_text*; if *-indent* was given,
        the marker_text is displayed into the indentation if possible.

== General highlighters

*fill* <face>::
    fill using the given *face*, mostly useful with regions highlighters

*column* <number> <face> [options]::
    highlight column *number* with face *face*, with the following *options*:

    *-ruler* <character>:::
        a single character to display instead of empty or whitespace cells at
        column *number*. If this option is provided, *face* will also not
        apply to non-empty cells, and will only apply to *character*.

*line* <number> <face>::
    highlight line *number* with face *face*

*regex* <regex> <capture_id>:<face> ...::
    highlight a regex, takes the regex as first parameter, followed by
    any number of face parameters.
    This highlights C++ style comments in cyan, with an eventual 'TODO:'
    in yellow on red background:

--------------------------------------------------------------------
add-highlighter window/ regex //\h*(TODO:)[^\n]* 0:cyan 1:yellow,red
--------------------------------------------------------------------

    capture_id can be either the capture number, or its name if a
    named capture is used in the regex (See
    <<regex#groups, `:doc regex groups`>>)

*dynregex* <expression> <capture_id>:<face> ...::
    similar to regex, but expand (like a command parameter would) the
    given expression before building a regex from the result.
    This highlights all the current search matches in italic:

-----------------------------------------------
add-highlighter window/ dynregex '%reg{/}' 0:+i
-----------------------------------------------

== Specs highlighters

The following highlighters are useful to add indicators like lint warnings,
git blame output or spelling mistakes.
See <<options#types,`:doc options types`>> for the format of `line-specs`
and `range-specs`.

*flag-lines* <face> <option_name>::
    add columns in front of the buffer, and display the flags specified
    in `line-specs` option, using <face>.
    In this example two words will be added in the gutter: a blue Foo at
    line 1 and a bold red/yellow Bar on line 3:

------------------------------------------------------------------------
declare-option line-specs my_flags
set-option window my_flags %val{timestamp} '1|Foo' '3|{red,yellow+b}Bar'
add-highlighter window/ flag-lines blue my_flags
------------------------------------------------------------------------

*ranges* <option_name>::
    use the data in the `range-specs` option of the given name to highlight
    the buffer. The string part of each tuple of the range-specs is
    interpreted as a *face* to apply to the range.
    In this example the 3 first chars of the buffer will be colored in red:

--------------------------------------------------------
declare-option range-specs my_range
set-option window my_range %val{timestamp} '1.1,1.3|red'
add-highlighter window/ ranges my_range
--------------------------------------------------------

*replace-ranges* <option_name>::
    use the data in the `range-specs` option of the given name to highlight
    the buffer. The string part of each tuple of the range-specs is
    interpreted as markup string (see <<faces#markup-strings,
    `:doc faces markup-strings`>>) and displayed in place of the range.
    Here, the 3 first chars of the buffer will be replaced by the word 'red':

--------------------------------------------------------
declare-option range-specs my_range
set-option window my_range %val{timestamp} '1.1,1.3|red'
add-highlighter window/ replace-ranges my_range
--------------------------------------------------------

== Highlighting Groups

The *group* highlighter is a container for other highlighters. A subgroup
can be added to an existing group or scope using:

-----------------------------------
add-highlighter <path>/<name> group 
-----------------------------------

Other highlighters can then be added to that group

------------------------------------------------
add-highlighter <path>/<name> <type> <params>...
------------------------------------------------

In order to specify which kinds of highlighters can be added to a
given group, the *-passes* flag set can be passed along with the group
name. Possible values for this option can be one or several (separated
with a pipe sign) of *colorize*, *move* or *wrap* (default: *colorize*):

--------------------------------------------------------------
add-highlighter window/<name> group -passes colorize|move|wrap
--------------------------------------------------------------

== Regions highlighters

A special highlighter provides a way to segment the buffer into regions,
which are to be highlighted differently.

-------------------------------------
add-highlighter <path>/<name> regions
-------------------------------------

Individual region definitions can then be added to that highlighter

----------------------------------------------------
add-highlighter <path>/<name>/<region_name> region \
    [-match-capture] [-recurse <recurse>]          \
    <opening> <closing> <type> <params>...
----------------------------------------------------

*opening*::
    regex that defines the region start text

*closing*::
    regex that defines the region end text

*recurse*::
    regex that defines the text that matches recursively an end token
    into the region, every match of *recurse* will consume a following
    match of *closing* regex, preventing it from closing the region.

*type* and *params*::
    A highlighter type, and associated params, as they would be passed
    to `add-highlighter` if they were not applied as a region.

If the *-match-capture* switch is passed, then region *closing* and *recurse*
regex matches are considered valid for a given region opening match only if they
matched the same content for the capture 1 in the *opening* regex.

The *recurse* option is useful for regions that can be nested, for example
the following construct:

----------
%sh{ ... }
----------

accepts nested braces scopes ('{ ... }') so the following string is valid:

----------------------
%sh{ ... { ... } ... }
----------------------

This region can be defined with:

---------------------------------
shell_expand -recurse \{ %sh\{ \}
---------------------------------

Regions are matched using the left-most rule: the left-most region opening
starts a new region. When a region closes, the closest next opening start
another region.

That matches the rule governing most programming language parsing.

A default region, that will apply its given highlighter to the segments of the
buffer that are not in any defined region, can be added with the *default-region*
highlighter type.

-----------------------------------------------------------------------------
add-highlighter <path>/<name>/<region_name> default-region <type> <params>...
-----------------------------------------------------------------------------

Most programming languages can then be properly highlighted using a region
highlighter as root:

-----------------------------------------------------------------
add-highlighter <path>/<lang> regions
add-highlighter <path>/<lang>/string region '"' '"' fill string
add-highlighter <path>/<lang>/comment region '//' '$' fill comment
add-highlighter <path>/<lang>/code default-region group
add-highlighter <path>/<lang>/code/variable regex ...
add-highlighter <path>/<lang>/code/function regex ...
-----------------------------------------------------------------

== Shared Highlighters

Highlighters are often defined for a specific filetype, and it makes then
sense to share the highlighters between all the windows on the same filetypes.

Highlighters can be put in the shared scope in order to make them reusable.

---------------------------------
add-highlighter shared/<name> ...
---------------------------------

The common case would be to create a named shared group, or regions and then
fill it with highlighters:

---------------------------------------
add-highlighter shared/<name> group
add-highlighter shared/<name>/ regex ...
---------------------------------------

It can then be referenced in a window using the ref highlighter.

----------------------------------
add-highlighter window/ ref <name>
----------------------------------

The ref can reference any named highlighter in the shared scope.
