# HG changeset patch # User Bram Moolenaar # Date 1600365607 -7200 # Node ID 19e0784ef76916f0c6816cf123fd971711822b76 # Parent f43d6cbbaa5b3218a720fdf335814b1e0586b032 patch 8.2.1703: ":highlight clear" does not restore default link Commit: https://github.com/vim/vim/commit/213da551dec465e193619684b260bf9d5a8d6afc Author: Bram Moolenaar Date: Thu Sep 17 19:59:26 2020 +0200 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 #6970, closes #4405) diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -4809,6 +4809,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 diff --git a/src/highlight.c b/src/highlight.c --- a/src/highlight.c +++ b/src/highlight.c @@ -73,6 +73,7 @@ typedef struct char_u *sg_gui_sp_name;// GUI special color name #endif int sg_link; // link to this highlight group ID + int sg_deflink; // default link; restored in highlight_clear() int sg_set; // combination of SG_* flags #ifdef FEAT_EVAL sctx_T sg_script_ctx; // script in which the group was last set @@ -715,6 +716,7 @@ do_highlight( char_u *to_end; int from_id; int to_id; + hl_group_T *hlgroup = NULL; from_end = skiptowhite(from_start); to_start = skipwhite(from_end); @@ -740,7 +742,14 @@ do_highlight( else to_id = syn_check_group(to_start, (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 @@ -752,21 +761,20 @@ do_highlight( if (SOURCING_NAME == NULL && !dodefault) emsg(_("E414: group has settings, highlight link ignored")); } - else if (HL_TABLE()[from_id - 1].sg_link != to_id + else if (hlgroup->sg_link != to_id #ifdef FEAT_EVAL - || HL_TABLE()[from_id - 1].sg_script_ctx.sc_sid - != current_sctx.sc_sid + || hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid #endif - || HL_TABLE()[from_id - 1].sg_cleared) + || hlgroup->sg_cleared) { if (!init) - HL_TABLE()[from_id - 1].sg_set |= SG_LINK; - HL_TABLE()[from_id - 1].sg_link = to_id; + hlgroup->sg_set |= SG_LINK; + hlgroup->sg_link = to_id; #ifdef FEAT_EVAL - HL_TABLE()[from_id - 1].sg_script_ctx = current_sctx; - HL_TABLE()[from_id - 1].sg_script_ctx.sc_lnum += SOURCING_LNUM; + hlgroup->sg_script_ctx = current_sctx; + hlgroup->sg_script_ctx.sc_lnum += SOURCING_LNUM; #endif - HL_TABLE()[from_id - 1].sg_cleared = FALSE; + hlgroup->sg_cleared = FALSE; redraw_all_later(SOME_VALID); // Only call highlight_changed() once after multiple changes. @@ -1684,6 +1692,8 @@ highlight_clear(int idx) HL_TABLE()[idx].sg_gui_attr = 0; #endif #ifdef FEAT_EVAL + // 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) diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim --- a/src/testdir/test_highlight.vim +++ b/src/testdir/test_highlight.vim @@ -832,10 +832,47 @@ func Test_highlight_term_attr() 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') @@ -846,19 +883,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 diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1703, +/**/ 1702, /**/ 1701,