How to create a syntax keyword at runtime?

41 views
Skip to first unread message

Ron Aaron

unread,
Dec 9, 2020, 3:56:35 AM12/9/20
to vim_dev
Hi all -

I want to have a keyword (user-defined function) highlighted by my syntax file.

The code looks like this:

    :  foo  blah blah ;

In this case I want "foo" to be scooped up. What I'm doing now is this:

     syn match colonDef "^\s*:\s\+\zs\S\+"

That highlights the correct thing (e.g. 'foo') where it's defined, but I can't figure out how to get it to be highlighted elsewhere in the code (e.g. when simply 'foo' appears without a leading colon).

How can I accomplish this?

Ron Aaron

unread,
Dec 13, 2020, 2:14:47 AM12/13/20
to vim_dev
Is this possible w/ vim's syntax highlighting?

Charles Campbell

unread,
Dec 13, 2020, 10:28:28 AM12/13/20
to vim...@googlegroups.com
What do you mean by "vim's syntax highlighting"? Assuming no filetype,
say in a file called "joe.coffee", you could type

syn keyword colonDef foo
hi link colonDef Statement

and foo would be highlighted as Statement in your file.

Somehow I don't think you're really meaning "vim's syntax highlighting",
but rather "vim's syntax highlighting for the XYZ filetype". Naturally,
that missing information greatly affects things.  Syntax highlighting
involves groups, containment, matches, regions, etc. My guess is that
you want your modified "colonDef" highlighting to occur in some region
defined by the filetype's syntax highlighting, but you've defined a
match that is not contained in that region. To find out what that region
is named, you could try my plugin:
http://www.drchip.org/astronaut/vim/index.html#HILINKS and use :HLT!,
move the cursor about, and you'll see a trace explaining what syntax and
highlighting regions/etc are involved. Additionally, there's issues of
priority involved, but often you can use "containedin=..." to get what
you want.

Once you've done that, you could place a file in your
.vim/after/syntax/XYZ.vim file the extra directions giving the
additional highlighting you want.

Regards,
Chip Campbell

Ron Aaron

unread,
Dec 14, 2020, 12:04:27 AM12/14/20
to vim_dev
I explained exactly what I mean in the original post.

Yes, of course I'm talking about a specific file type, but the specific type is unimportant since it's something I'm creating and not something in the vim syntax files.

What I intend is simply that if the user types in (the file being created) something like:

    : foo bar ;

Then "foo" becomes a syntax keyword. The criteria for becoming a keyword in this context is that it is preceded by a colon, and delimited by white-space. Thus 'bar' is not a keyword, nor is ": foo".  Think of the leading colon-space as a function declarator.

What I can't figure out is how to trap "foo" without trapping the leading colon-space.

Maxim Kim

unread,
Dec 14, 2020, 6:41:23 AM12/14/20
to vim_dev
If I get you right I don't think this is possible (or really cumbersome to do) with existing :syntax commands.

: foo bar ; <-- foo is defined and highlighted as statement

then anywhere else in the text:

bla bla bla foo bla bla <-- foo should be highlighted as statement

Although, text properties with external text analyzer might be a good fit for it.

понедельник, 14 декабря 2020 г. в 08:04:27 UTC+3, Ron Aaron:

Ron Aaron

unread,
Dec 14, 2020, 11:02:09 AM12/14/20
to vim_dev
Yes, Maxim; that's exactly what I want to accomplish. And yes, I don't see how to do it in vimscript, but I was hoping someone might have an idea.

I suppose an imap on ':' might be able to make it happen with functions.

Charles Campbell

unread,
Dec 14, 2020, 12:56:14 PM12/14/20
to vim...@googlegroups.com
Ron Aaron wrote:
I explained exactly what I mean in the original post.

Yes, of course I'm talking about a specific file type, but the specific type is unimportant since it's something I'm creating and not something in the vim syntax files.

What I intend is simply that if the user types in (the file being created) something like:

    : foo bar ;

Then "foo" becomes a syntax keyword. The criteria for becoming a keyword in this context is that it is preceded by a colon, and delimited by white-space. Thus 'bar' is not a keyword, nor is ": foo".  Think of the leading colon-space as a function declarator.

What I can't figure out is how to trap "foo" without trapping the leading colon-space.
OK, as I said in my earlier reply, what you need is to have

 syn keyword colonDef foo

(or whatever you want foo to be highlighted as). The trick is to get the : to trigger getting that new syntax statement. You can try something like:
inoremap ; ;<esc>:call InsertNewSyntax()<cr>a

fun! InsertNewSyntax()
  if getline(".") =~ '^\s*:\s*\h\w*'
   let newsyn= substitute(getline("."),'^\s*:\s*\(\h\w*\)\s*;','\1','')
   exe "syn keyword Statement ".newsyn
  endif
endfunction
You could even make this part of your syntax file, even though it isn't strictly syntax.  Every time you type a semicolon, the function is called which checks to see if it can extract a word from  : word ; and, if it can, it will install that word as a new keyword.

Regards,
Chip Campbell


P.S. IMHO -- this topic would've better have to have been in vim...@googlegroups.com, as it isn't associated with developing vim.
Reply all
Reply to author
Forward
0 new messages