Skip to content

Commit e413ea0

Browse files
committed
patch 8.2.3664: cannot adjust sign highlighting for 'cursorline'
Problem: Cannot adjust sign highlighting for 'cursorline'. Solution: Add CursorLineSign and CursorLineFold highlight groups. (Gregory Anders, closes #9201)
1 parent 1f2453f commit e413ea0

File tree

12 files changed

+104
-18
lines changed

12 files changed

+104
-18
lines changed

runtime/doc/sign.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ The color of the column is set with the SignColumn highlight group
5353
5454
:highlight SignColumn guibg=darkgrey
5555
<
56+
If 'cursorline' is enabled, then the CursorLineSign highlight group is used
57+
|hl-CursorLineSign|.
5658
*sign-identifier*
5759
Each placed sign is identified by a number called the sign identifier. This
5860
identifier is used to jump to the sign or to remove the sign. The identifier
@@ -171,6 +173,13 @@ See |sign_getdefined()| for the equivalent Vim script function.
171173
:sign list {name}
172174
Lists one defined sign and its attributes.
173175

176+
culhl={group}
177+
Highlighting group used for the text item when the cursor is
178+
on the same line as the sign and 'cursorline' is enabled.
179+
180+
Example: >
181+
:sign define MySign text=>> texthl=Search linehl=DiffText
182+
<
174183

175184
PLACING SIGNS *:sign-place* *E158*
176185

@@ -393,6 +402,9 @@ sign_define({list})
393402
text text that is displayed when there is no icon
394403
or the GUI is not being used.
395404
texthl highlight group used for the text item
405+
culhl highlight group used for the text item when
406+
the cursor is on the same line as the sign and
407+
'cursorline' is enabled.
396408

397409
If the sign named {name} already exists, then the attributes
398410
of the sign are updated.
@@ -437,6 +449,9 @@ sign_getdefined([{name}]) *sign_getdefined()*
437449
text text that is displayed when there is no icon
438450
or the GUI is not being used.
439451
texthl highlight group used for the text item
452+
culhl highlight group used for the text item when
453+
the cursor is on the same line as the sign and
454+
'cursorline' is enabled.
440455

441456
Returns an empty List if there are no signs and when {name} is
442457
not found.

runtime/doc/syntax.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5251,6 +5251,10 @@ LineNrBelow Line number for when the 'relativenumber'
52515251
*hl-CursorLineNr*
52525252
CursorLineNr Like LineNr when 'cursorline' is set and 'cursorlineopt'
52535253
contains "number" or is "both", for the cursor line.
5254+
*hl-CursorLineSign*
5255+
CursorLineSign Like SignColumn when 'cursorline' is set for the cursor line.
5256+
*hl-CursorLineFold*
5257+
CursorLineFold Like FoldColumn when 'cursorline' is set for the cursor line.
52545258
*hl-MatchParen*
52555259
MatchParen The character under the cursor or just before it, if it
52565260
is a paired bracket, and its match. |pi_paren.txt|

src/drawline.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ margin_columns_win(win_T *wp, int *left_col, int *right_col)
7676
#endif
7777

7878
#ifdef FEAT_SIGNS
79+
/*
80+
* Return TRUE if CursorLineSign highlight is to be used.
81+
*/
82+
static int
83+
use_cursor_line_sign(win_T *wp, linenr_T lnum)
84+
{
85+
return wp->w_p_cul
86+
&& lnum == wp->w_cursor.lnum
87+
&& (wp->w_p_culopt_flags & CULOPT_NBR);
88+
}
89+
7990
/*
8091
* Get information needed to display the sign in line 'lnum' in window 'wp'.
8192
* If 'nrcol' is TRUE, the sign is going to be displayed in the number column.
@@ -85,7 +96,7 @@ margin_columns_win(win_T *wp, int *left_col, int *right_col)
8596
get_sign_display_info(
8697
int nrcol,
8798
win_T *wp,
88-
linenr_T lnum UNUSED,
99+
linenr_T lnum,
89100
sign_attrs_T *sattr,
90101
int wcr_attr,
91102
int row,
@@ -111,7 +122,10 @@ get_sign_display_info(
111122
*n_extrap = number_width(wp) + 1;
112123
else
113124
{
114-
*char_attrp = hl_combine_attr(wcr_attr, HL_ATTR(HLF_SC));
125+
if (use_cursor_line_sign(wp, lnum))
126+
*char_attrp = hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLS));
127+
else
128+
*char_attrp = hl_combine_attr(wcr_attr, HL_ATTR(HLF_SC));
115129
*n_extrap = 2;
116130
}
117131

@@ -176,7 +190,11 @@ get_sign_display_info(
176190
*c_finalp = NUL;
177191
*n_extrap = (int)STRLEN(*pp_extra);
178192
}
179-
*char_attrp = sattr->sat_texthl;
193+
194+
if (use_cursor_line_sign(wp, lnum) && sattr->sat_culhl > 0)
195+
*char_attrp = sattr->sat_culhl;
196+
else
197+
*char_attrp = sattr->sat_texthl;
180198
}
181199
}
182200
}
@@ -1051,7 +1069,12 @@ win_line(
10511069
p_extra = p_extra_free;
10521070
c_extra = NUL;
10531071
c_final = NUL;
1054-
char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_FC));
1072+
if (use_cursor_line_sign(wp, lnum))
1073+
char_attr =
1074+
hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLF));
1075+
else
1076+
char_attr =
1077+
hl_combine_attr(wcr_attr, HL_ATTR(HLF_FC));
10551078
}
10561079
}
10571080
}

src/highlight.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ static char *(highlight_init_both[]) = {
153153
"lCursor guibg=fg guifg=bg", // should be different, but what?
154154
#endif
155155
"default link QuickFixLine Search",
156+
"default link CursorLineSign SignColumn",
157+
"default link CursorLineFold FoldColumn",
156158
CENT("Normal cterm=NONE", "Normal gui=NONE"),
157159
NULL
158160
};

src/optiondefs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ struct vimoption
298298
# define ISP_LATIN1 (char_u *)"@,161-255"
299299
#endif
300300

301-
# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC"
301+
# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC"
302302

303303
// Default python version for pyx* commands
304304
#if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)

src/popupwin.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ popup_highlight_curline(win_T *wp)
632632

633633
if (syn_name2id((char_u *)linehl) == 0)
634634
linehl = "PmenuSel";
635-
sign_define_by_name(sign_name, NULL, (char_u *)linehl, NULL, NULL);
635+
sign_define_by_name(sign_name, NULL, (char_u *)linehl, NULL, NULL, NULL);
636636
}
637637

638638
sign_place(&sign_id, (char_u *)"PopUpMenu", sign_name,

src/proto/sign.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ int buf_findsigntype_id(buf_T *buf, linenr_T lnum, int typenr);
88
int buf_signcount(buf_T *buf, linenr_T lnum);
99
void buf_delete_signs(buf_T *buf, char_u *group);
1010
void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after);
11-
int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl);
11+
int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl, char_u *culhl);
1212
int sign_exists_by_name(char_u *name);
1313
int sign_undefine_by_name(char_u *name, int give_error);
1414
int sign_place(int *sign_id, char_u *sign_group, char_u *sign_name, buf_T *buf, linenr_T lnum, int prio);

src/sign.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct sign
3232
char_u *sn_text; // text used instead of pixmap
3333
int sn_line_hl; // highlight ID for line
3434
int sn_text_hl; // highlight ID for text
35+
int sn_cul_hl; // highlight ID for text on current line when 'cursorline' is set
3536
};
3637

3738
static sign_T *first_sign = NULL;
@@ -517,6 +518,8 @@ buf_get_signattrs(win_T *wp, linenr_T lnum, sign_attrs_T *sattr)
517518
sattr->sat_texthl = syn_id2attr(sp->sn_text_hl);
518519
if (sp->sn_line_hl > 0)
519520
sattr->sat_linehl = syn_id2attr(sp->sn_line_hl);
521+
if (sp->sn_cul_hl > 0)
522+
sattr->sat_culhl = syn_id2attr(sp->sn_cul_hl);
520523
sattr->sat_priority = sign->se_priority;
521524

522525
// If there is another sign next with the same priority, may
@@ -540,6 +543,8 @@ buf_get_signattrs(win_T *wp, linenr_T lnum, sign_attrs_T *sattr)
540543
sattr->sat_texthl = syn_id2attr(next_sp->sn_text_hl);
541544
if (sp->sn_line_hl <= 0 && next_sp->sn_line_hl > 0)
542545
sattr->sat_linehl = syn_id2attr(next_sp->sn_line_hl);
546+
if (sp->sn_cul_hl <= 0 && next_sp->sn_cul_hl > 0)
547+
sattr->sat_culhl = syn_id2attr(next_sp->sn_cul_hl);
543548
}
544549
}
545550
return TRUE;
@@ -1035,7 +1040,8 @@ sign_define_by_name(
10351040
char_u *icon,
10361041
char_u *linehl,
10371042
char_u *text,
1038-
char_u *texthl)
1043+
char_u *texthl,
1044+
char_u *culhl)
10391045
{
10401046
sign_T *sp_prev;
10411047
sign_T *sp;
@@ -1077,6 +1083,9 @@ sign_define_by_name(
10771083
if (texthl != NULL)
10781084
sp->sn_text_hl = syn_check_group(texthl, (int)STRLEN(texthl));
10791085

1086+
if (culhl != NULL)
1087+
sp->sn_cul_hl = syn_check_group(culhl, (int)STRLEN(culhl));
1088+
10801089
return OK;
10811090
}
10821091

@@ -1298,6 +1307,7 @@ sign_define_cmd(char_u *sign_name, char_u *cmdline)
12981307
char_u *text = NULL;
12991308
char_u *linehl = NULL;
13001309
char_u *texthl = NULL;
1310+
char_u *culhl = NULL;
13011311
int failed = FALSE;
13021312

13031313
// set values for a defined sign.
@@ -1327,6 +1337,11 @@ sign_define_cmd(char_u *sign_name, char_u *cmdline)
13271337
arg += 7;
13281338
texthl = vim_strnsave(arg, p - arg);
13291339
}
1340+
else if (STRNCMP(arg, "culhl=", 6) == 0)
1341+
{
1342+
arg += 6;
1343+
culhl = vim_strnsave(arg, p - arg);
1344+
}
13301345
else
13311346
{
13321347
semsg(_(e_invarg2), arg);
@@ -1336,12 +1351,13 @@ sign_define_cmd(char_u *sign_name, char_u *cmdline)
13361351
}
13371352

13381353
if (!failed)
1339-
sign_define_by_name(sign_name, icon, linehl, text, texthl);
1354+
sign_define_by_name(sign_name, icon, linehl, text, texthl, culhl);
13401355

13411356
vim_free(icon);
13421357
vim_free(text);
13431358
vim_free(linehl);
13441359
vim_free(texthl);
1360+
vim_free(culhl);
13451361
}
13461362

13471363
/*
@@ -1712,6 +1728,13 @@ sign_getinfo(sign_T *sp, dict_T *retdict)
17121728
p = (char_u *)"NONE";
17131729
dict_add_string(retdict, "texthl", (char_u *)p);
17141730
}
1731+
if (sp->sn_cul_hl > 0)
1732+
{
1733+
p = get_highlight_name_ext(NULL, sp->sn_cul_hl - 1, FALSE);
1734+
if (p == NULL)
1735+
p = (char_u *)"NONE";
1736+
dict_add_string(retdict, "culhl", (char_u *)p);
1737+
}
17151738
}
17161739

17171740
/*
@@ -1883,6 +1906,15 @@ sign_list_defined(sign_T *sp)
18831906
else
18841907
msg_puts((char *)p);
18851908
}
1909+
if (sp->sn_cul_hl > 0)
1910+
{
1911+
msg_puts(" culhl=");
1912+
p = get_highlight_name_ext(NULL, sp->sn_cul_hl - 1, FALSE);
1913+
if (p == NULL)
1914+
msg_puts("NONE");
1915+
else
1916+
msg_puts((char *)p);
1917+
}
18861918
}
18871919

18881920
/*
@@ -2173,6 +2205,7 @@ sign_define_from_dict(char_u *name_arg, dict_T *dict)
21732205
char_u *linehl = NULL;
21742206
char_u *text = NULL;
21752207
char_u *texthl = NULL;
2208+
char_u *culhl = NULL;
21762209
int retval = -1;
21772210

21782211
if (name_arg == NULL)
@@ -2191,9 +2224,10 @@ sign_define_from_dict(char_u *name_arg, dict_T *dict)
21912224
linehl = dict_get_string(dict, (char_u *)"linehl", TRUE);
21922225
text = dict_get_string(dict, (char_u *)"text", TRUE);
21932226
texthl = dict_get_string(dict, (char_u *)"texthl", TRUE);
2227+
culhl = dict_get_string(dict, (char_u *)"culhl", TRUE);
21942228
}
21952229

2196-
if (sign_define_by_name(name, icon, linehl, text, texthl) == OK)
2230+
if (sign_define_by_name(name, icon, linehl, text, texthl, culhl) == OK)
21972231
retval = 0;
21982232

21992233
cleanup:
@@ -2202,6 +2236,7 @@ sign_define_from_dict(char_u *name_arg, dict_T *dict)
22022236
vim_free(linehl);
22032237
vim_free(text);
22042238
vim_free(texthl);
2239+
vim_free(culhl);
22052240

22062241
return retval;
22072242
}

src/structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,7 @@ typedef struct sign_attrs_S {
853853
char_u *sat_text;
854854
int sat_texthl;
855855
int sat_linehl;
856+
int sat_culhl;
856857
int sat_priority;
857858
} sign_attrs_T;
858859

src/testdir/test_signs.vim

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ func Test_sign()
1515
" the icon name when listing signs.
1616
sign define Sign1 text=x
1717

18-
call Sign_command_ignore_error('sign define Sign2 text=xy texthl=Title linehl=Error icon=../../pixmaps/stock_vim_find_help.png')
18+
call Sign_command_ignore_error('sign define Sign2 text=xy texthl=Title linehl=Error culhl=Search icon=../../pixmaps/stock_vim_find_help.png')
1919

2020
" Test listing signs.
2121
let a=execute('sign list')
2222
call assert_match('^\nsign Sign1 text=x \nsign Sign2 ' .
2323
\ 'icon=../../pixmaps/stock_vim_find_help.png .*text=xy ' .
24-
\ 'linehl=Error texthl=Title$', a)
24+
\ 'linehl=Error texthl=Title culhl=Search$', a)
2525

2626
let a=execute('sign list Sign1')
2727
call assert_equal("\nsign Sign1 text=x ", a)
@@ -392,19 +392,21 @@ func Test_sign_funcs()
392392
call sign_undefine()
393393

394394
" Tests for sign_define()
395-
let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
395+
let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error',
396+
\ 'culhl': 'Visual'}
396397
call assert_equal(0, "sign1"->sign_define(attr))
397398
call assert_equal([{'name' : 'sign1', 'texthl' : 'Error',
398-
\ 'linehl' : 'Search', 'text' : '=>'}], sign_getdefined())
399+
\ 'linehl' : 'Search', 'culhl' : 'Visual', 'text' : '=>'}],
400+
\ sign_getdefined())
399401

400402
" Define a new sign without attributes and then update it
401403
call sign_define("sign2")
402404
let attr = {'text' : '!!', 'linehl' : 'DiffAdd', 'texthl' : 'DiffChange',
403-
\ 'icon' : 'sign2.ico'}
405+
\ 'culhl': 'DiffDelete', 'icon' : 'sign2.ico'}
404406
call Sign_define_ignore_error("sign2", attr)
405407
call assert_equal([{'name' : 'sign2', 'texthl' : 'DiffChange',
406-
\ 'linehl' : 'DiffAdd', 'text' : '!!', 'icon' : 'sign2.ico'}],
407-
\ "sign2"->sign_getdefined())
408+
\ 'linehl' : 'DiffAdd', 'culhl' : 'DiffDelete', 'text' : '!!',
409+
\ 'icon' : 'sign2.ico'}], "sign2"->sign_getdefined())
408410

409411
" Test for a sign name with digits
410412
call assert_equal(0, sign_define(0002, {'linehl' : 'StatusLine'}))

0 commit comments

Comments
 (0)