vim-patch:8.2.1703: ":highlight clear" does not restore default link

Problem:    ":highlight clear" does not restore default link.
Solution:   Remember the default link and restore it. (Antony Scriven,
            closes vim/vim#6970, closes vim/vim#4405)
213da551de
This commit is contained in:
Andy K. Massimino 2021-03-04 00:58:07 -05:00
parent 4e6b31d978
commit 8601e8b0d6
3 changed files with 64 additions and 19 deletions

View File

@ -4689,6 +4689,7 @@ in their own color.
highlighting for groups added by the user!
Uses the current value of 'background' to decide which
default colors to use.
If there was a default link, restore it. |:hi-link|
:hi[ghlight] clear {group-name}
:hi[ghlight] {group-name} NONE

View File

@ -59,6 +59,7 @@ struct hl_group {
bool sg_cleared; ///< "hi clear" was used
int sg_attr; ///< Screen attr @see ATTR_ENTRY
int sg_link; ///< link to this highlight group ID
int sg_deflink; ///< default link; restored in highlight_clear()
int sg_set; ///< combination of flags in \ref SG_SET
sctx_T sg_script_ctx; ///< script in which the group was last set
// for terminal UIs
@ -6601,6 +6602,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
const char *to_end;
int from_id;
int to_id;
struct hl_group *hlgroup = NULL;
from_end = (const char *)skiptowhite((const char_u *)from_start);
to_start = (const char *)skipwhite((const char_u *)from_end);
@ -6627,7 +6629,14 @@ void do_highlight(const char *line, const bool forceit, const bool init)
(int)(to_end - to_start));
}
if (from_id > 0 && (!init || HL_TABLE()[from_id - 1].sg_set == 0)) {
if (from_id > 0) {
hlgroup = &HL_TABLE()[from_id - 1];
if (dodefault && (forceit || hlgroup->sg_deflink == 0)) {
hlgroup->sg_deflink = to_id;
}
}
if (from_id > 0 && (!init || hlgroup->sg_set == 0)) {
// Don't allow a link when there already is some highlighting
// for the group, unless '!' is used
if (to_id > 0 && !forceit && !init
@ -6635,17 +6644,16 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (sourcing_name == NULL && !dodefault) {
EMSG(_("E414: group has settings, highlight link ignored"));
}
} else if (HL_TABLE()[from_id - 1].sg_link != to_id
|| HL_TABLE()[from_id - 1].sg_script_ctx.sc_sid
!= current_sctx.sc_sid
|| HL_TABLE()[from_id - 1].sg_cleared) {
} else if (hlgroup->sg_link != to_id
|| hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid
|| hlgroup->sg_cleared) {
if (!init) {
HL_TABLE()[from_id - 1].sg_set |= SG_LINK;
hlgroup->sg_set |= SG_LINK;
}
HL_TABLE()[from_id - 1].sg_link = to_id;
HL_TABLE()[from_id - 1].sg_script_ctx = current_sctx;
HL_TABLE()[from_id - 1].sg_script_ctx.sc_lnum += sourcing_lnum;
HL_TABLE()[from_id - 1].sg_cleared = false;
hlgroup->sg_link = to_id;
hlgroup->sg_script_ctx = current_sctx;
hlgroup->sg_script_ctx.sc_lnum += sourcing_lnum;
hlgroup->sg_cleared = false;
redraw_all_later(SOME_VALID);
// Only call highlight changed() once after multiple changes
@ -7106,6 +7114,8 @@ static void highlight_clear(int idx)
XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_bg_name);
XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_sp_name);
HL_TABLE()[idx].sg_blend = -1;
// Restore any default link.
HL_TABLE()[idx].sg_link = HL_TABLE()[idx].sg_deflink;
// Clear the script ID only when there is no link, since that is not
// cleared.
if (HL_TABLE()[idx].sg_link == 0) {

View File

@ -623,10 +623,47 @@ func Test_xxlast_highlight_RGB_color()
hi clear
endfunc
" Test default highlighting is restored
func Test_highlight_restore_defaults()
hi! link TestLink Identifier
hi! TestHi ctermbg=red
func Test_highlight_clear_restores_links()
let aaa_id = hlID('aaa')
call assert_equal(aaa_id, 0)
" create default link aaa --> bbb
hi def link aaa bbb
let id_aaa = hlID('aaa')
let hl_aaa_bbb = HighlightArgs('aaa')
" try to redefine default link aaa --> ccc; check aaa --> bbb
hi def link aaa ccc
call assert_equal(HighlightArgs('aaa'), hl_aaa_bbb)
" clear aaa; check aaa --> bbb
hi clear aaa
call assert_equal(HighlightArgs('aaa'), hl_aaa_bbb)
" link aaa --> ccc; clear aaa; check aaa --> bbb
hi link aaa ccc
let id_ccc = hlID('ccc')
call assert_equal(synIDtrans(id_aaa), id_ccc)
hi clear aaa
call assert_equal(HighlightArgs('aaa'), hl_aaa_bbb)
" forcibly set default link aaa --> ddd
hi! def link aaa ddd
let id_ddd = hlID('ddd')
let hl_aaa_ddd = HighlightArgs('aaa')
call assert_equal(synIDtrans(id_aaa), id_ddd)
" link aaa --> eee; clear aaa; check aaa --> ddd
hi link aaa eee
let eee_id = hlID('eee')
call assert_equal(synIDtrans(id_aaa), eee_id)
hi clear aaa
call assert_equal(HighlightArgs('aaa'), hl_aaa_ddd)
endfunc
func Test_highlight_default_colorscheme_restores_links()
hi link TestLink Identifier
hi TestHi ctermbg=red
let hlTestLinkPre = HighlightArgs('TestLink')
let hlTestHiPre = HighlightArgs('TestHi')
@ -637,19 +674,16 @@ func Test_highlight_restore_defaults()
syntax reset
endif
let g:colors_name = 'test'
hi! link TestLink ErrorMsg
hi! TestHi ctermbg=green
hi link TestLink ErrorMsg
hi TestHi ctermbg=green
" Restore default highlighting
colorscheme default
syntax on
" 'default' should work no matter if highlight group was cleared
hi def link TestLink Identifier
hi def TestHi ctermbg=red
let hlTestLinkPost = HighlightArgs('TestLink')
let hlTestHiPost = HighlightArgs('TestHi')
call assert_equal(hlTestLinkPre, hlTestLinkPost)
call assert_equal(hlTestHiPre, hlTestHiPost)
hi clear