Bram Moolenaar wrote:
>
> Suresh Govindachar wrote:
>> Bram Moolenaar wrote:
>>> Suresh Govindachar wrote:
>>>
>>>> Please consider supporting expressions for syntax matching.
>>>> An example of usage is indicated below:
>>>
>>> I don't quite get it. ":syn match" commands use a pattern.
>>> You can use ":exec" to get the pattern from an expression.
>>
>> Good, but how does one use :exec to get the pattern from an
>> expression?
>>
>> As an example expression, the following expression returns 0
>> or 1 for line("."):
>>
>> (
>> \ ( foldlevel(line(".")) != foldlevel(line(".")-1) ) &&
>> \ ( foldlevel(line(".")) != foldlevel(line(".")+1) ) &&
>> \ ( 4 == foldlevel(line('.'))/2 )
>> \ )
>> \ ? 1
>> \ : 0
>>
>> How would I use exec to get a pattern?
[In the above, line(".") I does _not_ mean the line where the
cursor currently is; but means "the line the syntax engine
is currently dealing with".]
> Obviously you can currently only evaluate the expression the
> moment the syntax is defined, not when an item is used.
>
> Each item may be used at every character in the file.
> Evaluating all the expressions for every item at every character
> would be very slow. Even the current mechanism with patterns is
> slow for some languages, and it includes all kinds of
> optimizations to avoid trying a match at every character and
> caching the result. With an expression you never know what it
> will do, thus these optimizations would not be possible. And
> evaluating the expression adds on top of that.
Did not grasp this complexity. However, the following special
case (which my present needs fall under) seems to have a solution.
Situation: We have a function f(line_n) which takes in a line
number and which returns a number between -1 and N.
We have defined highlights level0, level1, ..., levelN.
We want to leave line_n un-colored if f(line_n)
is -1, otherwise we want to color it with 'Level'.f(line_n)
Solution: Create a syntax file as follows (for those not
familiar with it, "oneline" below is an option to the
syntax command):
syn clear
%g/./let i = line('.') |
\ if( f(i) >= 0) |
\ exec 'syn match level'.f(i) .
\ ' /\%'.i.'l.*/ oneline [other-options] |
\ endif |
\ nohls
rest of the file defines highlights level<n>
I implemented the solution and have spent a little time working
with it. It is good enough for my needs, but some people might
not like the occasional need to update the syntax (meaning issue
'syn off | syn on').
Curious if anyone else is confronting a similar situation and
finds that the preceding solution is acceptable?
By the way, although having the :g command in a syntax file works
for me, I could not get the following example in :help /\%l
:exe '/\%' . line(".") . 'l.*'
to follow the current line. (I know about cursorline; just
mentioning that I could not make the preceding example work.)
Thanks,
--Suresh