I am modifying some functions in my script to work on different vim versions. For example, the following Add() works fine on the latest vim which has vim9 feature,
1 if !exists(':def')
2 function! Add(x, y)
3 return a:x + a:y
4 endfunction
5 else
6 def! Add(x: number, y: number): number
7 return x + y
8 enddef
9 endif
10
11 echo Add(3, 5)
But on the old vim which does not have it, an error message is shown.
Line 7:
E133: :return not inside a function
I am wondering why vim checks the line 7. Is there a good approach to avoid the error? And is exists(':def') appropriate to check if vim9 or non-vim9?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.![]()
There might be a better way, but in the meantime, try this:
if exists(':def') != 2 fu Add(x, y) abort
return a:x + a:y
endfu
else
fu DefineAdd() abort
def Add(x: number, y: number): number
return x + y
enddef
endfu
call DefineAdd()
endif
echo Add(3, 5)I think you can put a finish just before the else
Using something like exists(':def') != 2 is probably not enough because :def was added pretty early, but there have been hundreds of bugs some of which might crash your Vim. I'd be very careful using vim9script in older Vim versions. Better use has('patch-8.2.XXXX') instead.
It is probably easier to separate the two versions into two files IMO, something like:
" File: plugin/calc.vim if has('patch-8.2.XXXX') command -bar Calculator call calc9#run(<q-args>) else command -bar Calculator call calc#run(<q-args>) endif
And then put the vim9script version into the file autoload/calc9.vim whereas the legacy version using :function into autoload/calc.vim. The same check can be done for mappings and autocommands.
Yes, vim9script is still under development. It is too early to release the script. Meanwhile, we can enjoy to implement the script using exists(':def') for different vim versions.
When it becomes officially available, I would expect that something like 'vim9script' is to be included in the feature-list, then we can check using has().
Separating into two files might be an ideal approach. But mixing them in a single file still can be attractive depending on the script. In my case, only time consuming/sensitive parts are to be implemented in both vim9 and legacy scripts in one file.
For small scripts it would be convenient to be able to keep using one file. Perhaps we can allow for "vim9script" after an if/endif block that is not executed. Thus if/endif itself would not count as a command when encountering "vim9script". Then this should work:
if !has('vim9script') ... legacy script implementation finish endif vim9script ... vim9script implementation
Hi, again.
As lacygoill mentioned above, has('vim9script') is available now and the following is still usable ad convenient on the latest 8.2.
if !has('vim9script')
fu Add(x, y) abort
return a:x + a:y
endfu
else
fu DefineAdd() abort
def Add(x: number, y: number): number
return x + y
enddef
endfu
call DefineAdd()
endif
But it is not described in vim9-mix. Is there any regression or disadvantage on it?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
The help at "vim9-mix" shows the preferred way to do this. I'm not sure why you would use this if/else construct, defining a :def function inside a legacy function (to be able to skip over the unknown :def command in an old Vim version). It looks more complicated.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Thank you for your reply. A main reason is defining not all but a few time-consuming functions in both legacy and vim9 scripts, on each different place, in a plugin/autoload file. Using :finish command, as described in "vim9-mix", does not allow to do that. I would like to make sure if that approach does not have any problem and negative impact. Or I would like to know if there would be more useful approach.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
FWIW: I am using this in vim-airline: https://github.com/vim-airline/vim-airline/blob/master/autoload/airline/highlighter.vim So far, I haven't heard any complaints
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Yes, that is a good option. But in my plugin, something like cpo restoring is needed at the end. So I am looking for another good option in which :finish command is not necessary
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Perhaps you can move some code to another script file, where items are exported, and using "import" in the main script file.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Like this, how would you think to mention another way in vim9-mix?
There is another way to define both syntax in any place in one script file:
" legacy script commands go here
...
if has('vim9script')
function DefineVim9script()
# Vim9 script commands go here
endfunction
call DefineVim9script()
endif
To replace the existing legacy functions, ":def!" should be used and overwrite them in the Vim9 script.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()
Like this, how would you think to mention another way in the vim9-mix?
(I reposted this. sorry if my previous post was not deleted.)
There is another way to define functions in both syntax in one script file:
function ABC()
" legacy script commands go here
endfunction
...
if has('vim9script')
function DefineVim9script()
def! ABC()
# Vim9 script commands go here
enddef
endfunction
call DefineVim9script()
endif
Note that ":def!" should be used to overwrite the legacy functions.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.![]()