From 4e6b31d978e95be631705dbfe994749c44520d47 Mon Sep 17 00:00:00 2001 From: "Andy K. Massimino" Date: Thu, 4 Mar 2021 00:39:40 -0500 Subject: [PATCH 1/4] vim-patch:8.2.1693: "hi def" does not work for cleared highlight Problem: "hi def" does not work for cleared highlight. Solution: Check the "sg_cleared" flag. (Maxim Kim, closes vim/vim#6956, closes vim/vim#4405) https://github.com/vim/vim/commit/05eb5b9cae123b138bbd23cc77e50657ece6b4ad --- src/nvim/syntax.c | 15 +++++++------- src/nvim/testdir/test_highlight.vim | 32 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 547d953be9..140d528e8d 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -7076,13 +7076,14 @@ void restore_cterm_colors(void) */ static int hl_has_settings(int idx, int check_link) { - return HL_TABLE()[idx].sg_attr != 0 - || HL_TABLE()[idx].sg_cterm_fg != 0 - || HL_TABLE()[idx].sg_cterm_bg != 0 - || HL_TABLE()[idx].sg_rgb_fg_name != NULL - || HL_TABLE()[idx].sg_rgb_bg_name != NULL - || HL_TABLE()[idx].sg_rgb_sp_name != NULL - || (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)); + return HL_TABLE()[idx].sg_cleared == 0 + && (HL_TABLE()[idx].sg_attr != 0 + || HL_TABLE()[idx].sg_cterm_fg != 0 + || HL_TABLE()[idx].sg_cterm_bg != 0 + || HL_TABLE()[idx].sg_rgb_fg_name != NULL + || HL_TABLE()[idx].sg_rgb_bg_name != NULL + || HL_TABLE()[idx].sg_rgb_sp_name != NULL + || (check_link && (HL_TABLE()[idx].sg_set & SG_LINK))); } /* diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim index 4cc4d775d1..631d19172f 100644 --- a/src/nvim/testdir/test_highlight.vim +++ b/src/nvim/testdir/test_highlight.vim @@ -623,4 +623,36 @@ 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 + + let hlTestLinkPre = HighlightArgs('TestLink') + let hlTestHiPre = HighlightArgs('TestHi') + + " Test colorscheme + hi clear + if exists('syntax_on') + syntax reset + endif + let g:colors_name = 'test' + 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 +endfunc + " vim: shiftwidth=2 sts=2 expandtab From 8601e8b0d628037d253b76de8aa524c6174f4af9 Mon Sep 17 00:00:00 2001 From: "Andy K. Massimino" Date: Thu, 4 Mar 2021 00:58:07 -0500 Subject: [PATCH 2/4] 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) https://github.com/vim/vim/commit/213da551dec465e193619684b260bf9d5a8d6afc --- runtime/doc/syntax.txt | 1 + src/nvim/syntax.c | 30 +++++++++++------ src/nvim/testdir/test_highlight.vim | 52 ++++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 19 deletions(-) diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index b45e9ed450..aeee02a1e0 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -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 diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 140d528e8d..9501093e21 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -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) { diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim index 631d19172f..e7ee42ecd6 100644 --- a/src/nvim/testdir/test_highlight.vim +++ b/src/nvim/testdir/test_highlight.vim @@ -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 From 7e89606591c76efc7587911ff6d9c3414525f2a2 Mon Sep 17 00:00:00 2001 From: "Andy K. Massimino" Date: Fri, 5 Mar 2021 00:03:08 -0500 Subject: [PATCH 3/4] vim-patch:8.2.1705: "verbose hi Name" reports incorrect info after ":hi clear" Problem: "verbose hi Name" reports incorrect info after ":hi clear". Solution: Store the script context. (Antony Scriven, closes vim/vim#6975) https://github.com/vim/vim/commit/e8df0104985af58ee501a6fbac8ac9f886e84e5a Also adds src/nvim/testdir/script_util.vim which originates from patch 8.2.1366 (https://github.com/vim/vim/commit/a6296200bd5191bab7efcdcc16c9e79eb498e8e0) because some tests in test_highlight.vim use it for testing :verbose. Should merge this and older related patches later. Also, fix collateral damage to test_options.vim test_options tests for file name completion in the test directory, but since we've added a new file, the test output is now different. This test is slightly different from upstream anyway, so for now we just add the file name. This may change when more upstream patches are added which alter this test. --- src/nvim/syntax.c | 14 +++--- src/nvim/testdir/script_util.vim | 69 +++++++++++++++++++++++++++++ src/nvim/testdir/test_highlight.vim | 34 ++++++++++++++ src/nvim/testdir/test_options.vim | 2 +- 4 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 src/nvim/testdir/script_util.vim diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 9501093e21..d204968c0f 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -61,6 +61,7 @@ struct hl_group { 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_deflink_sctx; ///< script where the default link was set sctx_T sg_script_ctx; ///< script in which the group was last set // for terminal UIs int sg_cterm; ///< "cterm=" highlighting attr @@ -6633,6 +6634,8 @@ void do_highlight(const char *line, const bool forceit, const bool init) hlgroup = &HL_TABLE()[from_id - 1]; if (dodefault && (forceit || hlgroup->sg_deflink == 0)) { hlgroup->sg_deflink = to_id; + hlgroup->sg_deflink_sctx = current_sctx; + hlgroup->sg_deflink_sctx.sc_lnum += sourcing_lnum; } } @@ -7114,14 +7117,11 @@ 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. + // Restore default link and context if they exist. Otherwise clears. 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) { - HL_TABLE()[idx].sg_script_ctx.sc_sid = 0; - HL_TABLE()[idx].sg_script_ctx.sc_lnum = 0; - } + // Since we set the default link, set the location to where the default + // link was set. + HL_TABLE()[idx].sg_script_ctx = HL_TABLE()[idx].sg_deflink_sctx; } diff --git a/src/nvim/testdir/script_util.vim b/src/nvim/testdir/script_util.vim new file mode 100644 index 0000000000..9913b1dfaf --- /dev/null +++ b/src/nvim/testdir/script_util.vim @@ -0,0 +1,69 @@ +" Functions shared by the tests for Vim Script + +" Commands to track the execution path of a script +com! XpathINIT let g:Xpath = '' +com! -nargs=1 -bar Xpath let g:Xpath ..= +com! XloopINIT let g:Xloop = 1 +com! -nargs=1 -bar Xloop let g:Xpath ..= .. g:Xloop +com! XloopNEXT let g:Xloop += 1 + +" MakeScript() - Make a script file from a function. {{{2 +" +" Create a script that consists of the body of the function a:funcname. +" Replace any ":return" by a ":finish", any argument variable by a global +" variable, and every ":call" by a ":source" for the next following argument +" in the variable argument list. This function is useful if similar tests are +" to be made for a ":return" from a function call or a ":finish" in a script +" file. +func MakeScript(funcname, ...) + let script = tempname() + execute "redir! >" . script + execute "function" a:funcname + redir END + execute "edit" script + " Delete the "function" and the "endfunction" lines. Do not include the + " word "function" in the pattern since it might be translated if LANG is + " set. When MakeScript() is being debugged, this deletes also the debugging + " output of its line 3 and 4. + exec '1,/.*' . a:funcname . '(.*)/d' + /^\d*\s*endfunction\>/,$d + %s/^\d*//e + %s/return/finish/e + %s/\ 0 + let cnt = cnt + 1 + s/\) + diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim index e7ee42ecd6..ce22de09ca 100644 --- a/src/nvim/testdir/test_highlight.vim +++ b/src/nvim/testdir/test_highlight.vim @@ -3,6 +3,7 @@ source view_util.vim source screendump.vim source check.vim +source script_util.vim func Test_highlight() " basic test if ":highlight" doesn't crash @@ -661,6 +662,39 @@ func Test_highlight_clear_restores_links() call assert_equal(HighlightArgs('aaa'), hl_aaa_ddd) endfunc +func Test_highlight_clear_restores_context() + func FuncContextDefault() + hi def link Context ContextDefault + endfun + + func FuncContextRelink() + " Dummy line + hi link Context ContextRelink + endfunc + + let scriptContextDefault = MakeScript("FuncContextDefault") + let scriptContextRelink = MakeScript("FuncContextRelink") + let patContextDefault = fnamemodify(scriptContextDefault, ':t') .. ' line 1' + let patContextRelink = fnamemodify(scriptContextRelink, ':t') .. ' line 2' + + exec "source" scriptContextDefault + let hlContextDefault = execute("verbose hi Context") + call assert_match(patContextDefault, hlContextDefault) + + exec "source" scriptContextRelink + let hlContextRelink = execute("verbose hi Context") + call assert_match(patContextRelink, hlContextRelink) + + hi clear + let hlContextAfterClear = execute("verbose hi Context") + call assert_match(patContextDefault, hlContextAfterClear) + + delfunc FuncContextDefault + delfunc FuncContextRelink + call delete(scriptContextDefault) + call delete(scriptContextRelink) +endfunc + func Test_highlight_default_colorscheme_restores_links() hi link TestLink Identifier hi TestHi ctermbg=red diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index 1202b842fd..d23f0b5021 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -225,7 +225,7 @@ func Test_set_completion() " Expand files and directories. call feedkeys(":set tags=./\\\"\", 'tx') - call assert_match('./samples/ ./sautest/ ./screendump.vim ./setup.vim ./shared.vim', @:) + call assert_match('./samples/ ./sautest/ ./screendump.vim ./script_util.vim ./setup.vim ./shared.vim', @:) call feedkeys(":set tags=./\\\\ dif\\\"\", 'tx') call assert_equal('"set tags=./\\ diff diffexpr diffopt', @:) From 79575cfe8a191dabb1352f8d75d984a7866d70fd Mon Sep 17 00:00:00 2001 From: "Andy K. Massimino" Date: Sun, 7 Mar 2021 10:15:28 -0500 Subject: [PATCH 4/4] Fix a failing test (highlight_spec.lua) --- test/functional/ui/highlight_spec.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index ef3acd7d2e..8992ee27ce 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -333,10 +333,10 @@ describe('highlight defaults', function() command('highlight clear EndOfBuffer') screen:expect{grid=[[ ^ | - ~ | - ~ | + {1:~ }| + {1:~ }| | - ]], hl_groups={EndOfBuffer=0, MsgSeparator=2}} + ]], hl_groups={EndOfBuffer=1, MsgSeparator=2}} end) end)