vim-patch:8.0.0513: fix getting name of cleared highlight group (#8103)

Problem:    Getting name of cleared highlight group is wrong. (Matt Wozniski)
Solution:   Only skip over cleared names for completion. (closes vim/vim#1592)
            Also fix that a cleared group causes duplicate completions.
c96272e30e
This commit is contained in:
KunMing Xie 2018-03-09 02:49:21 +08:00 committed by Justin M. Keyes
parent 1d5eec2c62
commit 5ec0a6d13f
5 changed files with 28 additions and 9 deletions

View File

@ -16216,7 +16216,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
break; break;
} }
case 'n': { // name case 'n': { // name
p = get_highlight_name(NULL, id - 1); p = get_highlight_name_ext(NULL, id - 1, false);
break; break;
} }
case 'r': { // reverse case 'r': { // reverse

View File

@ -5828,7 +5828,8 @@ static void sign_list_defined(sign_T *sp)
} }
if (sp->sn_line_hl > 0) { if (sp->sn_line_hl > 0) {
msg_puts(" linehl="); msg_puts(" linehl=");
const char *const p = get_highlight_name(NULL, sp->sn_line_hl - 1); const char *const p = get_highlight_name_ext(NULL,
sp->sn_line_hl - 1, false);
if (p == NULL) { if (p == NULL) {
msg_puts("NONE"); msg_puts("NONE");
} else { } else {
@ -5837,7 +5838,8 @@ static void sign_list_defined(sign_T *sp)
} }
if (sp->sn_text_hl > 0) { if (sp->sn_text_hl > 0) {
msg_puts(" texthl="); msg_puts(" texthl=");
const char *const p = get_highlight_name(NULL, sp->sn_text_hl - 1); const char *const p = get_highlight_name_ext(NULL,
sp->sn_text_hl - 1, false);
if (p == NULL) { if (p == NULL) {
msg_puts("NONE"); msg_puts("NONE");
} else { } else {

View File

@ -7758,20 +7758,26 @@ static void highlight_list_two(int cnt, int attr)
} }
/* /// Function given to ExpandGeneric() to obtain the list of group names.
* Function given to ExpandGeneric() to obtain the list of group names.
* Also used for synIDattr() function.
*/
const char *get_highlight_name(expand_T *const xp, int idx) const char *get_highlight_name(expand_T *const xp, int idx)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_WARN_UNUSED_RESULT
{
return get_highlight_name_ext(xp, idx, true);
}
/// Obtain a highlight group name.
/// When "skip_cleared" is TRUE don't return a cleared entry.
const char *get_highlight_name_ext(expand_T *xp, int idx, int skip_cleared)
FUNC_ATTR_WARN_UNUSED_RESULT
{ {
if (idx < 0) { if (idx < 0) {
return NULL; return NULL;
} }
// Items are never removed from the table, skip the ones that were cleared. // Items are never removed from the table, skip the ones that were cleared.
while (idx < highlight_ga.ga_len && HL_TABLE()[idx].sg_cleared) { if (skip_cleared && idx < highlight_ga.ga_len && HL_TABLE()[idx].sg_cleared) {
idx++; return "";
} }
if (idx == highlight_ga.ga_len && include_none != 0) { if (idx == highlight_ga.ga_len && include_none != 0) {

View File

@ -70,6 +70,14 @@ func Test_highlight_completion()
call assert_equal('"hi default', getreg(':')) call assert_equal('"hi default', getreg(':'))
call feedkeys(":hi c\<S-Tab>\<Home>\"\<CR>", 'xt') call feedkeys(":hi c\<S-Tab>\<Home>\"\<CR>", 'xt')
call assert_equal('"hi clear', getreg(':')) call assert_equal('"hi clear', getreg(':'))
" A cleared group does not show up in completions.
hi Anders ctermfg=green
call assert_equal(['Aardig', 'Anders'], getcompletion('A', 'highlight'))
hi clear Aardig
call assert_equal(['Anders'], getcompletion('A', 'highlight'))
hi clear Anders
call assert_equal([], getcompletion('A', 'highlight'))
endfunc endfunc
func Test_expr_completion() func Test_expr_completion()

View File

@ -322,13 +322,16 @@ func Test_syn_clear()
syntax keyword Bar tar syntax keyword Bar tar
call assert_match('Foo', execute('syntax')) call assert_match('Foo', execute('syntax'))
call assert_match('Bar', execute('syntax')) call assert_match('Bar', execute('syntax'))
call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
syn clear Foo syn clear Foo
call assert_notmatch('Foo', execute('syntax')) call assert_notmatch('Foo', execute('syntax'))
call assert_match('Bar', execute('syntax')) call assert_match('Bar', execute('syntax'))
call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
syn clear Foo Bar syn clear Foo Bar
call assert_notmatch('Foo', execute('syntax')) call assert_notmatch('Foo', execute('syntax'))
call assert_notmatch('Bar', execute('syntax')) call assert_notmatch('Bar', execute('syntax'))
hi clear Foo hi clear Foo
call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
hi clear Bar hi clear Bar
endfunc endfunc