[vim/vim] Add built-in functions to get and set highlight groups (PR #9039)

78 views
Skip to first unread message

Yegappan Lakshmanan

unread,
Oct 24, 2021, 1:33:52 AM10/24/21
to vim/vim, Subscribed

You can view, comment on, or merge this pull request online at:

  https://github.com/vim/vim/pull/9039

Commit Summary

File Changes

Patch Links:

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

Yegappan Lakshmanan

unread,
Oct 24, 2021, 1:46:29 AM10/24/21
to vim/vim, Push

@yegappan pushed 1 commit.

  • 69441db Use vim_snprintf() instead of snprintf()

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

codecov[bot]

unread,
Oct 24, 2021, 1:53:40 AM10/24/21
to vim/vim, Subscribed

Codecov Report

Merging #9039 (69441db) into master (844fb64) will decrease coverage by 87.64%.
The diff coverage is 0.00%.

Impacted file tree graph

@@             Coverage Diff             @@

##           master    #9039       +/-   ##

===========================================

- Coverage   90.10%    2.45%   -87.65%     

===========================================

  Files         151      149        -2     

  Lines      169669   166354     -3315     

===========================================

- Hits       152879     4085   -148794     

- Misses      16790   162269   +145479     
Flag Coverage Δ
huge-clang-none ?
huge-gcc-none ?
huge-gcc-testgui ?
huge-gcc-unittests 2.45% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/evalfunc.c 0.00% <ø> (-96.51%) ⬇️
src/highlight.c 6.88% <0.00%> (-83.88%) ⬇️
src/float.c 0.00% <0.00%> (-99.22%) ⬇️
src/gui_gtk_f.c 0.00% <0.00%> (-97.43%) ⬇️
src/crypt_zip.c 0.00% <0.00%> (-97.06%) ⬇️
src/cmdhist.c 0.00% <0.00%> (-97.00%) ⬇️
src/sha256.c 0.00% <0.00%> (-96.94%) ⬇️
src/evalbuffer.c 0.00% <0.00%> (-96.92%) ⬇️
src/textprop.c 0.00% <0.00%> (-96.84%) ⬇️
src/match.c 0.00% <0.00%> (-96.76%) ⬇️
... and 139 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 844fb64...69441db. Read the comment docs.

Bram Moolenaar

unread,
Oct 24, 2021, 7:47:00 AM10/24/21
to vim/vim, Subscribed

In the list of functions "hlset()" has "set highlight group attributes", thus "hlget()" should say "get highlight group attributes".

When the name is specified, it should be clear that it returns a list with that entry. The "returns an empty list" paragraph can be moved up, so that the main info about what is returned is in one place.

Otherwise it looks OK to me. Perhaps the info about "cleared" should say a bit more. Like hlexists() mentions that a name can exist without highlighting defined for it, it doesn't actually need to be cleared.

Yegappan Lakshmanan

unread,
Oct 24, 2021, 1:45:05 PM10/24/21
to vim/vim, Push

@yegappan pushed 1 commit.

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Yegappan Lakshmanan

unread,
Oct 24, 2021, 1:46:44 PM10/24/21
to vim_dev, reply+ACY5DGC3NACBM74EPB...@reply.github.com, vim/vim, Subscribed
Hi Bram,

On Sun, Oct 24, 2021 at 4:47 AM Bram Moolenaar <vim-dev...@256bit.org> wrote:

In the list of functions "hlset()" has "set highlight group attributes", thus "hlget()" should say "get highlight group attributes".

When the name is specified, it should be clear that it returns a list with that entry. The "returns an empty list" paragraph can be moved up, so that the main info about what is returned is in one place.

Otherwise it looks OK to me. Perhaps the info about "cleared" should say a bit more. Like hlexists() mentions that a name can exist without highlighting defined for it, it doesn't actually need to be cleared.



I have updated the PR  incorporating your comments.

Regards,
Yegappan

vim-dev ML

unread,
Oct 24, 2021, 1:46:59 PM10/24/21
to vim/vim, vim-dev ML, Your activity

Hi Bram,

On Sun, Oct 24, 2021 at 4:47 AM Bram Moolenaar ***@***.***>

wrote:

> In the list of functions "hlset()" has "set highlight group attributes",
> thus "hlget()" should say "get highlight group attributes".
>
> When the name is specified, it should be clear that it returns a list with
> that entry. The "returns an empty list" paragraph can be moved up, so that
> the main info about what is returned is in one place.
>
> Otherwise it looks OK to me. Perhaps the info about "cleared" should say a
> bit more. Like hlexists() mentions that a name can exist without
> highlighting defined for it, it doesn't actually need to be cleared.
>
>
>
I have updated the PR incorporating your comments.

Regards,
Yegappan

Yegappan Lakshmanan

unread,
Oct 24, 2021, 4:02:44 PM10/24/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 1 commit.

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Yegappan Lakshmanan

unread,
Oct 24, 2021, 4:04:15 PM10/24/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 2 commits.

  • b687ed6 Add built-in functions to get and set highlight groups.
  • e1fd96c Refactor the changes

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Yegappan Lakshmanan

unread,
Oct 25, 2021, 1:00:51 AM10/25/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 1 commit.

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Yegappan Lakshmanan

unread,
Oct 25, 2021, 10:06:27 PM10/25/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 1 commit.

  • e49d01e Add support for clearing highlight attributes and update tests

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Yegappan Lakshmanan

unread,
Oct 25, 2021, 10:09:04 PM10/25/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 2 commits.

  • e1b3187 Add built-in functions to get and set highlight groups.
  • 893915c Add support for clearing highlight attributes and update tests

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Bram Moolenaar

unread,
Oct 26, 2021, 8:55:31 AM10/26/21
to vim/vim, vim-dev ML, Comment

I'll leave this for a day for anybody to comment.

—
You are receiving this because you commented.

Romain Lafourcade

unread,
Oct 26, 2021, 10:30:15 AM10/26/21
to vim/vim, vim-dev ML, Comment

@romainl commented on this pull request.


In runtime/doc/eval.txt:

> +		The 'term', 'cterm' and 'gui' items in the above Dictionary
+		have a dictionary value with the following optional boolean
+		items: 'bold', 'standout', 'underline', 'undercurl', 'italic',
+		'reverse', 'inverse' and 'strikethrough'.
+
+
+		Example(s): >
+			:echo hlget()
+			:echo hlget('ModeMsg')
+<
+		Can also be used as a |method|: >
+			GetName()->hlget()
+<
+							*hlset()*
+hlset({list})
+		Set the attributes of a List of highlight groups. If a

"Sets"

—
You are receiving this because you commented.

Romain Lafourcade

unread,
Oct 26, 2021, 10:41:10 AM10/26/21
to vim/vim, vim-dev ML, Comment

@romainl commented on this pull request.


In runtime/doc/eval.txt:

> @@ -6716,6 +6718,81 @@ hlexists({name})					*hlexists()*
 
 		Can also be used as a |method|: >
 			GetName()->hlexists()
+<
+							*hlget()*
+hlget([{name}])

[{name}] gives the impression that one must pass a potentially empty list to the function, which is not the case.

—
You are receiving this because you commented.

lacygoill

unread,
Oct 26, 2021, 11:22:02 AM10/26/21
to vim/vim, vim-dev ML, Comment

@lacygoill commented on this pull request.


In runtime/doc/eval.txt:

> @@ -6716,6 +6718,81 @@ hlexists({name})					*hlexists()*
 
 		Can also be used as a |method|: >
 			GetName()->hlexists()
+<
+							*hlget()*
+hlget([{name}])

[{name}] gives the impression that one must pass a potentially empty list to the function, which is not the case.

That has always bothered me as well, but that's the convention used in the help everywhere else.
{foo} means that foo is a placeholder name (i.e. not to be taken literally, but replaced with a relevant name).
And the surrounding square brackets mean that the parameter is optional.

We can read the same [{name}] for getfontname():
https://github.com/vim/vim/blob/2446ec9b567ce2b72bd06d121f200f40bbdc8a84/runtime/doc/eval.txt#L5787

sign_getdefined():
https://github.com/vim/vim/blob/2446ec9b567ce2b72bd06d121f200f40bbdc8a84/runtime/doc/sign.txt#L423

sign_undefine():
https://github.com/vim/vim/blob/2446ec9b567ce2b72bd06d121f200f40bbdc8a84/runtime/doc/sign.txt#L650

—
You are receiving this because you commented.

Yegappan Lakshmanan

unread,
Oct 26, 2021, 11:29:01 AM10/26/21
to vim/vim, vim-dev ML, Comment

@yegappan commented on this pull request.


In runtime/doc/eval.txt:

> @@ -6716,6 +6718,81 @@ hlexists({name})					*hlexists()*
 
 		Can also be used as a |method|: >
 			GetName()->hlexists()
+<
+							*hlget()*
+hlget([{name}])

Yes. That is the convention used in the help files. The optional argument is surrounded by square brackets.

—
You are receiving this because you commented.

Yegappan Lakshmanan

unread,
Oct 26, 2021, 11:32:52 AM10/26/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 1 commit.

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Romain Lafourcade

unread,
Oct 26, 2021, 11:35:14 AM10/26/21
to vim/vim, vim-dev ML, Comment

@romainl commented on this pull request.


In runtime/doc/eval.txt:

> +			term	term attributes.  See |highlight-term|.
+
+		The 'term', 'cterm' and 'gui' items in the above Dictionary
+		have a dictionary value with the following optional boolean
+		items: 'bold', 'standout', 'underline', 'undercurl', 'italic',
+		'reverse', 'inverse' and 'strikethrough'.
+
+		Example(s): >
+			:echo hlget()
+			:echo hlget('ModeMsg')
+<
+		Can also be used as a |method|: >
+			GetName()->hlget()
+<
+hlset({list})						*hlset()*
+		Create or modify the attributes of a List of highlight groups.

"Creates or modifies" to follow the "Returns" above.

—
You are receiving this because you commented.

Yegappan Lakshmanan

unread,
Oct 26, 2021, 11:37:42 AM10/26/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 2 commits.

  • 57a4058 Add built-in functions to get and set highlight groups.
  • 84addaa Update help

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

lacygoill

unread,
Oct 26, 2021, 12:42:52 PM10/26/21
to vim/vim, vim-dev ML, Comment

hlget('SpecialKey') outputs a list with a single dictionary item:

./src/vim -Nu NONE --cmd 'echo hlget("SpecialKey") | qa!'

[{'id': 1, 'ctermfg': '4', 'name': 'SpecialKey', 'term': {'bold': v:true}, 'guifg': 'Blue'}]

^^                                                                                        ^^

What matters is the dictionary. Wouldn't it make more sense to drop the list?

./src/vim -Nu NONE --cmd 'echo hlget("SpecialKey") | qa!'

{'id': 1, 'ctermfg': '4', 'name': 'SpecialKey', 'term': {'bold': v:true}, 'guifg': 'Blue'}

^                                                                                        ^

Rationale: it's easier to read this:

:echo hlget('SpecialKey').ctermfg

Than this:

:echo hlget('SpecialKey')[0].ctermfg

                         ^^^

                         what's this for?

Unless there are cases where hlget('Name') can return more than 1 dictionary? Are there?

And if the highlight group does not exist, we could return an empty dictionary, instead of an empty list.


Similarly, could hlset() accept a dictionary – in addition to a list – when we only want to set 1 highlight group?

—
You are receiving this because you commented.

lacygoill

unread,
Oct 26, 2021, 12:43:14 PM10/26/21
to vim/vim, vim-dev ML, Comment

Could hlget() accept an extra optional boolean parameter to make it automatically resolve links?

:echo hlget('Group', v:true)[0]
                     ^----^

Otherwise, we might have to use a while loop which makes the code more verbose:

vim9script
hlset([{name: 'A', linksto: 'B'}])
hlset([{name: 'B', linksto: 'C'}])
hlset([{'ctermfg': '4', 'name': 'C', 'term': {'bold': v:true}, 'guifg': 'Blue'}])
var hl: dict<any> = hlget('A')[0]
while hl->has_key('linksto')
    hl = hlget(hl.linksto)->get(0, {})
endwhile
echo hl
{'id': 56, 'ctermfg': '4', 'name': 'C', 'term': {'bold': true}, 'guifg': 'Blue'}

—
You are receiving this because you commented.

Bram Moolenaar

unread,
Oct 26, 2021, 1:04:01 PM10/26/21
to vim/vim, vim-dev ML, Comment

For the return value: it is much better if the function always returns the same type, not a list with one call and a dictionary with another. That you get a list with one entry (or an empty list if not found) is easy to deal with.

—
You are receiving this because you commented.

Yegappan Lakshmanan

unread,
Oct 26, 2021, 2:34:47 PM10/26/21
to vim/vim, vim-dev ML, Comment

hlget('SpecialKey') outputs a list with a single dictionary item:

What matters is the dictionary. Wouldn't it make more sense to drop the list?

As Bram mentioned in his reply, it is better to use the same return type for both
a single highlight group and for all the highlight groups.

Unless there are cases where hlget('Name') can return more than 1 dictionary? Are there?

The hlget('Name') call will always return a single dictionary.

And if the highlight group does not exist, we could return an empty dictionary, instead of an empty list.

Similarly, could hlset() accept a dictionary – in addition to a list – when we only want to set 1 highlight group?

Similar to the return value, it is better to always accept a single type for
a argument. We do have some existing functions that accept different types
for the argument and this caused problems with the Vim9 type checks.

—
You are receiving this because you commented.

Yegappan Lakshmanan

unread,
Oct 26, 2021, 11:40:23 PM10/26/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 1 commit.

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Romain Lafourcade

unread,
Oct 27, 2021, 1:30:00 AM10/27/21
to vim/vim, vim-dev ML, Comment

@yegappan could you outline your plans for your hlrefactor branch?

As we are working on modernising the built-in colorscheme under the vim/colorschemes umbrella it might be interesting for us to know what you have in store regarding syntax highlighting.

Thanks.

—
You are receiving this because you commented.

Yegappan Lakshmanan

unread,
Oct 27, 2021, 10:24:23 AM10/27/21
to vim_dev, reply+ACY5DGBHZOETAN4W3W...@reply.github.com, vim/vim, vim-dev ML, Comment
Hi,

On Tue, Oct 26, 2021 at 10:29 PM Romain Lafourcade <vim-dev...@256bit.org> wrote:

@yegappan could you outline your plans for your hlrefactor branch?


When developing the hlget() and hlset() functions, I found that the do_highlight()
function was too long. So I refactored this function before adding the new functions.
I don't have further plans to add new functionality to this branch (except for any
changes to the hlget() and hlset() functions)
 

As we are working on modernising the built-in colorscheme under the vim/colorschemes umbrella it might be interesting for us to know what you have in store regarding syntax highlighting.



Are you looking for built-in functions to manage with syntax highlighting?

Regards,
Yegappan
 

vim-dev ML

unread,
Oct 27, 2021, 10:24:42 AM10/27/21
to vim/vim, vim-dev ML, Your activity

Hi,

On Tue, Oct 26, 2021 at 10:29 PM Romain Lafourcade <
***@***.***> wrote:

> @yegappan <https://github.com/yegappan> could you outline your plans for

> your hlrefactor branch?
>

When developing the hlget() and hlset() functions, I found that the
do_highlight()
function was too long. So I refactored this function before adding the new
functions.
I don't have further plans to add new functionality to this branch (except
for any
changes to the hlget() and hlset() functions)


> As we are working on modernising the built-in colorscheme under the
> vim/colorschemes umbrella it might be interesting for us to know what you
> have in store regarding syntax highlighting.
>
>
>
Are you looking for built-in functions to manage with syntax highlighting?

Regards,
Yegappan

—
You are receiving this because you are subscribed to this thread.

Yegappan Lakshmanan

unread,
Oct 27, 2021, 1:42:06 PM10/27/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 1 commit.

  • 00b0393 Resolve highlight group links recursively

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Romain Lafourcade

unread,
Oct 27, 2021, 2:16:18 PM10/27/21
to vim/vim, vim-dev ML, Comment

Are you looking for built-in functions to manage with syntax highlighting?

Not particularly, I was just being nosy.

Thank you again.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub.

Yegappan Lakshmanan

unread,
Oct 27, 2021, 10:49:38 PM10/27/21
to vim_dev, reply+ACY5DGC7QC6QTPOLXX...@reply.github.com, vim/vim, vim-dev ML, Comment
Hi,

On Tue, Oct 26, 2021 at 9:43 AM lacygoill <vim-dev...@256bit.org> wrote:

Could hlget() accept an extra optional boolean parameter to make it automatically resolve links?


I have updated the PR to add support for this.

- Yegappan

vim-dev ML

unread,
Oct 27, 2021, 10:49:56 PM10/27/21
to vim/vim, vim-dev ML, Your activity

Hi,


On Tue, Oct 26, 2021 at 9:43 AM lacygoill ***@***.***> wrote:

> Could hlget() accept an extra optional boolean parameter to make it
> automatically resolve links?
>

I have updated the PR to add support for this.

- Yegappan


> :echo hlget('Group', v:true)[0]
> ^----^
>
> Otherwise, we might have to use a while loop which makes the code more
> verbose:
>
> vim9scripthlset([{name: 'A', linksto: 'B'}])hlset([{name: 'B', linksto: 'C'}])hlset([{'ctermfg': '4', 'name': 'C', 'term': {'bold': v:true}, 'guifg': 'Blue'}])var hl: dict<any> = hlget('A')[0]while hl->has_key('linksto')
> hl = hlget(hl.linksto)->get(0, {})endwhileecho hl

>
> {'id': 56, 'ctermfg': '4', 'name': 'C', 'term': {'bold': true}, 'guifg': 'Blue'}
>
>
>

—
You are receiving this because you are subscribed to this thread.

Yegappan Lakshmanan

unread,
Oct 31, 2021, 11:25:58 AM10/31/21
to vim/vim, vim-dev ML, Push

@yegappan pushed 1 commit.

  • dbfc360 Add built-in functions to get and set highlight groups.

—
You are receiving this because you are subscribed to this thread.

View it on GitHub.

Bram Moolenaar

unread,
Nov 3, 2021, 5:57:11 PM11/3/21
to vim/vim, vim-dev ML, Comment

Closed #9039 via d1a8d65.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub.

lacygoill

unread,
Nov 10, 2021, 5:21:10 PM11/10/21
to vim/vim, vim-dev ML, Comment

To clear a highlight group with :highlight, we need to choose one of 3 Ex commands, depending on how it was defined.

If it's defined with its own attributes, then we need :highlight clear:

highlight MyGroup ctermbg=green guibg=green
highlight clear MyGroup
highlight MyGroup
MyGroup        xxx cleared

If it's linked to another highlight group, then we need to link it to NONE:

highlight default link MyGroup ErrorMsg
highlight link MyGroup NONE
highlight MyGroup
MyGroup        xxx cleared

Actually, :highlight clear might work too, but only if the group was defined without the default argument.

If it's defined with its own attributes and is linked to another highlight group, we need to first clear it, then reset its link to NONE (the order of the commands matters):

highlight MyGroup ctermbg=green guibg=green
highlight! default link MyGroup ErrorMsg
highlight clear MyGroup
highlight link MyGroup NONE
highlight MyGroup
MyGroup        xxx cleared

That's a lot of info. Using hlset() instead of :highlight does not simplify the operation:

highlight MyGroup ctermbg=green guibg=green
highlight! default link MyGroup ErrorMsg
call hlset([{'name': 'MyGroup', 'cleared': v:true, 'linksto': 'NONE'}])
highlight MyGroup
MyGroup        xxx ctermbg=10 guibg=green

We need 2 invocations of hlset() to be sure the group is cleared:

highlight MyGroup ctermbg=green guibg=green
highlight! default link MyGroup ErrorMsg
call hlset([{'name': 'MyGroup', 'cleared': v:true}])
call hlset([{'name': 'MyGroup', 'linksto': 'NONE'}])
highlight MyGroup
MyGroup        xxx cleared

I think the first hlset() invocation fails to clear the group because it first removes the link then clears it (causing the link to be restored because of default). When both the cleared and linksto keys are present, wouldn't it make more sense for hlset() to process cleared before linksto?

Yegappan Lakshmanan

unread,
Nov 10, 2021, 11:33:05 PM11/10/21
to vim_dev, reply+ACY5DGD7GGVFXTYH5G...@reply.github.com, vim/vim, vim-dev ML, Comment
Hi,

I have created PR #9117 to support this.

Regards,
Yegappan

 

vim-dev ML

unread,
Nov 10, 2021, 11:33:22 PM11/10/21
to vim/vim, vim-dev ML, Your activity

Hi,


On Wed, Nov 10, 2021 at 2:21 PM lacygoill ***@***.***> wrote:

> To clear a highlight group with :highlight, we need to choose one of 3 Ex
> commands, depending on how it was defined.
>
> If it's defined with its own attributes, then we need :highlight clear:
>
> highlight MyGroup ctermbg=green guibg=greenhighlight clear MyGrouphighlight MyGroup

>
> MyGroup xxx cleared
>
> If it's linked to another highlight group, then we need to link it to NONE
> :
>
> highlight default link MyGroup ErrorMsghighlight link MyGroup NONEhighlight MyGroup
>
> MyGroup xxx cleared
>
> *Actually, :highlight clear might work too, but only if the group was
> defined without the default argument.*
>
> If it's defined with its own attributes *and* is linked to another
> highlight group, we need to first clear it, *then* reset its link to NONE

> (the order of the commands matters):
>
> highlight MyGroup ctermbg=green guibg=greenhighlight! default link MyGroup ErrorMsghighlight clear MyGrouphighlight link MyGroup NONEhighlight MyGroup

>
> MyGroup xxx cleared
>
> That's a lot of info. Using hlset() instead of :highlight does not
> simplify the operation:
>
> highlight MyGroup ctermbg=green guibg=greenhighlight! default link MyGroup ErrorMsgcall hlset([{'name': 'MyGroup', 'cleared': v:true, 'linksto': 'NONE'}])highlight MyGroup

>
> MyGroup xxx ctermbg=10 guibg=green
>
> We need 2 invocations of hlset() to be sure the group is cleared:
>
> highlight MyGroup ctermbg=green guibg=greenhighlight! default link MyGroup ErrorMsgcall hlset([{'name': 'MyGroup', 'cleared': v:true}])call hlset([{'name': 'MyGroup', 'linksto': 'NONE'}])highlight MyGroup

>
> MyGroup xxx cleared
>
> I think the first hlset() invocation fails to clear the group because it
> first removes the link then clears it (causing the link to be restored
> because of default). When both the cleared and linksto keys are present,
> wouldn't it make more sense for hlset() to process cleared *before*

> linksto?
>
>
>
I have created PR #9117 to support this.

Regards,
Yegappan

—
You are receiving this because you are subscribed to this thread.

lacygoill

unread,
Nov 11, 2021, 8:20:00 AM11/11/21
to vim/vim, vim-dev ML, Comment

Thank you very much for the quick PR, I'm going to test it as soon as I can.


I noticed two other possible issues for which I would like your opinion.

Issue 1: hlset() can't emulate the bang of :highlight!.
Issue 2: hlget() does not give any information for the default argument of a linked highlight group.

With regards to issue 1:

vim9script
highlight MyGroup ctermbg=green
hlset([{name: 'MyGroup', linksto: 'ErrorMsg'}])
highlight MyGroup
MyGroup        xxx ctermbg=10

Notice that the link was not installed. I think that's because hlset() operates like :highlight by default; not like :highlight!. I've read :help hlget() and :help hlset(), but couldn't find any key allowing us to emulate the bang.

This means that there exists an operation that :highlight can perform but not hlset():

vim9script
highlight MyGroup ctermbg=green
highlight! link MyGroup ErrorMsg
highlight MyGroup
MyGroup        xxx ctermbg=10
                   links to ErrorMsg

Shouldn't hlset() provide all the features of :highlight?

With regards to issue 2:

vim9script
[{name: 'MyGroup', linksto: 'ErrorMsg'}]->hlset()
highlight clear MyGroup
highlight MyGroup
MyGroup     xxx cleared

Notice that MyGroup has been cleared. This means that when hlset() defines a group with a link, it does not use default. How are we supposed to tell hlset() that we do want default? Shouldn't it accept a boolean key like default_link?


If you consider all of this as valid, I can open separate issues; let me know. Thank you again for your work on these very useful functions.

—
You are receiving this because you commented.

Yegappan Lakshmanan

unread,
Nov 11, 2021, 10:54:15 PM11/11/21
to vim_dev, reply+ACY5DGBPXJDORRJUB2...@reply.github.com, vim/vim, vim-dev ML, Comment
Hi,

On Thu, Nov 11, 2021 at 5:20 AM lacygoill <vim-dev...@256bit.org> wrote:

Thank you very much for the quick PR, I'm going to test it as soon as I can.


I noticed two other possible issues for which I would like your opinion.

Issue 1: hlset() can't emulate the bang of :highlight!.
Issue 2: hlget() does not give any information for the default argument of a linked highlight group.


Thanks for the detailed feedback. I have updated the PR to add support for these.
Can you try the updated PR and let me know if you see any problems?

Regards,
Yegappan

vim-dev ML

unread,
Nov 11, 2021, 10:54:31 PM11/11/21
to vim/vim, vim-dev ML, Your activity

Hi,


On Thu, Nov 11, 2021 at 5:20 AM lacygoill ***@***.***> wrote:

> Thank you very much for the quick PR, I'm going to test it as soon as I
> can.
> ------------------------------

>
> I noticed two other possible issues for which I would like your opinion.
>
> Issue 1: hlset() can't emulate the bang of :highlight!.
> Issue 2: hlget() does not give any information for the default argument
> of a linked highlight group.
>

Thanks for the detailed feedback. I have updated the PR to add support for
these.
Can you try the updated PR and let me know if you see any problems?

Regards,
Yegappan


> With regards to issue 1:
>
> vim9scripthighlight MyGroup ctermbg=greenhlset([{name: 'MyGroup', linksto: 'ErrorMsg'}])highlight MyGroup

>
> MyGroup xxx ctermbg=10
>
> Notice that the link was not installed. I think that's because hlset()
> operates like :highlight by default; not like :highlight!. I've read :help
> hlget() <https://vimhelp.org/eval.txt.html#hlget%28%29> and :help hlset()
> <https://vimhelp.org/eval.txt.html#hlset%28%29>, but couldn't find any

> key allowing us to emulate the bang.
>
> This means that there exists an operation that :highlight can perform but
> not hlset():
>
> vim9scripthighlight MyGroup ctermbg=greenhighlight! link MyGroup ErrorMsghighlight MyGroup

>
> MyGroup xxx ctermbg=10
> links to ErrorMsg
>
> Shouldn't hlset() provide all the features of :highlight?
>
> With regards to issue 2:
>
> vim9script
> [{name: 'MyGroup', linksto: 'ErrorMsg'}]->hlset()highlight clear MyGrouphighlight MyGroup

>
> MyGroup xxx cleared
>
> Notice that MyGroup has been cleared. This means that when hlset()
> defines a group with a link, it does not use default. How are we supposed
> to tell hlset() that we do want default? Shouldn't it accept a boolean
> key like default_link?
> ------------------------------

>
> If you consider all of this as valid, I can open separate issues; let me
> know. Thank you again for your work on these very useful functions.
>
>
>

—
You are receiving this because you are subscribed to this thread.

lacygoill

unread,
Nov 11, 2021, 11:30:31 PM11/11/21
to vim/vim, vim-dev ML, Comment

Thank you very much for the quick fix. Everything works fine with maybe one exception. The default key is still absent from the output of hlget().

vim9script
[{name: 'MyGroup', linksto: 'ErrorMsg', default: true}]->hlset()
echo hlget('MyGroup')->get(0, {})->has_key('default')
0

This matters if we want to create an exact duplicate of an existing highlight group, and maybe slightly alter one of its attribute. For example:

vim9script
highlight default link MyGroup ErrorMsg
var hg_save: list<dict<any>> = hlget('MyGroup')
var dup: string = 'Duplicate'
hg_save[0]->extend({'name': dup})
hg_save->hlset()
highlight clear Duplicate
highlight Duplicate
Duplicate     xxx cleared

Notice that Duplicate is cleared. This means that when it was created by hlset(), the latter did not use default; otherwise, the link would have been automatically restored just like here:

vim9script
highlight default link MyGroup ErrorMsg
highlight clear MyGroup
highlight MyGroup
MyGroup        xxx links to ErrorMsg

I think the issue comes from hlget() which still does not tell us whether MyGroup is linked to ErrorMsg with default or not. It would help if the output of hlget() included default: true or default: false for a linked group:

vim9script
[{name: 'MyGroup', linksto: 'ErrorMsg', default: true}]->hlset()
echo hlget('MyGroup')
[{'id': 54, 'linksto': 'ErrorMsg', 'default': true, 'name': 'MyGroup'}]
                                   ^-------------^

—
You are receiving this because you commented.

Yegappan Lakshmanan

unread,
Nov 12, 2021, 11:14:51 AM11/12/21
to vim_dev, reply+ACY5DGCYMQ4SRR543N...@reply.github.com, vim/vim, vim-dev ML, Comment
Hi,

On Thu, Nov 11, 2021 at 8:30 PM lacygoill <vim-dev...@256bit.org> wrote:

Thank you very much for the quick fix. Everything works fine with maybe one exception. The default key is still absent from the output of hlget().


The 'default' argument to the highlight command is only used to determine whether the new
attributes/link can override the already existing attributes/link and the 'default' setting is not
stored with the highlight group in the internal Vim structures. So the hlget() function cannot
return this as it is not present in the internal Vim highlight group structures.

For example, you can run the following commands:

:highlight hlg1 ctermfg=2
:highlight default hlg2 ctermfg=2
:highlight hlg1
hlg1           xxx ctermfg=2
:highlight hlg2
hlg2           xxx ctermfg=2

As you can see from the above output, both hlg1 and hlg2 have similar output and the
"default" setting is missing for hlg2.

Regards,
Yegappan

vim-dev ML

unread,
Nov 12, 2021, 11:15:10 AM11/12/21
to vim/vim, vim-dev ML, Your activity

Hi,


On Thu, Nov 11, 2021 at 8:30 PM lacygoill ***@***.***> wrote:

> Thank you very much for the quick fix. Everything works fine with maybe
> one exception. The default key is still absent from the output of hlget().
>

The 'default' argument to the highlight command is only used to determine
whether the new
attributes/link can override the already existing attributes/link and the
'default' setting is not
stored with the highlight group in the internal Vim structures. So the
hlget() function cannot
return this as it is not present in the internal Vim highlight group
structures.

For example, you can run the following commands:

:highlight hlg1 ctermfg=2
:highlight default hlg2 ctermfg=2
:highlight hlg1
hlg1 xxx ctermfg=2
:highlight hlg2
hlg2 xxx ctermfg=2

As you can see from the above output, both hlg1 and hlg2 have similar
output and the
"default" setting is missing for hlg2.

Regards,
Yegappan


> vim9script
> [{name: 'MyGroup', linksto: 'ErrorMsg', default: true}]->hlset()echo hlget('MyGroup')->get(0, {})->has_key('default')

>
> 0
>
> This matters if we want to create an exact duplicate of an existing
> highlight group, and maybe slightly alter one of its attribute. For example:
>
> vim9scripthighlight default link MyGroup ErrorMsgvar hg_save: list<dict<any>> = hlget('MyGroup')var dup: string = 'Duplicate'

> hg_save[0]->extend({'name': dup})
> hg_save->hlset()highlight clear Duplicatehighlight Duplicate

>
> Duplicate xxx cleared
>
> Notice that Duplicate is cleared. This means that when it was created by
> hlset(), the latter did not use default; otherwise, the link would have
> been automatically restored just like here:
>
> vim9scripthighlight default link MyGroup ErrorMsghighlight clear MyGrouphighlight MyGroup

>
> MyGroup xxx links to ErrorMsg
>
> I think the issue comes from hlget() which still does not tell us whether
> MyGroup is linked to ErrorMsg with default or not. It would help if the
> output of hlget() included default: true or default: false for a linked
> group:
>
> vim9script
> [{name: 'MyGroup', linksto: 'ErrorMsg', default: true}]->hlset()echo hlget('MyGroup')

>
> [{'id': 54, 'linksto': 'ErrorMsg', 'default': true, 'name': 'MyGroup'}]
> ^-------------^
>
>
>

—
You are receiving this because you are subscribed to this thread.

Yegappan Lakshmanan

unread,
Nov 12, 2021, 11:36:19 AM11/12/21
to vim_dev, reply+ACY5DGCYMQ4SRR543N...@reply.github.com, vim/vim, vim-dev ML, Comment
Hi,

On Fri, Nov 12, 2021 at 8:14 AM Yegappan Lakshmanan <yega...@gmail.com> wrote:
>
> Hi,
>
> On Thu, Nov 11, 2021 at 8:30 PM lacygoill <vim-dev...@256bit.org> wrote:
>>
>> Thank you very much for the quick fix. Everything works fine with maybe one exception. The default key is still absent from the output of hlget().
>
>
> The 'default' argument to the highlight command is only used to determine whether the new
> attributes/link can override the already existing attributes/link and the 'default' setting is not
> stored with the highlight group in the internal Vim structures. So the hlget() function cannot
> return this as it is not present in the internal Vim highlight group structures.
>

After sending this reply, I noticed that Vim does store the 'default'
setting for links,
but doesn't store it for highlight attributes. I have updated the PR
to return the
default setting for links.

Regards,
Yegappan

vim-dev ML

unread,
Nov 12, 2021, 11:36:35 AM11/12/21
to vim/vim, vim-dev ML, Your activity

Hi,


On Fri, Nov 12, 2021 at 8:14 AM Yegappan Lakshmanan ***@***.***> wrote:
>
> Hi,
>

lacygoill

unread,
Nov 12, 2021, 12:30:31 PM11/12/21
to vim/vim, vim-dev ML, Comment

I have updated the PR to return the default setting for links.

Thank you very much. I've just tested the PR, and everything works as expected.

—
You are receiving this because you commented.

lacygoill

unread,
Nov 19, 2021, 8:27:15 AM11/19/21
to vim/vim, vim-dev ML, Comment

Interestingly enough, :highlight is faster than hlset():

vim9script
var time = reltime()
def Func()
    for i: number in range(100'000)
        highlight ErrorMsg term=standout ctermfg=253 ctermbg=168 guifg=#dadada guibg=#d75f87
    endfor
enddef
Func()
(reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run Func()')->setline(1)
0.343 seconds to run Func()
vim9script
var time = reltime()
def Func()
    for i: number in range(100'000)
        [{
            name: 'ErrorMsg',
            ctermfg: '253',
            ctermbg: '168',
            guibg: '#d75f87',
            guifg: '#dadada',
            term: {standout: true},
        }]->hlset()
    endfor
enddef
Func()
(reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run Func()')->setline(1)
0.511 seconds to run Func()

The discrepancy is more pronounced at the script level:

vim9script
var time = reltime()
for i in range(100'000)
    highlight ErrorMsg term=standout ctermfg=253 ctermbg=168 guifg=#dadada guibg=#d75f87
endfor
(reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run the script')->setline(1)
0.523 seconds to run the script
vim9script
var time = reltime()
for i: number in range(100'000)
    [{
        name: 'ErrorMsg',
        ctermfg: '253',
        ctermbg: '168',
        guibg: '#d75f87',
        guifg: '#dadada',
        term: {standout: true},
    }]->hlset()
endfor
(reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run the script')->setline(1)
1.268 seconds to run the script

Log for hlset().
Log for :highlight.

Yegappan Lakshmanan

unread,
Nov 20, 2021, 2:32:15 PM11/20/21
to vim_dev, reply+ACY5DGFDRBG4HW4SMC...@reply.github.com, vim/vim, vim-dev ML, Comment
Hi,

I took a look at this issue. It looks like just populating the attributes itself takes time. For example,
if you source the following script:

vim9script
var time = reltime()
var attr: list<dict<any>>

for i: number in range(100'000)
    attr = [{

        name: 'ErrorMsg',
        ctermfg: '253',
        ctermbg: '168',
        guibg: '#d75f87',
        guifg: '#dadada',
        term: {standout: true},
    }]
endfor
(reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run the script')->setline(1)

The above script takes around 0.630 seconds in my setup (without any calls to hlset()).
So it looks like most of the time is spent outside of the hlset() function.

Regards,
Yegappan

vim-dev ML

unread,
Nov 20, 2021, 2:32:31 PM11/20/21
to vim/vim, vim-dev ML, Your activity

Hi,


On Fri, Nov 19, 2021 at 5:27 AM lacygoill ***@***.***> wrote:

> Interestingly enough, :highlight is faster than hlset():
>
> vim9scriptvar time = reltime()def Func()

> for i: number in range(100'000)
> highlight ErrorMsg term=standout ctermfg=253 ctermbg=168 guifg=#dadada guibg=#d75f87
> endforenddefFunc()
> (reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run Func()')->setline(1)
>
> 0.343 seconds to run Func()
>
> vim9scriptvar time = reltime()def Func()

> for i: number in range(100'000)
> [{
> name: 'ErrorMsg',
> ctermfg: '253',
> ctermbg: '168',
> guibg: '#d75f87',
> guifg: '#dadada',
> term: {standout: true},
> }]->hlset()
> endforenddefFunc()
> (reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run Func()')->setline(1)
>
> 0.511 seconds to run Func()
>
> The discrepancy is more pronounced at the script level:
>
> vim9scriptvar time = reltime()for i in range(100'000)

> highlight ErrorMsg term=standout ctermfg=253 ctermbg=168 guifg=#dadada guibg=#d75f87endfor
> (reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run the script')->setline(1)
>
> 0.523 seconds to run the script
>
> vim9scriptvar time = reltime()for i: number in range(100'000)

> [{
> name: 'ErrorMsg',
> ctermfg: '253',
> ctermbg: '168',
> guibg: '#d75f87',
> guifg: '#dadada',
> term: {standout: true},
> }]->hlset()endfor
> (reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run the script')->setline(1)
>
> 1.268 seconds to run the script
>
>
>
I took a look at this issue. It looks like just populating the attributes
itself takes time. For example,
if you source the following script:

vim9script
var time = reltime()
var attr: list<dict<any>>
for i: number in range(100'000)
attr = [{
name: 'ErrorMsg',
ctermfg: '253',
ctermbg: '168',
guibg: '#d75f87',
guifg: '#dadada',
term: {standout: true},
}]
endfor
(reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to run
the script')->setline(1)

The above script takes around 0.630 seconds in my setup (without any calls
to hlset()).
So it looks like most of the time is spent outside of the hlset() function.

Regards,
Yegappan

—
You are receiving this because you are subscribed to this thread.

Yegappan Lakshmanan

unread,
Nov 20, 2021, 8:38:17 PM11/20/21
to vim_dev, reply+ACY5DGFDRBG4HW4SMC...@reply.github.com, vim/vim, vim-dev ML, Comment
Hi,
If I modify the script so that the attributes are initialized outside
of the for loop, then the
script runs faster (around 0.520 seconds):

vim9script
var attr: list<dict<any>> = [{
name: 'ErrorMsg',
ctermfg: '253',
ctermbg: '168',
guibg: '#d75f87',
guifg: '#dadada',
term: {standout: true},
}]
var time = reltime()
for i: number in range(100'000)
attr->hlset()
endfor
(reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to
run the script')->setline(1)

Similarly, if hlset() is called for a large number of attributes in a
single invocation, then
the script runs faster (0.230 seconds):

vim9script
var l: list<dict<any>> = []
for i: number in range(100'000)
l->extend([{
name: 'ErrorMsg',
ctermfg: '253',
ctermbg: '168',
guibg: '#d75f87',
guifg: '#dadada',
term: {standout: true},
}])
endfor
var time = reltime()
l->hlset()
(reltime(time)->reltimestr()->matchstr('.*\..\{,3}') .. ' seconds to
run the script')->setline(1)

Regards,
Yegappan

vim-dev ML

unread,
Nov 20, 2021, 8:38:36 PM11/20/21
to vim/vim, vim-dev ML, Your activity

Hi,

On Sat, Nov 20, 2021 at 11:32 AM Yegappan Lakshmanan
***@***.***> wrote:
Reply all
Reply to author
Forward
0 new messages