Merge pull request #14060 from andymass/vim-8.2.1703

[RFC] vim-patch:8.2.{1693,1703,1705}
This commit is contained in:
Jan Edmund Lazo 2021-03-20 18:08:16 -04:00 committed by GitHub
commit dc8da7ba40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 208 additions and 27 deletions

View File

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

View File

@ -59,7 +59,9 @@ struct hl_group {
bool sg_cleared; ///< "hi clear" was used bool sg_cleared; ///< "hi clear" was used
int sg_attr; ///< Screen attr @see ATTR_ENTRY int sg_attr; ///< Screen attr @see ATTR_ENTRY
int sg_link; ///< link to this highlight group ID 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 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 sctx_T sg_script_ctx; ///< script in which the group was last set
// for terminal UIs // for terminal UIs
int sg_cterm; ///< "cterm=" highlighting attr int sg_cterm; ///< "cterm=" highlighting attr
@ -6601,6 +6603,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
const char *to_end; const char *to_end;
int from_id; int from_id;
int to_id; int to_id;
struct hl_group *hlgroup = NULL;
from_end = (const char *)skiptowhite((const char_u *)from_start); from_end = (const char *)skiptowhite((const char_u *)from_start);
to_start = (const char *)skipwhite((const char_u *)from_end); to_start = (const char *)skipwhite((const char_u *)from_end);
@ -6627,7 +6630,16 @@ void do_highlight(const char *line, const bool forceit, const bool init)
(int)(to_end - 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;
hlgroup->sg_deflink_sctx = current_sctx;
hlgroup->sg_deflink_sctx.sc_lnum += sourcing_lnum;
}
}
if (from_id > 0 && (!init || hlgroup->sg_set == 0)) {
// Don't allow a link when there already is some highlighting // Don't allow a link when there already is some highlighting
// for the group, unless '!' is used // for the group, unless '!' is used
if (to_id > 0 && !forceit && !init if (to_id > 0 && !forceit && !init
@ -6635,17 +6647,16 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (sourcing_name == NULL && !dodefault) { if (sourcing_name == NULL && !dodefault) {
EMSG(_("E414: group has settings, highlight link ignored")); 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
|| HL_TABLE()[from_id - 1].sg_script_ctx.sc_sid || hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid
!= current_sctx.sc_sid || hlgroup->sg_cleared) {
|| HL_TABLE()[from_id - 1].sg_cleared) {
if (!init) { 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; hlgroup->sg_link = to_id;
HL_TABLE()[from_id - 1].sg_script_ctx = current_sctx; hlgroup->sg_script_ctx = current_sctx;
HL_TABLE()[from_id - 1].sg_script_ctx.sc_lnum += sourcing_lnum; hlgroup->sg_script_ctx.sc_lnum += sourcing_lnum;
HL_TABLE()[from_id - 1].sg_cleared = false; hlgroup->sg_cleared = false;
redraw_all_later(SOME_VALID); redraw_all_later(SOME_VALID);
// Only call highlight changed() once after multiple changes // Only call highlight changed() once after multiple changes
@ -7076,13 +7087,14 @@ void restore_cterm_colors(void)
*/ */
static int hl_has_settings(int idx, int check_link) static int hl_has_settings(int idx, int check_link)
{ {
return HL_TABLE()[idx].sg_attr != 0 return HL_TABLE()[idx].sg_cleared == 0
|| HL_TABLE()[idx].sg_cterm_fg != 0 && (HL_TABLE()[idx].sg_attr != 0
|| HL_TABLE()[idx].sg_cterm_bg != 0 || HL_TABLE()[idx].sg_cterm_fg != 0
|| HL_TABLE()[idx].sg_rgb_fg_name != NULL || HL_TABLE()[idx].sg_cterm_bg != 0
|| HL_TABLE()[idx].sg_rgb_bg_name != NULL || HL_TABLE()[idx].sg_rgb_fg_name != NULL
|| HL_TABLE()[idx].sg_rgb_sp_name != NULL || HL_TABLE()[idx].sg_rgb_bg_name != NULL
|| (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)); || HL_TABLE()[idx].sg_rgb_sp_name != NULL
|| (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)));
} }
/* /*
@ -7105,12 +7117,11 @@ static void highlight_clear(int idx)
XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_bg_name); XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_bg_name);
XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_sp_name); XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_sp_name);
HL_TABLE()[idx].sg_blend = -1; HL_TABLE()[idx].sg_blend = -1;
// Clear the script ID only when there is no link, since that is not // Restore default link and context if they exist. Otherwise clears.
// cleared. HL_TABLE()[idx].sg_link = HL_TABLE()[idx].sg_deflink;
if (HL_TABLE()[idx].sg_link == 0) { // Since we set the default link, set the location to where the default
HL_TABLE()[idx].sg_script_ctx.sc_sid = 0; // link was set.
HL_TABLE()[idx].sg_script_ctx.sc_lnum = 0; HL_TABLE()[idx].sg_script_ctx = HL_TABLE()[idx].sg_deflink_sctx;
}
} }

View File

@ -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 ..= <args>
com! XloopINIT let g:Xloop = 1
com! -nargs=1 -bar Xloop let g:Xpath ..= <args> .. 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/\<a:\(\h\w*\)/g:\1/ge
normal gg0
let cnt = 0
while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
let cnt = cnt + 1
s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
endwhile
g/^\s*$/d
write
bwipeout
return script
endfunc
" ExecAsScript - Source a temporary script made from a function. {{{2
"
" Make a temporary script file from the function a:funcname, ":source" it, and
" delete it afterwards. However, if an exception is thrown the file may remain,
" the caller should call DeleteTheScript() afterwards.
let s:script_name = ''
function! ExecAsScript(funcname)
" Make a script from the function passed as argument.
let s:script_name = MakeScript(a:funcname)
" Source and delete the script.
exec "source" s:script_name
call delete(s:script_name)
let s:script_name = ''
endfunction
function! DeleteTheScript()
if s:script_name
call delete(s:script_name)
let s:script_name = ''
endif
endfunc
com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)

View File

@ -3,6 +3,7 @@
source view_util.vim source view_util.vim
source screendump.vim source screendump.vim
source check.vim source check.vim
source script_util.vim
func Test_highlight() func Test_highlight()
" basic test if ":highlight" doesn't crash " basic test if ":highlight" doesn't crash
@ -623,4 +624,103 @@ func Test_xxlast_highlight_RGB_color()
hi clear hi clear
endfunc endfunc
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_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
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
" '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 " vim: shiftwidth=2 sts=2 expandtab

View File

@ -225,7 +225,7 @@ func Test_set_completion()
" Expand files and directories. " Expand files and directories.
call feedkeys(":set tags=./\<C-A>\<C-B>\"\<CR>", 'tx') call feedkeys(":set tags=./\<C-A>\<C-B>\"\<CR>", '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\<C-A>\<C-B>\"\<CR>", 'tx') call feedkeys(":set tags=./\\\\ dif\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"set tags=./\\ diff diffexpr diffopt', @:) call assert_equal('"set tags=./\\ diff diffexpr diffopt', @:)

View File

@ -333,10 +333,10 @@ describe('highlight defaults', function()
command('highlight clear EndOfBuffer') command('highlight clear EndOfBuffer')
screen:expect{grid=[[ screen:expect{grid=[[
^ | ^ |
~ | {1:~ }|
~ | {1:~ }|
| |
]], hl_groups={EndOfBuffer=0, MsgSeparator=2}} ]], hl_groups={EndOfBuffer=1, MsgSeparator=2}}
end) end)
end) end)