Assume we have this text:


matchaddpos("Error", [[1,2]]) highlights the second character (the first 'a') as "Error" group.

 ^ highlighted

When I insert a 'b' at the beginning, it becomes

 ^ highlighted

It looks like the color is stick to the "grid" instead of the character underneath.

What I wanted is this:

  ^ highlighted

That is, is there a "thing" that, when I call thing("Group", [[lnum,col]]), the color is added to the character at that position, so that even when the character moves, the color follows it?

  • 4
    no, not possible. This was discussed briefly, when matchaddpos() was introduced, but nobody really was interested in implementing it. – Christian Brabandt Jul 21 '16 at 6:28
  • What do you intend to use this for? – Antony Jul 21 '16 at 7:01

In vim, it is now possible since patch 8.1.0579 using text properties (:help textprop).

As the name suggests, a text property is a property that can be associated to text, and moves with it. Properties can be used for highlighting, but the concept is more general and could have other use cases (e.g. tagging for jumping).

To do highlighting with properties, firstly it is necessary to define a property type for the desired highlight group, and secondly to apply it to regions of text. A property type can be defined using the function prop_type_add()

call prop_type_add('error_property', {'highlight': 'Error'})

where 'error_property' is a name for the new property, and the second argument defines what the property is, in this case it is the Error syntax highlight group (for more options, please refer to |prop_type_add()|).

Once a property type is defined, it can be assigned to a region of text using the function prop_add(). An instance of property can be identified by an optional id. What I find handy is the fact that a property can span over multiple lines:

let l:options = {
\   'id': l:id,
\   'type': 'error_property',
\   'end_lnum': l:end_line,
\   'end_col': l:end_column,
\ }
call prop_add(l:start_line, l:start_column, l:options)

For additional options, please refer to |prop_add()|.

Properties can be removed with prop_remove(), either by id or by type, e.g.

" Remove property with ID equal to 1
call prop_remove({'id': 1})

" Remove all properties of type 'error_property' within lines l:start and l:end (inclusive)
call prop_remove({'type': 'error_property', 'all': v:true}, l:start, l:end)

You can't do that with matchadpos(). This is a known problem with Vim highlighting, and it isn't likely to be solved any time soon.

The best you can do is to use matcadd() with a regexp that matches on line 1, and anchor it at the first a. Perhaps like this:

:call matchadd('Error', '\%1l[^a]\zsa')

Now it's partially possible (adapts to line insertions and deletions only) with NeoVim!

From Neovim Newsletter #7 - Summer of Road:

  • buffer-local highlighting (:help api-highlights) is similar to matchaddpos(), with some key differences: it is associated with a buffer and adapts to line insertions and deletions. Useful for linter or semantic highlighter plugins that monitor a buffer for changes and compute highlights in the background.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.