1

I'm trying to write a plugin to highlight overused words in a file. After this question I now have a way to highlight the most frequent words in each paragraph.

To restrict the highlighting of a word to a single paragraph I'm using matchadd with a line range:

matchadd('Error', word . '\%>' . (a:firstline - 1) . 'l\%<' . (a:lastline + 1) . 'l')

The problem is that if the user adds or removes a line in the middle of a file it messes up the highlighting of the following lines.

So how can I keep the highlighting up to date after changes in the file?

My first thought is to just clear the previous matches and highlight everything all over again when a line is added or removed. Is there no better way to do it? If there isn't, how can I detect if a line was added or removed so I can clear the matches and add them again?

  • 2
    You could keep track of the number of lines in the file. But I think a better approach is to reload the highlighting on an appropriate event, such as InsertLeave. The reloading should first clear all existing highlighting, which can be done with matchdelete(). – Karl Yngve Lervåg Jul 26 '16 at 9:10
  • @KarlYngveLervåg Yes, but then the highlighting will be all wrong while the user is typing, especially if he types a lot all at once. I guess the more conservative approach would be to clear the highlighting on InsertEnter and add it back on InsertLeave. But now that I'm looking into it I figured I can check if the number of lines is different on CursorMovedI and update if it is… or even update every time the user types a space to have "real time" highlighting, it doesn't seem to add too much overhead, I'm not sure if it would be considered bad practice. Thanks! – dbmrq Jul 26 '16 at 19:23
  • Yes, you could also use the CursorMovedI. However, as you've noticed, you should make sure to test this well, as it may have a large performance impact. If it is only for personal use, I wouldn't be too worried, but if you are working on a public thing, I would be more conservative. – Karl Yngve Lervåg Jul 26 '16 at 19:46
  • 1
    I do hope more people will use the plugin. I'll leave it up to the user, then… "if you want to highlight matches, add this autocmd". Thanks for your help. :) – dbmrq Jul 26 '16 at 20:41
1

I also have the same issue in my plugin, diffchar.vim. This plugin highlights the exact diff units with matchadd/matchaddpos and tries to interactively update those highlights while editing.

My approach is:

  • always record which lines are highlighted
  • get TextChanged/TextChangedI events
  • get the post-edit contents of highlighted lines
  • do 'undo'
  • get the pre-edit contents of highlighted lines
  • do 'redo'
  • compare between pre and post to find which lines are changed
  • clear highlights of changed line and then draw them

Since I do not think it is perfect, I am still looking for a better approach :-).

  • Wow, I was reading the autocmd-events documentation online instead of in ViM and it must have been an old version or something, because TextChanged wasn't mentioned. That'll be a huge improvement already! – dbmrq Jul 27 '16 at 5:22
0

After looking into :h autocmd-events for a bit I came up with this:

let s:lastline = 0

function! MyAutoFunction()
    if line('$') != s:lastline
        " Clear previous matches
        " Add matches back
        let s:lastline = line('$')
    endif
endfunction

au TextChanged,TextChangedI * call MyAutoFunction()

And it seems to work pretty well.

If anybody has a better idea, I'm all ears. :)


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.