diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/syntax.c | 30 | ||||
-rw-r--r-- | src/nvim/testdir/test_highlight.vim | 52 |
2 files changed, 63 insertions, 19 deletions
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 |