7

I'm trying to write a syntax file for Linux logrotate scripts.

Often they contain inline definitions of scripts to be run before or after the rotate action.

An example (the cups-daemon logrotate script as provided by Ubuntu 14.04):

    prerotate
            if [ -e /var/run/cups/cupsd.pid ]; then
                    invoke-rc.d --quiet cups stop > /dev/null
                    touch /var/run/cups/cupsd.stopped
            fi
    endscript
    postrotate
            if [ -e /var/run/cups/cupsd.stopped ]; then
                    rm /var/run/cups/cupsd.stopped
                    invoke-rc.d --quiet cups start > /dev/null
                    sleep 10
            fi
    endscript

Is there any way to both:

  • highlight prerotate and postrotate as keywords, and
  • highlight all in between as a region?

I may define proper highlighting for either of those, but it seems not for both.

" this works
syntax keyword LogrotateKeyword prerotate postrotate endscript

" this also works
syntax region LogrotateScript start=/prerotate/ms=e+1 end=/endscript/me=s-1

Now both of those in the same syntax file yield only highlighting for keywords, regardless of the rule order used.

I tried match (with \zs/\ze or lookaheads/lookbehinds) instead of region too. I also tried to use match for both the keywords and inline scripts, hoping it would not make the definitions overlap, the results seem to be just the same.

I might keep the default color for the inline script, but apparently frequently the inline stuff contains other logrotate keywords, which might be confusing.

Most likely irrelevant to this issue: Vim 7.4 with patches 1-1529 (pi-rho PPA) and Ubuntu 14.04.

  • If you ever finish the logrotate syntax file, please do share. It would be nice to have. – muru Mar 21 '16 at 18:37
  • @muru Here it is. Thank you for your excellent answer :) – Łukasz Górski Mar 21 '16 at 19:04
5

After some experimenting, here's something that works:

syntax keyword LogrotateKeyword prerotate postrotate endscript contained
syntax region LogrotateScript start=/\v^\s*(pre|post)rotate\s*$/rs=e+1 end=/^\s*endscript\s*$/re=s-1 keepend contains=LogrotateKeyword

To get one syntax set to cooperate with another that's overlapping, we can contain the narrower match within the broader match.

In this case:

  • I mark the keywords as contained and the region as containing the keywords. Marking the keywords is not necessary, but, considering the nature of these keywords, they will always be accompanied by this region in the valid case.
  • I had to use keepend so that the match for the keyword doesn't obscure the match for the end of the region.
  • I picked the broader regular expressions that cover the whole line, so that highlighting doesn't extend to these lines (or if you set a coloured background, it will look very weird).

Combining with Vim's shell script syntax highlighting:

syntax include @sh syntax/sh.vim
syntax keyword LogrotateKeyword prerotate postrotate endscript contained
syntax region LogrotateScript start=/\v^\s*(pre|post)rotate\s*$/rs=e+1 end=/^\s*endscript\s*$/re=s-1 keepend contains=LogrotateKeyword,@sh
highlight LogrotateKeyword ctermfg=yellow 

I get:

enter image description here

Note that I used re and rs instead of ms/hs, me/he. With the other options, combining the keywords with shell script syntax didn't work, though I don't know why.


The following would be better:

syntax region LogrotateScript matchgroup=LogrotateKeyword start=/\v(pre|post)rotate/ end=/endscript/ contains=@sh

In this case, I take advantage of matchgroup:

                                                        :syn-matchgroup
        "matchgroup" can be used to highlight the start and/or end pattern
        differently than the body of the region.  Example: 
  :syntax region String matchgroup=Quote start=+"+  skip=+\\"+  end=+"+
       This will highlight the quotes with the "Quote" group, and the text in
        between with the "String" group.

Looking back, matchgroup was meant to solve exactly this problem. We don't need to list out the delimiting keywords separately, since matchgroug lets us highlight the delimiters separately.

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.