I spent some time tackling this and wondered if anybody had a more
elegant solution.  The problem is that some color schemes set the
background of strings, comments, etc. to something other than the
default background color.  Any syntax using a highlight group that
isn't affected by this, but is "contained" inside a string, such as a
variable reference in a scripting language like sh or Tcl, will thus
have a different background than the surrounding string.  This makes
the string appear broken up, when in fact it's not.  I asked on #vim
if there was a way to select only the foreground or background to be
'transparent' but was told there isn't.  That leaves setting the
highlighting guibg/guifg and ctermbg/ctermfg manually.  This isn't
that hard, but it requires some repetition and hackishness that makes
me uncomfortable.

As proof-of-concept, I modified the Tcl syntax to use a cluster for
variable references inside strings.  Thus, I have:

syn cluster tclVarRefC add=tclVarRef
syn region tclString ... contai...@tclvarrefc

This is opposed to simply containing the tclVarRef directly as it had
previously been.  Then to my .vimrc I added a ton of code:

======== >8 ================================ 8< ========

function! TweakSyntax()
    if &filetype == 'tcl'
        syn match tclVarRefS "$\(\(::\)\?\([[:alnum:]_]*::\)*\)\a[[:alnum:]_]*" 
contained
        syn match tclVarRefS "${[^}]*}" contained

        " This is needed because when a file is loaded from the command line,
        " the colorscheme autocommand is triggered before the syntax one.
        " Thus the syntax cluster is set, then immediately cleared by the Tcl
        " syntax file load, forcing us to set it again manually here.
        call TclStringBackgroundHack()
    endif
endfunction

" --------------------------------------------------------------------
"   Some themes use a special background color for strings that is
"   different from the main background.  This hack subverts that.
" --------------------------------------------------------------------

let g:tcl_use_string_bg=1

function! TclSafeAdjustSyntax(group, type, fallback, what, mode)
    let l:typeSyn=synIDattr(synIDtrans(hlID(a:type)), a:what, a:mode)
    let l:fallbackSyn=synIDattr(synIDtrans(hlID(a:fallback)), a:what, a:mode)
    if a:type != '' && l:typeSyn != -1 && l:typeSyn != ''
        exec 'hi ' . a:group . ' ' . a:mode . a:what . "=" . l:typeSyn
    elseif a:fallback != '' && l:fallbackSyn != -1 && l:fallbackSyn != ''
        exec 'hi ' . a:group . ' ' . a:mode . a:what . "=" . l:fallbackSyn
    endif
endfunc

function! TclStringBackgroundHack()
    if exists('g:tcl_use_string_bg') && g:tcl_use_string_bg == 1
        syn cluster tclVarRefC remove=tclVarRef add=tclVarRefS

        if has('gui_running')
            call TclSafeAdjustSyntax('tclVarRefS', 'String',     'Identifier', 
'bg', 'gui')
            call TclSafeAdjustSyntax('tclVarRefS', 'Identifier', '',           
'fg', 'gui')
        else
            call TclSafeAdjustSyntax('tclVarRefS', 'String',     'Identifier', 
'bg', 'cterm')
            call TclSafeAdjustSyntax('tclVarRefS', 'Identifier', '',           
'fg', 'cterm')
        endif
    else
        syn cluster tclVarRefC remove=tclVarRefS add=tclVarRef
    endif
endfunc

" --------------------------------------------------------------------
"   Auto Commands
" --------------------------------------------------------------------

if !exists("autocommands_loaded")
    autocmd Syntax * call TweakSyntax()
    autocmd ColorScheme * call TclStringBackgroundHack()
endif

======== >8 ================================ 8< ========

This creates an alternate syntax that does the same thing, but we
change the highlighting to use only the parts that we want: the
background of a String, the foreground of an Identifier.  (We need to
make a separate syntax so that the current one can continue to be
used... I think.  This is an area where there might be a better way.)
Then I add this new syntax to the cluster and remove the old one.  Tcl
strings at this point will use my hacked variable reference tclVarRefS
rather than the normal tclVarRef which is used outside strings.  On
color scheme change, we are forced to recalculate the colors.  The
syntax hook is present because otherwise the syntax setup in vimrc at
startup time is cleared by the syntax file (I'm not exactly sure why
this occurs).

So what do you think?  Is there a simpler way to do it?

In case my description of the problem was unclear, I've put an example
on my website:
http://real.metasyntax.net:2357/blog/2009/06/06/#Vim-Color-Schemes-and-String-Background

Thanks for feedback
    and happy Vimming,

-- 
Taylor Christopher Venable
http://real.metasyntax.net:2357/

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Reply via email to