Vim 7.3 new feature Conceal has an issue that when you change your colorscheme the current conceal information will be partly removed automatically.
I found this issue with the combination of Haskell-Conceal plugin and unite-colorscheme plugin which internally uses tabpagecolorscheme plugin. Every time I moved the tab, the concealed text highlighted wrongly. After a research I figured out that it was not by changing the tab but by changing colorscheme into the same colorscheme.
First of all, the idiom to define a concealed token in a syntax file is (1) to define a syntax match {your favourite name here} "{regexp}" conceal cchar={the replacement}
(2) and to link the color by highlight! link Conceal {token name}
. Note that normal highlights only needs to hightlight
without the bang.
The main part of the implementation of colorscheme
command is defined as below which is from src/syntax.c of vim repository.
6755 /*
6756 * Load color file "name".
6757 * Return OK for success, FAIL for failure.
6758 */
6759 int
6760 load_colors(name)
6761 char_u *name;
6762 {
6763 char_u *buf;
6764 int retval = FAIL;
6765 static int recursive = FALSE;
6766
6767 /* When being called recursively, this is probably because setting
6768 * 'background' caused the highlighting to be reloaded. This means it is
6769 * working, thus we should return OK. */
6770 if (recursive)
6771 return OK;
6772
6773 recursive = TRUE;
6774 buf = alloc((unsigned)(STRLEN(name) + 12));
6775 if (buf != NULL)
6776 {
6777 sprintf((char *)buf, "colors/%s.vim", name);
6778 retval = source_runtime(buf, FALSE);
6779 vim_free(buf);
6780 #ifdef FEAT_AUTOCMD
6781 apply_autocmds(EVENT_COLORSCHEME, NULL, NULL, FALSE, curbuf);
6782 #endif
6783 }
6784 recursive = FALSE;
6785
6786 return retval;
6787 }
Basically this function runs :source colors/{the colorscheme name}.vim
and them runs autocmds already registers in Colorscheme event. This function itself looks good.
Every colorscheme files run :highlight clear
in the beginning of the files. This removes all highlights except for user-defined ones. Thus it preserves syntactic information of each syntax files, but breaks conceal information given by each syntax files, because it's not treated as user-defined one but as just extended built-in one.
Possible solutions
I propose the following solutions. Each of them are independent and exclusive.
- Remove the procedure of removing conceal information from
:highlight clear
command - Fix colorscheme command to recover the conceal information after changing colorscheme
- The behaviour is specification. Just add documentation in Vim core to persuade conceal users to add autocmd event to change conceal again after colorscheme changed.
The below is the patch for the solution (a).
diff --git src/syntax.c src/syntax.c
index 369311f..90165cf 100644
--- src/syntax.c
+++ src/syntax.c
@@ -6572,10 +6572,6 @@ static char *(highlight_init_light[]) =
CENT("ColorColumn term=reverse ctermbg=LightRed",
"ColorColumn term=reverse ctermbg=LightRed guibg=LightRed"),
#endif
-#ifdef FEAT_CONCEAL
- CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey",
- "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"),
-#endif
#ifdef FEAT_AUTOCMD
CENT("MatchParen term=reverse ctermbg=Cyan",
"MatchParen term=reverse ctermbg=Cyan guibg=Cyan"),
@@ -6662,10 +6658,6 @@ static char *(highlight_init_dark[]) =
CENT("MatchParen term=reverse ctermbg=DarkCyan",
"MatchParen term=reverse ctermbg=DarkCyan guibg=DarkCyan"),
#endif
-#ifdef FEAT_CONCEAL
- CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey",
- "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"),
-#endif
#ifdef FEAT_GUI
"Normal gui=NONE",
#endif