LeMiz
LeMiz

Reputation: 5634

Custom syntax highlighting in vim for links

I have a custom file format for graphs which looks like this:

node1.link1 : node2
node1.attribute1 : an_attribute_for_node1
node2.my_attribute1 : an_attribute_for_node2

(there is nothing special about the attributes names, an attribute is a link iff one can find its value at the left of a dot. So node2 is a link, because there is a line somewhere in the file that begins with node2.<something>).

I would like to highlight the attribute values if they are links (so I would like to highlight node2, but not attribute_for_node1).

Obviously, this kind of syntax highlighting cannot be based only on line wide regexp, because one needs to read the entire file to do the correct highlighting.

I already have a python parser for this kind of files (which gives a dict of dict string -> (string -> string)), but I don't know if python can interact with syntax highlighting in vim 7.

EDIT As a clarification, the dictionary produced for this example is:

d = {
  'node1': {'link1' : 'node2', 'attribute1' : 'an_attribute_for_node1'},
  'node2': {'attribute2': 'an_attribute_for_node2'}
}

By definition, l is a link for node n if and only if:

d[n][l] in d

Names are meaningless, the format is only structure dependant, and there is no language keywords. I would like to highlight node2 in the first line, because it is the name for a node.

I hope it is clearer now.

Someone has an idea ?

Upvotes: 1

Views: 1512

Answers (1)

DrAl
DrAl

Reputation: 72606

This should be very straightforward, but it's a little difficult to work out exactly what your dict looks like (what is 'string'? node1? attribute1? something else?). I have a plugin that I wrote called the ctags highlighter which does a fairly similar thing: it uses ctags to generate a list of keywords and then uses python to turn this into a simple vim script that highlights those keywords appropriately.

Basically, what you need to do is make your parser (or another python module that uses your parser) to generate a list of keywords (node1, node2 etc) and output them in this form (use as many per line as you like, but don't make the lines too long):

syn keyword GraphNode node1 node2
syn keyword GraphNode node3

Write this to a file and create an autocommand that does something like:

autocmd BufRead,BufNewFile *.myextension if filereadable('nodelist.vim') | source nodelist.vim | endif

Then do:

hi GraphNode guifg=blue

or whatever. If you want more details, post a little more information about your parser or have a look at the code in my plugin.

For more information, see

:help :autocmd
:help syn-keyword
:help BufEnter
:help BufNewFile
:help filereadable()
:help :source
:help :highlight

Edit

I'm still not completely sure I know what you want, but if I am understanding correctly, something like this should work:

Let's assume that your python parser is called mypyparser.py, it takes one argument (the current filename) and the dictionary it creates is called MyPyDict. You'll obviously have to modify the script to match the actual use of your parser. Add this script somewhere in your runtimepath (e.g. in .vimrc or in ~/.vim/ftplugin/myfiletype.vim) and then open your file and type :HighlightNodes.

" Create a command for ease of use
command! HighlightNodes call HighlightNodes()
function! HighlightNodes()
    " Run the parser to create MyPyDict
    exe 'pyfile mypyparser.py ' . expand('%:p')
    " Next block is python code (indent gone to keep python happy)
    py <<EOF
# Import the Vim interface
import vim
# Iterate through the keys in the dictionary and highlight them in Vim
for key in MyPyDict.keys():
    vim.command('syn keyword GraphNode ' + key)
endfor
EOF
    " Make sure that the GraphNode is highlighted in some colour or other
    hi link GraphNode Keyword
endfunction

Upvotes: 2

Related Questions