Search code examples
vimsyntax-highlighting

How to modify existing highlight group in vim?


If I have an existing highlight group in vim via link, for example

hi link my_highlight_group my_default_color

Is it possible to add 'bold' to my_highlight_group without changing my_default_color? Following does not work:

hi my_highlight_group gui=bold

Surprisingly, I can add bold if my_highlight group is defined directly (not via link):

hi my_highlight_group guifg=#F0000
hi my_highlight_group gui=bold

Solution

  • As "too much php" has said, there is no direct way to say "create a value that looks like that one and add bold". The best way is to modify your colour scheme. If you're not using a custom colour scheme, copy one from the main vim installation directory to your ~/.vim/colors directory and edit it to suit you. Alternatively, search on the vim scripts page and try some of the many that are available.

    Shameless plug: if you want one that's easier to edit than the standard format, try my "Bandit" colour scheme.

    If you really want to be able to add bold on the fly, you'll need a fairly complex script, like the one below. Note that this won't be saved for your next session unless you call it automatically after loading your colour scheme or by doing something like:

    :autocmd ColorScheme AddBoldToGroup my_highlight_group
    

    The script in all it's enormity is below. As far as I am aware, there is no significantly quicker way of doing this! Obviously you could save a few lines by writing less verbose code, but the general idea of using redir and silent hi repeatedly is the only way.

    " Call this with something like
    "
    " :AddBoldToGroup perlRepeat
    "
    command! -complete=highlight -nargs=1 AddBoldToGroup call AddBoldToGroup(<f-args>)
    function! AddBoldToGroup(group)
        " Redirect the output of the "hi" command into a variable
        " and find the highlighting
        redir => GroupDetails
        exe "silent hi " . a:group
        redir END
    
        " Resolve linked groups to find the root highlighting scheme
        while GroupDetails =~ "links to"
            let index = stridx(GroupDetails, "links to") + len("links to")
            let LinkedGroup =  strpart(GroupDetails, index + 1)
            redir => GroupDetails
            exe "silent hi " . LinkedGroup
            redir END
        endwhile
    
        " Extract the highlighting details (the bit after "xxx")
        let MatchGroups = matchlist(GroupDetails, '\<xxx\>\s\+\(.*\)')
        let ExistingHighlight = MatchGroups[1]
    
        " Check whether there's an existing gui= block
        let MatchGroups = matchlist(ExistingHighlight, '^\(.\{-}\) gui=\([^ ]\+\)\( .\{-}\)\?$')
        if MatchGroups != []
            " If there is, check whether "bold" is already in it
            let StartHighlight = MatchGroups[1]
            let GuiHighlight = MatchGroups[2]
            let EndHighlight = MatchGroups[3]
            if GuiHighlight =~ '.*bold.*'
                " Already done
                return
            endif
            " Add "bold" to the gui block
            let GuiHighlight .= ',bold'
            let NewHighlight = StartHighlight . GuiHighlight . EndHighlight
        else
            " If there's no GUI block, just add one with bold in it
            let NewHighlight = ExistingHighlight . " gui=bold"
        endif
    
        " Create the highlighting group
        exe "hi " . a:group . " " NewHighlight
    endfunction