5

I'd like to highlight sections of a document which are too long (measured in lines) so they will all print on a physical page. Sections are separated with ===. I tried to do it with this code:

matchadd('ErrorMsg', '\%(^\|===\n\)\%(.*\n\)\{5}\zs\%(.*\n\)\+\ze', -1)

Everything works hunky-dory. But when I increase the size:

matchadd('ErrorMsg', '\%(^\|===\n\)\%(.*\n\)\{80}\zs\%(.*\n\)\+\ze', -1)

matches don't highlight. From the documentation :matchadd:

Defines a pattern to be highlighted in the current window (a
    "match")

Based on figuring out where exactly the problem happens, I think it's not using text outside the current window. What should I be doing instead? Sections are already associated with folds if that helps.

2
  • 1
    I think you are misunderstanding what window actually means. Also, I think your regex is wrong, but this depends on an actual example and you didn't give one. Apr 19, 2017 at 10:53
  • that is probably the limitation of vim's multiline regexes coupled with redraws. For me it works for the number of available window lines-1.
    – Maxim Kim
    Jul 27, 2021 at 15:38

3 Answers 3

1

If you are not insisting on using matchadd you can try to use properties, here is the proof of concept you can play with:

call prop_type_add('TEST', {'highlight': 'ErrorMsg'})

"screen jumps sometimes, try to find your own way
func! UpdatePage(pagesize) abort
    let cpos = getcurpos()
    1
    call prop_clear(1, line('$'))
    while search('^|===$', 'Wc')
        normal! j
        let next_section = search('\(^|===$\)\|\%$', 'Wn')
        let next_section = (next_section == line('$')?line('$'):next_section-1)
        if next_section - line('.') > a:pagesize
            call prop_add(line('.') + a:pagesize, 1, {'end_lnum': next_section, 'end_col': 1000, 'type': 'TEST'})
        endif
    endwhile
    call setpos('.', cpos)
endfunc

" TODO: add it to its own group
au! InsertLeave * call UpdatePage(80)

enter image description here

1

A much simpler option is to set colorcolumn=80 or whatever number(s) you want: then you have a line down the screen that shows your breakpoint.

0

How about :au BufWinEnter * let w:m1=matchadd('ErrorMsg', '\(^===\)\_p\{20,}\1', -1) ?

This works with my little lorem ipsum test case.

The solution here is \_p\{20,}, which matches at least 20 printable characters including newline (that is the _).

I tried this with a little "lorem ipsum", consecutive blocks are also highlighted, which makes the whole affair quite colorful...

1
  • This is testing for 20 printable characters--I want to match 20 lines, I'm not sure what you were understanding me as asking, but my original regex is already correct. Is your window more, or less, than 20 rows tall? If your individual matches fir on the screen, you are not duplicating the problem I describe. Apr 19, 2017 at 3:27

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.