https://github.com/vim/vim/pull/8775
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.![]()
Merging #8775 (763fdab) into master (5aec755) will decrease coverage by
1.88%.
The diff coverage is82.75%.
❗ Current head 763fdab differs from pull request most recent head e71b389. Consider uploading reports for the commit e71b389 to get more accurate results
@@ Coverage Diff @@ ## master #8775 +/- ## ========================================== - Coverage 90.15% 88.26% -1.89% ========================================== Files 151 146 -5 Lines 170691 166364 -4327 ========================================== - Hits 153882 146839 -7043 - Misses 16809 19525 +2716
| Flag | Coverage Δ | |
|---|---|---|
| huge-clang-none | ? |
|
| huge-gcc-none | ? |
|
| huge-gcc-testgui | 88.26% <82.75%> (-0.01%) |
⬇️ |
| huge-gcc-unittests | ? |
Flags with carried forward coverage won't be shown. Click here to find out more.
| Impacted Files | Coverage Δ | |
|---|---|---|
| src/optionstr.c | 94.08% <66.66%> (-1.09%) |
⬇️ |
| src/option.c | 93.56% <80.95%> (-0.63%) |
⬇️ |
| src/ops.c | 95.18% <100.00%> (-0.82%) |
⬇️ |
| src/quickfix.c | 94.81% <100.00%> (-0.13%) |
⬇️ |
| src/libvterm/src/rect.h | 0.00% <0.00%> (-96.56%) |
⬇️ |
| src/libvterm/src/mouse.c | 0.00% <0.00%> (-48.34%) |
⬇️ |
| src/libvterm/src/state.c | 48.87% <0.00%> (-41.13%) |
⬇️ |
| src/libvterm/include/vterm.h | 0.00% <0.00%> (-37.50%) |
⬇️ |
| src/libvterm/src/pen.c | 49.85% <0.00%> (-34.81%) |
⬇️ |
| src/libvterm/src/keyboard.c | 54.73% <0.00%> (-33.69%) |
⬇️ |
| ... and 137 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 5aec755...e71b389. Read the comment docs.
@yegappan pushed 1 commit.
—
You are receiving this because you are subscribed to this thread.
View it on GitHub or unsubscribe.
This deserves a good example, or perhaps two, for how the lambda can be useful.
This could be handy for when the opfunc is a script-local function. We can't write this:
set operatorfunc=s:MyOpfunc
Because it raises E120:
E120: Using <SID> not in a script context: s:MyOpfunc
So, we have to write this:
let &operatorfunc = expand('<SID>') .. 'MyOpfunc'
Which looks a bit weird.
But with a lambda, we could write this instead:
set operatorfunc={type\ ->\ s:MyOpfunc(type)}
One could argue that it still looks weird. I still prefer reading a lambda which can be used in many other contexts, rather than expand('<SID>'), which is less often used.
Just 2 remarks. It works with :set but not with :let. That is, we cannot write this:
let &operatorfunc = {type -> s:MyOpfunc(type)}
Because it raises E729:
E729: Using a Funcref as a String
It still doesn't work if we manually coerce the lambda into a string:
let &operatorfunc = {type -> s:MyOpfunc(type)}->string()
^--------^
Because this time, it raises E129:
E129: Function name required
It would be nice if could work so that we don't have to escape spaces:
# ugly
set operatorfunc={type\ ->\ s:MyOpfunc(type)}
^ ^
# nicer
let &operatorfunc = {type -> s:MyOpfunc(type)}
^ ^
Also, it doesn't work with a Vim9 lambda. That is, in a Vim9 script/function, we cannot write this:
set operatorfunc=(type)\ =>\ MyOpfunc(type)
Because it raises E117:
E117: Unknown function: (type) => MyOpfunc(type)
I suspect that's because the option is wrongly evaluated in the legacy context. Possibly relevant todo item:
Use the location where the option was set for deciding whether it's to be
evaluated in Vim9 script context.
As a workaround, we have to use the :legacy modifier:
legacy set operatorfunc={type\ ->\ MyOpfunc(type)}
^----^
Using the example given at :help g@:
vim9script nnoremap <expr> <F4> <SID>CountSpaces() xnoremap <expr> <F4> <SID>CountSpaces() nnoremap <expr> <F4><F4> <SID>CountSpaces() .. '_' def CountSpaces(type = ''): string if type == '' legacy set operatorfunc={type\ ->\ CountSpaces(type)} return 'g@' endif var sel_save: string = &selection var reg_save: dict<any> = getreginfo('"') var cb_save: string = &clipboard var visual_marks_save: list<list<number>> = [getpos("'<"), getpos("'>")] try set clipboard= selection=inclusive var commands: dict<string> = {line: "'[V']y", char: "`[v`]y", block: "`[\<c-v>`]y"} silent execute 'noautocmd keepjumps normal! ' .. get(commands, type, '"') echom getreg('"')->count(' ') finally setreg('"', reg_save) setpos("'<", visual_marks_save[0]) setpos("'>", visual_marks_save[1]) &clipboard = cb_save &selection = sel_save endtry return '' enddef 'a b c d e'->setline(1) feedkeys("\<F4>\<F4>")
What's weird is that we don't have to specify the s: prefix in the legacy lambda in front of the script-local function name. Usually, in the legacy context, s: is mandatory; it can only be dropped in the Vim9 context.
This could be handy for when the opfunc is a script-local function. We can't write this:
set operatorfunc=s:MyOpfuncBecause it raises E120:
E120: Using <SID> not in a script context: s:MyOpfuncSo, we have to write this:
let &operatorfunc = expand('<SID>') .. 'MyOpfunc'Which looks a bit weird.
But with a lambda, we could write this instead:
set operatorfunc={type\ ->\ s:MyOpfunc(type)}One could argue that it still looks weird. I still prefer reading a lambda which can be used in many other contexts, rather than
expand('<SID>'), which is less often used.
Just 2 remarks. It works with
:setbut not with:let. That is, we cannot write this:let &operatorfunc = {type -> s:MyOpfunc(type)}Because it raises
E729:E729: Using a Funcref as a StringIt still doesn't work if we manually coerce the lambda into a string:
let &operatorfunc = {type -> s:MyOpfunc(type)}->string() ^--------^Because this time, it raises
E129:E129: Function name requiredIt would be nice if could work so that we don't have to escape spaces:
# ugly set operatorfunc={type\ ->\ s:MyOpfunc(type)} ^ ^ # nicer let &operatorfunc = {type -> s:MyOpfunc(type)} ^ ^
Also, it doesn't work with a Vim9 lambda. That is, in a Vim9 script/function, we cannot write this:
set operatorfunc=(type)\ =>\ MyOpfunc(type)
Because it raises
E117:E117: Unknown function: (type) => MyOpfunc(type)I suspect that's because the option is wrongly evaluated in the legacy context. Possibly relevant todo item:
Use the location where the option was set for deciding whether it's to be
evaluated in Vim9 script context.As a workaround, we have to use the
:legacymodifier:legacy set operatorfunc={type\ ->\ MyOpfunc(type)} ^----^Using the example given at
:help g@:
There are several options that use a string value which is the name of a function.
Most functions, also lambdas, have a string name, some with a non-alpha prefix.
That allows using any function, so long as we can get the name as a string.
Then we could allow using:
let &operatorfunc = {type -> [some expression]}
And also:
let &operatorfunc = s:SomeFunc
Keeping the option type a string avoids having to deal with a different option value in very many places.
We just need to add a flag to the options that use a function name, and covert the function reference to a name for these.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub.
Finally had time to look into the patch. It does make sense, I think we can use his for all options that take the name of a function as an argument.
The use of function() and funcref() is not documented. We should make a separate section in the help, with some examples, and link to it from the options that support this format.
We have to make sure that the callback is cleared when exiting. The asan build doesn't report a leak, but that's probably because the tests end with making the option empty.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub.
It seems that we can use a partial in a legacy function:
vim9script nnoremap <expr> zd <SID>ZdSetup('zd') function ZdSetup(cmd) set operatorfunc=function('s:Zd',\ [a:cmd]) return 'g@l' endfunction def Zd(cmd: string, type: string) execute 'normal! ' .. cmd enddef var lines =<< trim END some folded lines {{{ some folded lines some folded lines }}} END lines->setline(1) &foldmethod = 'marker' normal zd
the fold is correctly deleted
But not in a Vim9 function:
vim9script nnoremap <expr> zd <SID>ZdSetup('zd') def ZdSetup(cmd: string): string set operatorfunc=function(Zd,\ [cmd]) return 'g@l' enddef def Zd(cmd: string, type: string) execute 'normal! ' .. cmd enddef var lines =<< trim END some folded lines {{{ some folded lines some folded lines }}} END lines->setline(1) &foldmethod = 'marker' normal zd
E121: Undefined variable: cmd
Am I missing something? Shouldn't Vim be able to find the cmd argument in a :def function:
set operatorfunc=function(Zd,\ [cmd])
^^^
just like it is able to in a legacy function:
set operatorfunc=function('s:Zd',\ [a:cmd])
^---^
Note that the issue is not caused by the omission of the s: scope in front of Zd, nor by the omission of the quotes around. None of them are required in the Vim9 context. And it doesn't suppress the error here anyway.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub.
Sorry, I think it's the same issue as the one reported earlier about the lambdas:
Also, it doesn't work with a Vim9 lambda. That is, in a Vim9 script/function, we cannot write this:
set operatorfunc=(type)\ =>\ MyOpfunc(type)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub.
Finally had time to look into the patch. It does make sense, I think we can use his for all options that take the name of a function as an argument.
The use of function() and funcref() is not documented. We should make a separate section in the help, with some examples, and link to it from the options that support this format.
We have to make sure that the callback is cleared when exiting. The asan build doesn't report a leak, but that's probably because the tests end with making the option empty.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub.
Finally had time to look into the patch. It does make sense, I think we can use his for all options that take the name of a function as an argument.
The use of function() and funcref() is not documented. We should make a separate section in the help, with some examples, and link to it from the options that support this format.
We have to make sure that the callback is cleared when exiting. The asan build doesn't report a leak, but that's probably because the tests end with making the option empty.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub.
This could be handy for when the opfunc is a script-local function. We can't write this:
set operatorfunc=s:MyOpfunc
Because it raises E120:
E120: Using <SID> not in a script context: s:MyOpfuncSo, we have to write this:
let &operatorfunc = expand('<SID>') .. 'MyOpfunc'Which looks a bit weird.
But with a lambda, we could write this instead:
set operatorfunc={type\ ->\ s:MyOpfunc(type)}One could argue that it still looks weird. I still prefer reading a lambda which can be used in many other contexts, rather than
expand('<SID>'), which is less often used.
Just 2 remarks. It works with
:setbut not with:let. That is, we cannot write this:let &operatorfunc = {type -> s:MyOpfunc(type)}
Because it raises
E729:E729: Using a Funcref as a StringIt still doesn't work if we manually coerce the lambda into a string:
let &operatorfunc = {type -> s:MyOpfunc(type)}->string() ^--------^
Because this time, it raises
E129:E129: Function name requiredIt would be nice if could work so that we don't have to escape spaces:
# ugly set operatorfunc={type\ ->\ s:MyOpfunc(type)} ^ ^ # nicer let &operatorfunc = {type -> s:MyOpfunc(type)} ^ ^Also, it doesn't work with a Vim9 lambda. That is, in a Vim9 script/function, we cannot write this:
set operatorfunc=(type)\ =>\ MyOpfunc(type)
Because it raises
E117:E117: Unknown function: (type) => MyOpfunc(type)I suspect that's because the option is wrongly evaluated in the legacy context. Possibly relevant todo item:
Use the location where the option was set for deciding whether it's to be
evaluated in Vim9 script context.As a workaround, we have to use the
:legacymodifier:legacy set operatorfunc={type\ ->\ MyOpfunc(type)} ^----^
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub.
Thank you very much for all your work on this. I don't know whether it's planned at some point, but we can still not set an opfunc with a simple assignment in Vim9:
vim9scriptnnoremap <expr> <F4><F4> <SID>CountSpaces() .. '_' def CountSpaces(type = ''): string if type == ''
&operatorfunc = (t) => CountSpaces(t)
return 'g@'
endif
normal! '[V']y
echomsg getreg('"')->count(' ')
return ''
enddef
'a b c d e'->setline(1) feedkeys("\<F4>\<F4>")
E1012: Type mismatch; expected string but got func(any): string
The issue comes from this line:
&operatorfunc = (t) => CountSpaces(t)
Which works in legacy:
legacy let &operatorfunc = {t -> CountSpaces(t)}
Test:
vim9scriptnnoremap <expr> <F4><F4> <SID>CountSpaces() .. '_' def CountSpaces(type = ''): string if type == ''
legacy let &operatorfunc = {t -> CountSpaces(t)}
return 'g@'
endif
normal! '[V']y
echomsg getreg('"')->count(' ')
return ''
enddef
'a b c d e'->setline(1) feedkeys("\<F4>\<F4>")
4
Also, still in Vim9, we can not use a partial; neither with :set:
set operatorfunc=function(Zd,\ [cmd])
Test:
vim9script nnoremap <expr> zd <SID>ZdSetup('zd') def ZdSetup(cmd: string): string set operatorfunc=function(Zd,\ [cmd]) return 'g@l' enddef def Zd(cmd: string, type: string) execute 'normal! ' .. cmd enddef var lines =<< trim END some folded lines {{{ some folded lines some folded lines }}} END lines->setline(1) &foldmethod = 'marker' normal zd
E121: Undefined variable: cmd
nor with an assignment:
&operatorfunc = function(Zd, [cmd])
Test:
vim9script nnoremap <expr> zd <SID>ZdSetup('zd') def ZdSetup(cmd: string): string
&operatorfunc = function(Zd, [cmd])
return 'g@l' enddef def Zd(cmd: string, type: string) execute 'normal! ' .. cmd enddef var lines =<< trim END some folded lines {{{ some folded lines some folded lines }}} END lines->setline(1) &foldmethod = 'marker' normal zd
E1012: Type mismatch; expected string but got func(...): unknown
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub.
Thank you very much for all your work on this. I don't know whether it's planned at some point, but we can still not set an opfunc with a simple assignment in Vim9:
—
You are receiving this because you are subscribed to this thread.
The option assignment to a lambda in a :def function was implemented with 8.2.3765. I hope it works for you.
The "set" command is not compiled, thus it cannot use variables from its context. You can see this with ":disas":
set operatorfunc=function(Zd,\ [cmd])
0 EXEC set operatorfunc=function(Zd,\ [cmd])
The last example fails because the 'operatorfunc' option is set to the lambda, not the partial.
Perhaps we could make this work but since using a lambda is easier and already works, I don't think we need it.
—
You are receiving this because you commented.
Actually, using a lambda doesn't work, because the 'operatorfunc' calls the function without the context of where it was defined.