I have two scenarios where I want vim to highlight those items. Currently my fix for these are to add the return types directly into the after/syntax/c.vim file, but this gets incredibly tedious. Here are two examples:

typedef struct Item {
    char* tag;
} Item;

Item* fetch_item(void)

int main(void)
    Item *item = fetch_item();

So, I would like two things highlighted here:

  • Item <-- the new 'type' I've added, similar to how vim highlights int or char, etc.
  • fetch_item() <-- the new 'function' I've added, similar to how vim highlights printf.

What is the best way to do this without having to manually add a function name to the c.vim file whenever I create a new function?


This is quite a crude way to do it. Though from the various highlighting tag plugins I found -- such as https://github.com/xolox/vim-easytags and https://github.com/ludovicchabant/vim-gutentags -- this was the only solution that worked to capture all the items I wanted to grab.

Here's a python script that will generate additional tags for enums, typedefs, and functions:

# ~/.vim/after/generate_ctags.py
import re
from sys import argv

# write the new tags to the following C syntax file
syntax_file = '/home/ubuntu/.vim/after/syntax/c.vim'

# define basic regexes for the types to capture. These are quite crude for the
# structs and especially functions, but works for my functions/structs
with open(argv[-1), 'r') as f: input_data=f.read()
typedefs = re.findall(r'typedef\s+struct\s+([^\s{]+).+}\s*\1\s*;', input_data, re.DOTALL)
enums = re.findall(r'typedef\s+enum\s{[^}]+}\s+(\w+)\s*;', input_data, re.DOTALL)
functions = re.findall(r'(?:^|\n)(?:[\w*]+\s){1,2}(\w+)(?=\s*\()', input_data, re.DOTALL)

# See what we've already written
with open(syntax_file, 'r') as f: existing=f.read()

# If we haven't added it manually, append a line to the file with it
with open(syntax_file, 'a') as f:
    for tag in (typedefs + enums):
        format_string = 'syn keyword StorageClass %s\n' % tag
        if format_string not in existing: f.write(format_string)
    for tag in functions:
        if re.search(r'\nsyn keyword .+ %s\s' % tag, existing): continue
        f.write('syn keyword function %s\n' % tag)

And as a shortcut in vimrc:

" Generate new tags (typedef + enum + function)
function GenerateCTags()
    silent !python /home/ubuntu/.vim/after/generate_ctags.py %
nnoremap <Leader>7C :call GenerateCTags()<CR>
inoremap <Leader>7C <Esc>:call GenerateCTags()<CR>

Note that this does not handle the case of tags being removed -- i.e., if a function name is changed from my_function to my_new_function.

A better method would make use of ctags, but I haven't really figured that out yet (at least how to get parsable data from it). But either way, whatever is parsed needs to be inserted/modified/removed from the syntax file or something similar.

Here is a screenshot of the solution, highlighting Item and fetch_item:

enter image description here

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.