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() */

Raspunde prin e-mail lui