This is a potential enhancement to 'syn-modifier' for your consideration.
It adds 'syn-removeattrs', which can be used as follows:
syntax region Bold start='\*' end='\*' contains=Unbold
syntax region Unbold start='\~' end='\~' removeattrs
highlight Bold term=bold
highlight Unbold term=bold
*this is bold ~this is not~*
It's a logical extension of 'syn-modifier': if there's a way to turn attrs on
without affecting other highlighting there should probably be a way to turn
them off.
I'm not thrilled about the naming or the implementation, though. A lot of the
hl_combine_attrs code was copied with lots tiny changes to merge with flag1 &
~flag2 instead of flag1 | flag2. A fairly significant refactor would be needed
to reduce the repetition.
I'm also not thrilled about the syntax, it's confusing to "highlight Unbold
term=bold" and have it remove bold.
I'm open to suggestions. Regardless, I think 'syntax modifier' stands on its
own.
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff -r 97220839b0b2 runtime/doc/syntax.txt
--- a/runtime/doc/syntax.txt Sun Dec 02 19:49:32 2012 -0800
+++ b/runtime/doc/syntax.txt Sun Dec 02 19:51:19 2012 -0800
@@ -3465,6 +3465,7 @@
containedin
nextgroup
modifier
+ removeattrs
transparent
skipwhite
skipnl
@@ -3768,6 +3769,19 @@
"contains" arguments to make that work (omitted for simplicity of the
example).
+removeattrs *:syn-removeattrs*
+
+Like |syn-modifier| except terminal attributes (italic, bold, etc.) are
+removed from existing highlighting. This affects 'term', 'cterm', and 'gui'
+|attr-list|. For example:
+
+ syn region Bold start="\*" end="\*" contains=Unbold
+ syn region Unbold start="\~" end="\~" removeattrs
+
+ highlight Bold term=bold
+ highlight Unbold term=bold
+
+ *This is bold, but this: ~isn't~*
IMPLICIT CONCEAL *:syn-conceal-implicit*
diff -r 97220839b0b2 runtime/syntax/vim.vim
--- a/runtime/syntax/vim.vim Sun Dec 02 19:49:32 2012 -0800
+++ b/runtime/syntax/vim.vim Sun Dec 02 19:51:19 2012 -0800
@@ -421,14 +421,14 @@
syn cluster vimSynKeyGroup contains=vimSynNextgroup,vimSynKeyOpt,vimSynKeyContainedin
syn keyword vimSynType contained keyword skipwhite nextgroup=vimSynKeyRegion
syn region vimSynKeyRegion contained oneline keepend matchgroup=vimGroupName start="\k\+" skip="\\\\\|\\|" matchgroup=vimSep end="|\|$" contains=@vimSynKeyGroup
-syn match vimSynKeyOpt contained "\<\(conceal\|contained\|transparent\|skipempty\|skipwhite\|skipnl\|modifier\)\>"
+syn match vimSynKeyOpt contained "\<\(conceal\|contained\|transparent\|skipempty\|skipwhite\|skipnl\|modifier\|removeattrs\)\>"
syn cluster vimFuncBodyList add=vimSynType
" Syntax: match {{{2
syn cluster vimSynMtchGroup contains=vimMtchComment,vimSynContains,vimSynError,vimSynMtchOpt,vimSynNextgroup,vimSynRegPat,vimNotation
syn keyword vimSynType contained match skipwhite nextgroup=vimSynMatchRegion
syn region vimSynMatchRegion contained keepend matchgroup=vimGroupName start="\k\+" matchgroup=vimSep end="|\|$" contains=@vimSynMtchGroup
-syn match vimSynMtchOpt contained "\<\(conceal\|transparent\|contained\|excludenl\|skipempty\|skipwhite\|display\|extend\|skipnl\|fold\|modifier\)\>"
+syn match vimSynMtchOpt contained "\<\(conceal\|transparent\|contained\|excludenl\|skipempty\|skipwhite\|display\|extend\|skipnl\|fold\|modifier\|removeattrs\)\>"
if has("conceal")
syn match vimSynMtchOpt contained "\<cchar=" nextgroup=vimSynMtchCchar
syn match vimSynMtchCchar contained "\S"
@@ -443,7 +443,7 @@
syn cluster vimSynRegGroup contains=vimSynContains,vimSynNextgroup,vimSynRegOpt,vimSynReg,vimSynMtchGrp
syn keyword vimSynType contained region skipwhite nextgroup=vimSynRegion
syn region vimSynRegion contained keepend matchgroup=vimGroupName start="\k\+" skip="\\\\\|\\|" end="|\|$" contains=@vimSynRegGroup
-syn match vimSynRegOpt contained "\<\(conceal\(ends\)\=\|transparent\|contained\|excludenl\|skipempty\|skipwhite\|display\|keepend\|oneline\|extend\|skipnl\|fold\|modifier\)\>"
+syn match vimSynRegOpt contained "\<\(conceal\(ends\)\=\|transparent\|contained\|excludenl\|skipempty\|skipwhite\|display\|keepend\|oneline\|extend\|skipnl\|fold\|modifier\|removeattrs\)\>"
syn match vimSynReg contained "\(start\|skip\|end\)="he=e-1 nextgroup=vimSynRegPat
syn match vimSynMtchGrp contained "matchgroup=" nextgroup=vimGroup,vimHLGroup
syn region vimSynRegPat contained extend start="\z([-`~!@#$%^&*_=+;:'",./?]\)" skip="\\\\\|\\\z1" end="\z1" contains=@vimSynRegPatGroup skipwhite nextgroup=vimSynPatMod,vimSynReg
diff -r 97220839b0b2 src/syntax.c
--- a/src/syntax.c Sun Dec 02 19:49:32 2012 -0800
+++ b/src/syntax.c Sun Dec 02 19:51:29 2012 -0800
@@ -295,7 +295,8 @@
int si_attr; /* attributes in this state */
long si_flags; /* HL_HAS_EOL flag in this state,
* HL_SKIP* for si_next_list, and
- * HL_MODIFIER for modifiers */
+ * HL_MODIFIER and HL_INVERSE for
+ * modifiers */
#ifdef FEAT_CONCEAL
int si_seqnr; /* sequence number */
int si_cchar; /* substitution character for conceal */
@@ -1868,6 +1869,8 @@
short *next_list;
int found_match; /* found usable match */
int applied_modifier; /* Applied a syntax modifier */
+ int blocked_attr; /* Attributes blocked from turning
+ * on */
static int try_next_column = FALSE; /* must try in next col */
int do_keywords;
regmmatch_T regmatch;
@@ -2291,6 +2294,7 @@
* If not, use attributes from the current-but-one state, etc.
*/
current_attr = 0;
+ blocked_attr = 0;
applied_modifier = FALSE;
#ifdef FEAT_EVAL
@@ -2329,11 +2333,17 @@
#endif
}
- if (applied_modifier)
- current_attr = hl_combine_attr(sip->si_attr, current_attr);
+ if (sip->si_flags & HL_RMATTRS)
+ blocked_attr = hl_combine_attr(blocked_attr, sip->si_attr);
+
+ if (applied_modifier || sip->si_flags & HL_RMATTRS)
+ current_attr = hl_combine_attr(
+ hl_block_attr(sip->si_attr, blocked_attr),
+ current_attr);
else
current_attr = sip->si_attr;
- if (sip->si_flags & HL_MODIFIER)
+
+ if (sip->si_flags & (HL_MODIFIER | HL_RMATTRS))
applied_modifier = TRUE;
else
break;
@@ -3934,6 +3944,7 @@
{HL_TRANSP, "transparent"},
{HL_FOLD, "fold"},
{HL_MODIFIER, "modifier"},
+ {HL_RMATTRS, "removeattrs"},
#ifdef FEAT_CONCEAL
{HL_CONCEAL, "conceal"},
{HL_CONCEALENDS, "concealends"},
@@ -4488,12 +4499,13 @@
{"cCoOnNcCeEaAlL", 0, HL_CONCEAL},
{"cCoOnNcCeEaAlLeEnNdDsS", 0, HL_CONCEALENDS},
{"mMoOdDiIfFiIeErR", 0, HL_MODIFIER},
+ {"rReEmMoOvVeEaAtTtTrRsS", 0, HL_RMATTRS},
{"cCcChHaArR", 11, 0},
{"cCoOnNtTaAiInNsS", 1, 0},
{"cCoOnNtTaAiInNeEdDiInN", 2, 0},
{"nNeExXtTgGrRoOuUpP", 3, 0},
};
- static char *first_letters = "cCoOkKeEtTsSgGdDfFnNmM";
+ static char *first_letters = "cCoOkKeEtTsSgGdDfFnNmMrR";
if (arg == NULL) /* already detected error */
return NULL;
@@ -8531,6 +8543,126 @@
}
return get_attr_entry(&term_attr_table, &new_en);
}
+/*
+ * Return char_attr with all terminal attributes (bold, italic, etc.)
+ * that are on in block_attr turned off.
+ * This creates a new group when required.
+ * Since we expect attr removers to be rare we don't cache the result.
+ */
+ int
+hl_block_attr(char_attr, block_attr)
+ int char_attr;
+ int block_attr;
+{
+ attrentry_T *char_aep = NULL;
+ attrentry_T *block_aep;
+ attrentry_T new_en;
+
+ if (char_attr == 0)
+ return 0;
+ if (char_attr <= HL_ALL && block_attr <= HL_ALL)
+ return char_attr & ~block_attr;
+#ifdef FEAT_GUI
+ if (gui.in_use)
+ {
+ if (char_attr > HL_ALL)
+ char_aep = syn_gui_attr2entry(char_attr);
+ if (char_aep != NULL)
+ new_en = *char_aep;
+ else
+ {
+ vim_memset(&new_en, 0, sizeof(new_en));
+ new_en.ae_u.gui.fg_color = INVALCOLOR;
+ new_en.ae_u.gui.bg_color = INVALCOLOR;
+ new_en.ae_u.gui.sp_color = INVALCOLOR;
+ if (char_attr <= HL_ALL)
+ new_en.ae_attr = char_attr;
+ }
+
+ if (block_attr <= HL_ALL)
+ new_en.ae_attr &= ~block_attr;
+ else
+ {
+ block_aep = syn_gui_attr2entry(block_attr);
+ if (block_aep != NULL)
+ {
+ new_en.ae_attr &= ~block_aep->ae_attr;
+ if (block_aep->ae_u.gui.fg_color != INVALCOLOR)
+ new_en.ae_u.gui.fg_color = block_aep->ae_u.gui.fg_color;
+ if (block_aep->ae_u.gui.bg_color != INVALCOLOR)
+ new_en.ae_u.gui.bg_color = block_aep->ae_u.gui.bg_color;
+ if (block_aep->ae_u.gui.sp_color != INVALCOLOR)
+ new_en.ae_u.gui.sp_color = block_aep->ae_u.gui.sp_color;
+ if (block_aep->ae_u.gui.font != NOFONT)
+ new_en.ae_u.gui.font = block_aep->ae_u.gui.font;
+# ifdef FEAT_XFONTSET
+ if (block_aep->ae_u.gui.fontset != NOFONTSET)
+ new_en.ae_u.gui.fontset = block_aep->ae_u.gui.fontset;
+# endif
+ }
+ }
+ return get_attr_entry(&gui_attr_table, &new_en);
+ }
+#endif
+
+ if (t_colors > 1)
+ {
+ if (char_attr > HL_ALL)
+ char_aep = syn_cterm_attr2entry(char_attr);
+ if (char_aep != NULL)
+ new_en = *char_aep;
+ else
+ {
+ vim_memset(&new_en, 0, sizeof(new_en));
+ if (char_attr <= HL_ALL)
+ new_en.ae_attr = char_attr;
+ }
+
+ if (block_attr <= HL_ALL)
+ new_en.ae_attr &= ~block_attr;
+ else
+ {
+ block_aep = syn_cterm_attr2entry(block_attr);
+ if (block_aep != NULL)
+ {
+ new_en.ae_attr &= ~block_aep->ae_attr;
+ if (block_aep->ae_u.cterm.fg_color > 0)
+ new_en.ae_u.cterm.fg_color = block_aep->ae_u.cterm.fg_color;
+ if (block_aep->ae_u.cterm.bg_color > 0)
+ new_en.ae_u.cterm.bg_color = block_aep->ae_u.cterm.bg_color;
+ }
+ }
+ return get_attr_entry(&cterm_attr_table, &new_en);
+ }
+
+ if (char_attr > HL_ALL)
+ char_aep = syn_term_attr2entry(char_attr);
+ if (char_aep != NULL)
+ new_en = *char_aep;
+ else
+ {
+ vim_memset(&new_en, 0, sizeof(new_en));
+ if (char_attr <= HL_ALL)
+ new_en.ae_attr = char_attr;
+ }
+
+ if (block_attr <= HL_ALL)
+ new_en.ae_attr &= ~block_attr;
+ else
+ {
+ block_aep = syn_term_attr2entry(block_attr);
+ if (block_aep != NULL)
+ {
+ new_en.ae_attr &= ~block_aep->ae_attr;
+ if (block_aep->ae_u.term.start != NULL)
+ {
+ new_en.ae_u.term.start = block_aep->ae_u.term.start;
+ new_en.ae_u.term.stop = block_aep->ae_u.term.stop;
+ }
+ }
+ }
+ return get_attr_entry(&term_attr_table, &new_en);
+}
#endif
#ifdef FEAT_GUI
diff -r 97220839b0b2 src/vim.h
--- a/src/vim.h Sun Dec 02 19:49:32 2012 -0800
+++ b/src/vim.h Sun Dec 02 19:51:29 2012 -0800
@@ -895,6 +895,7 @@
# define HL_CONCEAL 0x20000 /* can be concealed */
# define HL_CONCEALENDS 0x40000 /* can be concealed */
# define HL_MODIFIER 0x80000 /* modifies attributes instead of clobbering */
+# define HL_RMATTRS 0x100000 /* removes terminal attributes */
#endif
/* Values for 'options' argument in do_search() and searchit() */