> I like the idea, but I would prefer to use += and -=, just like :set.
Done.
> Also, can you write a test for correct behavior?
Added += and -= tests to test51.
I've split the "src/" diff into a "src/syntax.c" diff and a "src/testdir/"
diff. Let me know if you prefer the diffs split up differently in the future.
> The documentation should mention what happens when trying to remove a
>
> value that isn't there. Is it a warning, error, or ignored?
It's ignored. I think this is the correct behavior, it allows you to do
highlight Unbold term-=bold
and apply it to any syntax group without worrying about whether or not it will
apply.
Docs have been updated.
> The error for unexpected plus sign should be put in a function instead
>
> of writing that code several times.
I extracted it into a function. It's not the cleanest, because the block of
code has to set the local 'error' variable and do a break. I took the route of
least replication.
--
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 0d0dd54bb0be runtime/doc/syntax.txt
--- a/runtime/doc/syntax.txt Sun Dec 02 01:21:06 2012 -0800
+++ b/runtime/doc/syntax.txt Sun Dec 02 10:31:03 2012 -0800
@@ -4337,6 +4337,8 @@
*bold* *underline* *undercurl*
*inverse* *italic* *standout*
term={attr-list} *attr-list* *highlight-term* *E418*
+term+={attr-list}
+term-={attr-list}
attr-list is a comma separated list (without spaces) of the
following items (in any order):
bold
@@ -4354,6 +4356,18 @@
then "underline" is used. In general "undercurl" is only available in
the GUI. The color is set with |highlight-guisp|.
+ If += is used {attr-list} is appended to any previously set attr
+ list for the syntax group. For example >
+
+ highlight Comment term=underline termfg=green
+ highlight Comment term+=italic
+
+ < makes the Comment group use both bold and italic.
+
+ Similarly, -= can be used to remove attributes from existing
+ attribute lists. Removing an attribute that is not present has no
+ effect.
+
start={term-list} *highlight-start* *E422*
stop={term-list} *term-list* *highlight-stop*
These lists of terminal codes can be used to get
@@ -4386,6 +4400,8 @@
2. highlight arguments for color terminals
cterm={attr-list} *highlight-cterm*
+cterm+={atttr-list}
+cterm-={atttr-list}
See above for the description of {attr-list} |attr-list|.
The "cterm" argument is likely to be different from "term", when
colors are used. For example, in a normal terminal comments could
@@ -4483,6 +4499,8 @@
3. highlight arguments for the GUI
gui={attr-list} *highlight-gui*
+gui+={attr-list}
+gui-={attr-list}
These give the attributes to use in the GUI mode.
See |attr-list| for a description.
Note that "bold" can be used here and by using a bold font. They
diff -r 0d0dd54bb0be runtime/syntax/vim.vim
--- a/runtime/syntax/vim.vim Sun Dec 02 01:21:06 2012 -0800
+++ b/runtime/syntax/vim.vim Sun Dec 02 10:31:03 2012 -0800
@@ -509,10 +509,13 @@
syn match vimHiKeyError contained "\i\+="he=e-1
endif
syn match vimHiTerm contained "\cterm="he=e-1 nextgroup=vimHiAttribList
+syn match vimHiTerm contained "\cterm[+-]="he=e-2 nextgroup=vimHiAttribList
syn match vimHiStartStop contained "\c\(start\|stop\)="he=e-1 nextgroup=vimHiTermcap,vimOption
syn match vimHiCTerm contained "\ccterm="he=e-1 nextgroup=vimHiAttribList
+syn match vimHiCTerm contained "\ccterm[+-]="he=e-2 nextgroup=vimHiAttribList
syn match vimHiCtermFgBg contained "\ccterm[fb]g="he=e-1 nextgroup=vimHiNmbr,vimHiCtermColor,vimFgBgAttrib,vimHiCtermError
syn match vimHiGui contained "\cgui="he=e-1 nextgroup=vimHiAttribList
+syn match vimHiGui contained "\cgui[+-]="he=e-2 nextgroup=vimHiAttribList
syn match vimHiGuiFont contained "\cfont="he=e-1 nextgroup=vimHiFontname
syn match vimHiGuiFgBg contained "\cgui\%([fb]g\|sp\)="he=e-1 nextgroup=vimHiGroup,vimHiGuiFontname,vimHiGuiRgb,vimFgBgAttrib
syn match vimHiTermcap contained "\S\+" contains=vimNotation
diff -r 0d0dd54bb0be src/testdir/test51.in
--- a/src/testdir/test51.in Sun Dec 02 01:21:06 2012 -0800
+++ b/src/testdir/test51.in Sun Dec 02 10:34:05 2012 -0800
@@ -10,10 +10,19 @@
:hi NewGroup term=bold cterm=italic ctermfg=DarkBlue ctermbg=Grey gui= guifg=#00ff00 guibg=Cyan
:hi Group2 term= cterm=
:hi Group3 term=underline cterm=bold
+:hi Group4 term=bold
+:hi Group4 term+=italic
+:hi Group5 term=underline,italic
+:hi Group5 term-=underline
+:hi Group6 term=bold
+:hi Group6 term+=italic term-=bold
:redir! >test.out
:hi NewGroup
:hi Group2
:hi Group3
+:hi Group4
+:hi Group5
+:hi Group6
:hi clear NewGroup
:hi NewGroup
:hi Group2
diff -r 0d0dd54bb0be src/testdir/test51.ok
--- a/src/testdir/test51.ok Sun Dec 02 01:21:06 2012 -0800
+++ b/src/testdir/test51.ok Sun Dec 02 10:34:05 2012 -0800
@@ -6,6 +6,12 @@
Group3 xxx term=underline cterm=bold
+Group4 xxx term=bold,italic
+
+Group5 xxx term=italic
+
+Group6 xxx term=italic
+
NewGroup xxx cleared
diff -r 538ff809ae53 src/syntax.c
--- a/src/syntax.c Thu Nov 29 20:10:00 2012 +0100
+++ b/src/syntax.c Sun Dec 02 11:06:33 2012 -0800
@@ -64,6 +64,10 @@
#define SG_GUI 4 /* gui has been set */
#define SG_LINK 8 /* link has been set */
+#define ATTR_SET 1 /* Set attributes. */
+#define ATTR_ADD 2 /* Add attributes. */
+#define ATTR_REMOVE 3 /* Remove attributes. */
+
static garray_T highlight_ga; /* highlight groups for 'highlight' option */
#define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data)))
@@ -6849,6 +6853,7 @@
int attr;
int id;
int idx;
+ int attrmode;
int dodefault = FALSE;
int doclear = FALSE;
int dolink = FALSE;
@@ -7089,9 +7094,9 @@
while (!ends_excmd(*linep))
{
key_start = linep;
- if (*linep == '=')
- {
- EMSG2(_("E415: unexpected equal sign: %s"), key_start);
+ if (*linep == '+' || *linep == '-' || *linep == '=')
+ {
+ EMSG2(_("E415: unexpected operator: %s"), key_start);
error = TRUE;
break;
}
@@ -7100,7 +7105,8 @@
* Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg" or
* "guibg").
*/
- while (*linep && !vim_iswhite(*linep) && *linep != '=')
+ while (*linep && !vim_iswhite(*linep)
+ && *linep != '=' && *linep != '+' && *linep != '-')
++linep;
vim_free(key);
key = vim_strnsave_up(key_start, (int)(linep - key_start));
@@ -7123,15 +7129,29 @@
}
/*
- * Check for the equal sign.
+ * Check for the operator.
*/
- if (*linep != '=')
- {
- EMSG2(_("E416: missing equal sign: %s"), key_start);
+ if (STRNCMP(linep, "+=", 2) == 0)
+ {
+ attrmode = ATTR_ADD;
+ linep += 2;
+ }
+ else if (STRNCMP(linep, "-=", 2) == 0)
+ {
+ attrmode = ATTR_REMOVE;
+ linep += 2;
+ }
+ else if (*linep == '=')
+ {
+ attrmode = ATTR_SET;
+ ++linep;
+ }
+ else
+ {
+ EMSG2(_("E416: missing operator: %s"), key_start);
error = TRUE;
break;
}
- ++linep;
/*
* Isolate the argument.
@@ -7207,7 +7227,12 @@
{
if (!init)
HL_TABLE()[idx].sg_set |= SG_TERM;
- HL_TABLE()[idx].sg_term = attr;
+ if (attrmode == ATTR_ADD)
+ HL_TABLE()[idx].sg_term |= attr;
+ else if (attrmode == ATTR_REMOVE)
+ HL_TABLE()[idx].sg_term &= ~attr;
+ else
+ HL_TABLE()[idx].sg_term = attr;
}
}
else if (*key == 'C')
@@ -7216,7 +7241,12 @@
{
if (!init)
HL_TABLE()[idx].sg_set |= SG_CTERM;
- HL_TABLE()[idx].sg_cterm = attr;
+ if (attrmode == ATTR_ADD)
+ HL_TABLE()[idx].sg_cterm |= attr;
+ else if (attrmode == ATTR_REMOVE)
+ HL_TABLE()[idx].sg_cterm &= ~attr;
+ else
+ HL_TABLE()[idx].sg_cterm = attr;
HL_TABLE()[idx].sg_cterm_bold = FALSE;
}
}
@@ -7227,13 +7257,22 @@
{
if (!init)
HL_TABLE()[idx].sg_set |= SG_GUI;
- HL_TABLE()[idx].sg_gui = attr;
+ if (attrmode == ATTR_ADD)
+ HL_TABLE()[idx].sg_gui |= attr;
+ else if (attrmode == ATTR_REMOVE)
+ HL_TABLE()[idx].sg_gui &= ~attr;
+ else
+ HL_TABLE()[idx].sg_gui = attr;
}
}
#endif
}
else if (STRCMP(key, "FONT") == 0)
{
+ /* Fonts can not be combined. */
+ if (!require_set_operation(attrmode, key_start, &error))
+ break;
+
/* in non-GUI fonts are simply ignored */
#ifdef FEAT_GUI
if (!gui.shell_created)
@@ -7288,6 +7327,10 @@
}
else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0)
{
+ /* Colors can not be combined. */
+ if (!require_set_operation(attrmode, key_start, &error))
+ break;
+
if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM))
{
if (!init)
@@ -7494,6 +7537,10 @@
}
else if (STRCMP(key, "GUIFG") == 0)
{
+ /* Colors can not be combined. */
+ if (!require_set_operation(attrmode, key_start, &error))
+ break;
+
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
{
@@ -7531,6 +7578,10 @@
}
else if (STRCMP(key, "GUIBG") == 0)
{
+ /* Colors can not be combined. */
+ if (!require_set_operation(attrmode, key_start, &error))
+ break;
+
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
{
@@ -7568,6 +7619,10 @@
}
else if (STRCMP(key, "GUISP") == 0)
{
+ /* Colors can not be combined. */
+ if (!require_set_operation(attrmode, key_start, &error))
+ break;
+
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
{
@@ -7593,6 +7648,9 @@
}
else if (STRCMP(key, "START") == 0 || STRCMP(key, "STOP") == 0)
{
+ if (!require_set_operation(attrmode, key_start, &error))
+ break;
+
char_u buf[100];
char_u *tname;
@@ -7748,6 +7806,17 @@
need_highlight_changed = TRUE;
}
+int
+require_set_operation(int attrmode, char* context, int *error)
+{
+ if (attrmode != ATTR_SET)
+ {
+ EMSG2(_("E415: invalid operator: %s"), context);
+ *error = TRUE;
+ }
+ return attrmode == ATTR_SET;
+}
+
#if defined(EXITFREE) || defined(PROTO)
void
free_highlight()