changeset 22308:19e0784ef769 v8.2.1703

patch 8.2.1703: ":highlight clear" does not restore default link Commit: https://github.com/vim/vim/commit/213da551dec465e193619684b260bf9d5a8d6afc Author: Bram Moolenaar <Bram@vim.org> 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)
author Bram Moolenaar <Bram@vim.org>
date Thu, 17 Sep 2020 20:00:07 +0200
parents f43d6cbbaa5b
children 59a0d8be7c65
files runtime/doc/syntax.txt src/highlight.c src/testdir/test_highlight.vim src/version.c
diffstat 4 files changed, 66 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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)
--- 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
--- 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,