mirror of
https://github.com/vim/vim
synced 2025-07-18 10:11:58 +00:00
Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
373c65104e | |||
7633fe595e | |||
38041da1c2 | |||
73fef33014 | |||
8d9437968b | |||
7fe875583b | |||
f5433fbfe4 | |||
da58134eed | |||
23c5527373 | |||
e55b1c098d | |||
820ffa567c | |||
a3b7fdc1bb | |||
8c524f76eb | |||
6797966dfc | |||
0cb5bcf583 | |||
845e0ee594 | |||
a190548e91 | |||
b326edf5b3 | |||
ef6746f637 | |||
280b0dc815 | |||
1089374130 | |||
7e380030c1 | |||
20298ce679 | |||
1e0b7b11db | |||
ec9b017b87 | |||
3b74b6b4bb | |||
c785b9a7f4 | |||
128d307963 | |||
c5b1c20b6b | |||
0779fab297 |
@ -8,6 +8,7 @@ cd src
|
||||
echo "Building MinGW 32bit console version"
|
||||
set PATH=c:\msys64\mingw32\bin;%PATH%
|
||||
mingw32-make.exe -f Make_ming.mak GUI=no OPTIMIZE=speed IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1
|
||||
.\vim -u NONE -c "redir @a | ver |0put a | wq" ver_ming.txt
|
||||
:: Save vim.exe before Make clean, moved back below.
|
||||
copy vim.exe testdir
|
||||
mingw32-make.exe -f Make_ming.mak clean
|
||||
@ -20,13 +21,14 @@ if "%FEATURE%" == "HUGE" (
|
||||
) ELSE (
|
||||
mingw32-make.exe -f Make_ming.mak OPTIMIZE=speed GUI=yes IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1
|
||||
)
|
||||
.\gvim -u NONE -c "redir @a | ver |0put a | wq" ver_ming.txt
|
||||
.\gvim -u NONE -c "redir @a | ver |0put a | wq" ver_ming_gui.txt
|
||||
|
||||
:: Filter out the progress bar from the build log
|
||||
sed -e "s/@<<$/@<< | sed -e 's#.*\\\\r.*##'/" Make_mvc.mak > Make_mvc2.mak
|
||||
|
||||
echo "Building MSVC 64bit console Version"
|
||||
nmake -f Make_mvc2.mak CPU=AMD64 OLE=no GUI=no IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1
|
||||
:: The executable is not used
|
||||
nmake -f Make_mvc2.mak clean
|
||||
|
||||
:: build MSVC huge version with python and channel support
|
||||
@ -43,6 +45,8 @@ if "%FEATURE%" == "HUGE" (
|
||||
move /Y testdir\vim.exe .
|
||||
echo "version output MinGW"
|
||||
type ver_ming.txt
|
||||
echo "version output MinGW GUI"
|
||||
type ver_ming_gui.txt
|
||||
echo "version output MVC"
|
||||
type ver_msvc.txt
|
||||
cd ..
|
||||
|
@ -1,4 +1,4 @@
|
||||
*eval.txt* For Vim version 8.2. Last change: 2020 Jun 14
|
||||
*eval.txt* For Vim version 8.2. Last change: 2020 Jun 17
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -3667,7 +3667,7 @@ complete_info([{what}])
|
||||
"function" User defined completion |i_CTRL-X_CTRL-U|
|
||||
"omni" Omni completion |i_CTRL-X_CTRL-O|
|
||||
"spell" Spelling suggestions |i_CTRL-X_s|
|
||||
"eval" |complete()| completion
|
||||
"eval" |complete()| completion
|
||||
"unknown" Other internal modes
|
||||
|
||||
If the optional {what} list argument is supplied, then only
|
||||
@ -4536,7 +4536,7 @@ flatten({list} [, {maxdepth}]) *flatten()*
|
||||
a very large number.
|
||||
The {list} is changed in place, make a copy first if you do
|
||||
not want that.
|
||||
*E900*
|
||||
*E900*
|
||||
{maxdepth} means how deep in nested lists changes are made.
|
||||
{list} is not modified when {maxdepth} is 0.
|
||||
{maxdepth} must be positive number.
|
||||
@ -5163,7 +5163,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
|
||||
highlight highlight groups
|
||||
history :history suboptions
|
||||
locale locale names (as output of locale -a)
|
||||
mapclear buffer argument
|
||||
mapclear buffer argument
|
||||
mapping mapping name
|
||||
menu menus
|
||||
messages |:messages| suboptions
|
||||
@ -5189,7 +5189,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
|
||||
If {type} is "cmdline", then the |cmdline-completion| result is
|
||||
returned. For example, to complete the possible values after
|
||||
a ":call" command: >
|
||||
echo getcompletion('call ', 'cmdline')
|
||||
echo getcompletion('call ', 'cmdline')
|
||||
<
|
||||
If there are no matches, an empty list is returned. An
|
||||
invalid value for {type} produces an error.
|
||||
@ -5770,8 +5770,8 @@ getwininfo([{winid}]) *getwininfo()*
|
||||
Returns information about windows as a List with Dictionaries.
|
||||
|
||||
If {winid} is given Information about the window with that ID
|
||||
is returned. If the window does not exist the result is an
|
||||
empty list.
|
||||
is returned, as a List with one item. If the window does not
|
||||
exist the result is an empty list.
|
||||
|
||||
Without {winid} information about all the windows in all the
|
||||
tab pages is returned.
|
||||
@ -8606,14 +8606,14 @@ searchcount([{options}]) *searchcount()*
|
||||
if result.total > result.maxcount &&
|
||||
\ result.current > result.maxcount
|
||||
return printf(' /%s [>%d/>%d]', @/,
|
||||
\ result.current, result.total)
|
||||
\ result.current, result.total)
|
||||
elseif result.total > result.maxcount
|
||||
return printf(' /%s [%d/>%d]', @/,
|
||||
\ result.current, result.total)
|
||||
\ result.current, result.total)
|
||||
endif
|
||||
endif
|
||||
return printf(' /%s [%d/%d]', @/,
|
||||
\ result.current, result.total)
|
||||
\ result.current, result.total)
|
||||
endfunction
|
||||
let &statusline .= '%{LastSearchCount()}'
|
||||
|
||||
@ -9386,7 +9386,9 @@ simplify({filename}) *simplify()*
|
||||
Unix) are not resolved. If the first path component in
|
||||
{filename} designates the current directory, this will be
|
||||
valid for the result as well. A trailing path separator is
|
||||
not removed either.
|
||||
not removed either. On Unix "//path" is unchanged, but
|
||||
"///path" is simplified to "/path" (this follows the Posix
|
||||
standard).
|
||||
Example: >
|
||||
simplify("./dir/.././/file/") == "./file/"
|
||||
< Note: The combination "dir/.." is only removed if "dir" is
|
||||
@ -9696,7 +9698,7 @@ state([{what}]) *state()*
|
||||
m halfway a mapping, :normal command, feedkeys() or
|
||||
stuffed command
|
||||
o operator pending or waiting for a command argument,
|
||||
e.g. after |f|
|
||||
e.g. after |f|
|
||||
a Insert mode autocomplete active
|
||||
x executing an autocommand
|
||||
w blocked on waiting, e.g. ch_evalexpr(), ch_read() and
|
||||
@ -10450,9 +10452,9 @@ terminalprops() *terminalprops()*
|
||||
If the |+termresponse| feature is missing then the result is
|
||||
an empty dictionary.
|
||||
|
||||
If "cursor_style" is 'y' then |t_RS| will be send to request the
|
||||
If "cursor_style" is 'y' then |t_RS| will be sent to request the
|
||||
current cursor style.
|
||||
If "cursor_blink_mode" is 'y' then |t_RC| will be send to
|
||||
If "cursor_blink_mode" is 'y' then |t_RC| will be sent to
|
||||
request the cursor blink status.
|
||||
"cursor_style" and "cursor_blink_mode" are also set if |t_u7|
|
||||
is not empty, Vim will detect the working of sending |t_RS|
|
||||
@ -10916,7 +10918,7 @@ win_screenpos({nr}) *win_screenpos()*
|
||||
GetWinid()->win_screenpos()
|
||||
<
|
||||
win_splitmove({nr}, {target} [, {options}]) *win_splitmove()*
|
||||
Move the window {nr} to a new split of the window {target}.
|
||||
Move the window {nr} to a new split of the window {target}.
|
||||
This is similar to moving to {target}, creating a new window
|
||||
using |:split| but having the same contents as window {nr}, and
|
||||
then closing {nr}.
|
||||
|
@ -1,4 +1,4 @@
|
||||
*mlang.txt* For Vim version 8.2. Last change: 2019 May 05
|
||||
*mlang.txt* For Vim version 8.2. Last change: 2020 Jun 16
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
|
@ -3897,6 +3897,7 @@ E105 mbyte.txt /*E105*
|
||||
E107 eval.txt /*E107*
|
||||
E108 eval.txt /*E108*
|
||||
E109 eval.txt /*E109*
|
||||
E1094 vim9.txt /*E1094*
|
||||
E11 cmdline.txt /*E11*
|
||||
E110 eval.txt /*E110*
|
||||
E111 eval.txt /*E111*
|
||||
@ -5798,6 +5799,7 @@ coding-style develop.txt /*coding-style*
|
||||
col() eval.txt /*col()*
|
||||
coldfusion.vim syntax.txt /*coldfusion.vim*
|
||||
collapse tips.txt /*collapse*
|
||||
collate-variable eval.txt /*collate-variable*
|
||||
color-xterm syntax.txt /*color-xterm*
|
||||
coloring syntax.txt /*coloring*
|
||||
colortest.vim syntax.txt /*colortest.vim*
|
||||
@ -9723,6 +9725,7 @@ v:charconvert_from eval.txt /*v:charconvert_from*
|
||||
v:charconvert_to eval.txt /*v:charconvert_to*
|
||||
v:cmdarg eval.txt /*v:cmdarg*
|
||||
v:cmdbang eval.txt /*v:cmdbang*
|
||||
v:collate eval.txt /*v:collate*
|
||||
v:completed_item eval.txt /*v:completed_item*
|
||||
v:count eval.txt /*v:count*
|
||||
v:count1 eval.txt /*v:count1*
|
||||
|
@ -1,4 +1,4 @@
|
||||
*testing.txt* For Vim version 8.2. Last change: 2020 Jun 13
|
||||
*testing.txt* For Vim version 8.2. Last change: 2020 Jun 15
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
|
@ -1,4 +1,4 @@
|
||||
*todo.txt* For Vim version 8.2. Last change: 2020 Jun 14
|
||||
*todo.txt* For Vim version 8.2. Last change: 2020 Jun 21
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -40,16 +40,16 @@ browser use: https://github.com/vim/vim/issues/1234
|
||||
|
||||
Include src/po/vim.pot ?
|
||||
|
||||
See if resizing a terminal can be fixed.
|
||||
|
||||
Vim9 script:
|
||||
Making everything work:
|
||||
- assignment to script var should check type
|
||||
- Compile: let [var, var] = expr
|
||||
share code for :let between compiled and uncompiled?
|
||||
- do not allow "let g:var = value", must drop "let"
|
||||
- Error for "g:var: string = 'value'"
|
||||
- Make func()->append('$') work - value is last argument, not first. #6305
|
||||
- possible memory leak in test_vim9_func through compile_nested_function.
|
||||
- memory leaks in test_vim9_expr
|
||||
- memory leaks in test_vim9_script
|
||||
- Test that a script-local function in Vim9 script cannot be deleted.
|
||||
- more return types depending on the first argument, like sort().
|
||||
- Check that when sourcing a Vim9 script, only the global items can be used.
|
||||
- Make "true" and "false" work in vim9script
|
||||
- Test that a function defined inside a :def function is local to that
|
||||
@ -240,10 +240,12 @@ Terminal emulator window:
|
||||
conversions.
|
||||
|
||||
Error numbers available:
|
||||
E489, E610, E611, E653, E856, E857, E861
|
||||
E489, E610, E611, E653, E856
|
||||
|
||||
Remove SPACE_IN_FILENAME ? It is only used for completion.
|
||||
|
||||
Patch to use collaction based sorting. (Christian Brabandt, #6229)
|
||||
|
||||
Can we detect true color support? https://gist.github.com/XVilka/8346728
|
||||
Try setting a color then request the current color, like using t_u7.
|
||||
|
||||
@ -272,6 +274,8 @@ The buffer list and windows are locked, no changes possible
|
||||
How about removing Atari MiNT support?
|
||||
src/Make_mint.mak, src/os_mint.h, matches with __MINT__
|
||||
|
||||
Patch to make :q work with local arglist. (Christian Brabandt, #6286)
|
||||
|
||||
Patch to fix drawing error with DirectX. (James Grant, #5688)
|
||||
Causes flicker on resizing. Workaround from Ken Takata.
|
||||
How about only setting the attribute when part of the Vim window is offscreen?
|
||||
@ -285,6 +289,8 @@ Motif: Build on Ubuntu can't enter any text in dialog text fields.
|
||||
Running test_gui and test_gui_init with Motif sometimes kills the window
|
||||
manager. Problem with Motif?
|
||||
|
||||
Patch to add :argdedupe. (Nir Lichtman, #6235)
|
||||
|
||||
:map output does not clear the reset of the command line.
|
||||
(#5623, also see #5962)
|
||||
|
||||
@ -1402,9 +1408,6 @@ the system encoding (usually utf-8).
|
||||
MS-Windows: use WS_HIDE instead of SW_SHOWMINNOACTIVE in os_win32.c?
|
||||
Otherwise task flickers in taskbar.
|
||||
|
||||
Should make ":@r" handle line continuation. (Cesar Romani, 2016 Jun 26)
|
||||
Also for ":@.".
|
||||
|
||||
Repeating 'opfunc' in a function only works once. (Tarmean, 2016 Jul 15, #925)
|
||||
|
||||
Have a way to get the call stack, in a function and from an exception.
|
||||
|
@ -211,7 +211,7 @@ will automatically delete it:
|
||||
- The flag that the file was modified is not set.
|
||||
- The process is not running.
|
||||
|
||||
You can programatically deal with this situation with the |FileChangedShell|
|
||||
You can programmatically deal with this situation with the |FileChangedShell|
|
||||
autocommand event.
|
||||
|
||||
|
||||
|
@ -112,7 +112,7 @@ Although it's shorter to do: >
|
||||
|
||||
Legacy Vim script does have type checking, but this happens at runtime, when
|
||||
the code is executed. And it's permissive, often a computation gives an
|
||||
unexpected value instead of reporting an error . Thus you can define a
|
||||
unexpected value instead of reporting an error. Thus you can define a
|
||||
function and think it's fine, but see a problem only later when it is called: >
|
||||
let s:collected = ''
|
||||
func ExtendAndReturn(add)
|
||||
@ -142,7 +142,7 @@ you did wrong: >
|
||||
|
||||
Vim9 script is strict, it uses the "+" operator only for numbers and floats.
|
||||
For string concatenation ".." must be used. This avoids mistakes and avoids
|
||||
the automatic conversion that gave a suprising result above. So you change
|
||||
the automatic conversion that gave a surprising result above. So you change
|
||||
the first line of the function to: >
|
||||
s:collected ..= add
|
||||
And now it works.
|
||||
|
@ -1,4 +1,4 @@
|
||||
*usr_toc.txt* For Vim version 8.2. Last change: 2020 Jun 11
|
||||
*usr_toc.txt* For Vim version 8.2. Last change: 2020 Jun 15
|
||||
|
||||
VIM USER MANUAL - by Bram Moolenaar
|
||||
|
||||
@ -340,6 +340,12 @@ Make Vim work as you like it.
|
||||
|45.4| Editing files with a different encoding
|
||||
|45.5| Entering language text
|
||||
|
||||
|usr_46.txt| Write plugins using Vim9 script
|
||||
|46.1| Introduction
|
||||
|46.2| Variable declarations
|
||||
|46.3| Functions and types
|
||||
|46.?| Using a Vim9 script from legacy script
|
||||
|
||||
==============================================================================
|
||||
Making Vim Run ~
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
*vim9.txt* For Vim version 8.2. Last change: 2020 Jun 14
|
||||
*vim9.txt* For Vim version 8.2. Last change: 2020 Jun 21
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -30,7 +30,7 @@ THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE
|
||||
|
||||
Vim script has been growing over time, while preserving backwards
|
||||
compatibility. That means bad choices from the past often can't be changed
|
||||
and compability with Vi restricts possible solutions. Execution is quite
|
||||
and compatibility with Vi restricts possible solutions. Execution is quite
|
||||
slow, each line is parsed every time it is executed.
|
||||
|
||||
The main goal of Vim9 script is to drastically improve performance. This is
|
||||
@ -68,7 +68,7 @@ In Vim script comments normally start with double quote. That can also be the
|
||||
start of a string, thus in many places it cannot be used. In Vim9 script a
|
||||
comment can also start with #. In Vi this is a command to list text with
|
||||
numbers, but you can also use `:number` for that. >
|
||||
let count = 0 # number of occurences
|
||||
let count = 0 # number of occurrences
|
||||
|
||||
To improve readability there must be a space between the command and the #
|
||||
that starts a comment. Note that #{ is the start of a dictionary, therefore
|
||||
@ -269,6 +269,13 @@ possible AFTER the operators. For example: >
|
||||
PosFunc(arg) :
|
||||
NegFunc(arg)
|
||||
|
||||
A special case is "->" for function call chains, it can appear in the next
|
||||
line: >
|
||||
let result = GetBuilder()
|
||||
->BuilderSetWidth(333)
|
||||
->BuilderSetHeight(777)
|
||||
->BuilderBuild()
|
||||
|
||||
Note that "enddef" cannot be used at the start of a continuation line, it ends
|
||||
the current function.
|
||||
|
||||
@ -566,7 +573,7 @@ defined (otherwise script-local) items: >
|
||||
|
||||
|
||||
Import ~
|
||||
*:import* *:imp*
|
||||
*:import* *:imp* *E1094*
|
||||
The exported items can be imported individually in another Vim9 script: >
|
||||
import EXPORTED_CONST from "thatscript.vim"
|
||||
import MyClass from "myclass.vim"
|
||||
@ -692,7 +699,7 @@ A, B and C, where A calls B, B calls C, and C calls A again. It's impossible
|
||||
to reorder the functions to avoid forward references.
|
||||
|
||||
An alternative would be to first scan through the file to locate items and
|
||||
figure out their type, so that forward refeferences are found, and only then
|
||||
figure out their type, so that forward references are found, and only then
|
||||
execute the script and compile the functions. This means the script has to be
|
||||
parsed twice, which is slower, and some conditions at the script level, such
|
||||
as checking if a feature is supported, are hard to use. An attempt was made
|
||||
|
@ -1,7 +1,7 @@
|
||||
" Vim support file to detect file types
|
||||
"
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2020 Jun 07
|
||||
" Last Change: 2020 Jun 15
|
||||
|
||||
" Listen very carefully, I will say this only once
|
||||
if exists("did_load_filetypes")
|
||||
@ -237,7 +237,7 @@ au BufNewFile,BufRead */etc/blkid.tab,*/etc/blkid.tab.old setf xml
|
||||
au BufNewFile,BufRead *bsd,*.bsdl setf bsdl
|
||||
|
||||
" Bazel (http://bazel.io)
|
||||
autocmd BufRead,BufNewFile *.bzl,WORKSPACE,BUILD.bazel setf bzl
|
||||
autocmd BufRead,BufNewFile *.bzl,WORKSPACE,BUILD.bazel setf bzl
|
||||
if has("fname_case")
|
||||
" There is another check for BUILD further below.
|
||||
autocmd BufRead,BufNewFile BUILD setf bzl
|
||||
@ -625,8 +625,8 @@ au BufNewFile,BufRead *.mo,*.gdmo setf gdmo
|
||||
au BufNewFile,BufRead *.ged,lltxxxxx.txt setf gedcom
|
||||
|
||||
" Git
|
||||
au BufNewFile,BufRead COMMIT_EDITMSG,MERGE_MSG,TAG_EDITMSG setf gitcommit
|
||||
au BufNewFile,BufRead *.git/config,.gitconfig,/etc/gitconfig setf gitconfig
|
||||
au BufNewFile,BufRead COMMIT_EDITMSG,MERGE_MSG,TAG_EDITMSG setf gitcommit
|
||||
au BufNewFile,BufRead *.git/config,.gitconfig,/etc/gitconfig setf gitconfig
|
||||
au BufNewFile,BufRead */.config/git/config setf gitconfig
|
||||
au BufNewFile,BufRead .gitmodules,*.git/modules/*/config setf gitconfig
|
||||
if !empty($XDG_CONFIG_HOME)
|
||||
@ -770,11 +770,11 @@ au BufNewFile,BufRead *.inf,*.INF setf inform
|
||||
au BufNewFile,BufRead */etc/initng/*/*.i,*.ii setf initng
|
||||
|
||||
" Innovation Data Processing
|
||||
au BufRead,BufNewFile upstream.dat\c,upstream.*.dat\c,*.upstream.dat\c setf upstreamdat
|
||||
au BufRead,BufNewFile fdrupstream.log,upstream.log\c,upstream.*.log\c,*.upstream.log\c,UPSTREAM-*.log\c setf upstreamlog
|
||||
au BufRead,BufNewFile upstream.dat\c,upstream.*.dat\c,*.upstream.dat\c setf upstreamdat
|
||||
au BufRead,BufNewFile fdrupstream.log,upstream.log\c,upstream.*.log\c,*.upstream.log\c,UPSTREAM-*.log\c setf upstreamlog
|
||||
au BufRead,BufNewFile upstreaminstall.log\c,upstreaminstall.*.log\c,*.upstreaminstall.log\c setf upstreaminstalllog
|
||||
au BufRead,BufNewFile usserver.log\c,usserver.*.log\c,*.usserver.log\c setf usserverlog
|
||||
au BufRead,BufNewFile usw2kagt.log\c,usw2kagt.*.log\c,*.usw2kagt.log\c setf usw2kagtlog
|
||||
au BufRead,BufNewFile usserver.log\c,usserver.*.log\c,*.usserver.log\c setf usserverlog
|
||||
au BufRead,BufNewFile usw2kagt.log\c,usw2kagt.*.log\c,*.usw2kagt.log\c setf usw2kagtlog
|
||||
|
||||
" Ipfilter
|
||||
au BufNewFile,BufRead ipf.conf,ipf6.conf,ipf.rules setf ipfilter
|
||||
@ -1073,7 +1073,7 @@ au BufNewFile,BufRead Mutt{ng,}rc setf muttrc
|
||||
au BufRead,BufNewfile *.n1ql,*.nql setf n1ql
|
||||
|
||||
" Nano
|
||||
au BufNewFile,BufRead */etc/nanorc,*.nanorc setf nanorc
|
||||
au BufNewFile,BufRead */etc/nanorc,*.nanorc setf nanorc
|
||||
|
||||
" Nastran input/DMAP
|
||||
"au BufNewFile,BufRead *.dat setf nastran
|
||||
@ -1156,7 +1156,7 @@ au BufNewFile,BufRead *.dpr setf pascal
|
||||
au BufNewFile,BufRead *.pdf setf pdf
|
||||
|
||||
" PCMK - HAE - crm configure edit
|
||||
au BufNewFile,BufRead *.pcmk setf pcmk
|
||||
au BufNewFile,BufRead *.pcmk setf pcmk
|
||||
|
||||
" Perl
|
||||
if has("fname_case")
|
||||
@ -1646,10 +1646,10 @@ au BufNewFile,BufRead *.cm setf voscm
|
||||
|
||||
" Swift
|
||||
au BufNewFile,BufRead *.swift setf swift
|
||||
au BufNewFile,BufRead *.swift.gyb setf swiftgyb
|
||||
au BufNewFile,BufRead *.swift.gyb setf swiftgyb
|
||||
|
||||
" Swift Intermediate Language
|
||||
au BufNewFile,BufRead *.sil setf sil
|
||||
au BufNewFile,BufRead *.sil setf sil
|
||||
|
||||
" Sysctl
|
||||
au BufNewFile,BufRead */etc/sysctl.conf,*/etc/sysctl.d/*.conf setf sysctl
|
||||
@ -2066,7 +2066,7 @@ au BufNewFile,BufRead *fvwm2rc*
|
||||
au BufNewFile,BufRead */tmp/lltmp* call s:StarSetf('gedcom')
|
||||
|
||||
" Git
|
||||
au BufNewFile,BufRead */.gitconfig.d/*,/etc/gitconfig.d/* call s:StarSetf('gitconfig')
|
||||
au BufNewFile,BufRead */.gitconfig.d/*,/etc/gitconfig.d/* call s:StarSetf('gitconfig')
|
||||
|
||||
" Gitolite
|
||||
au BufNewFile,BufRead */gitolite-admin/conf/* call s:StarSetf('gitolite')
|
||||
|
@ -1,7 +1,7 @@
|
||||
" Vim filetype plugin
|
||||
" Language: Vim
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2020 May 17
|
||||
" Last Change: 2020 Jun 16
|
||||
|
||||
" Only do this when not done yet for this buffer
|
||||
if exists("b:did_ftplugin")
|
||||
@ -83,8 +83,7 @@ endif
|
||||
if exists("loaded_matchit")
|
||||
let b:match_ignorecase = 0
|
||||
let b:match_words =
|
||||
\ '\<fu\%[nction]\>:\<retu\%[rn]\>:\<endf\%[unction]\>,' .
|
||||
\ '\<def\>:\<retu\%[rn]\>:\<enddef\>,' .
|
||||
\ '\<\%(fu\%[nction]\|def\)\>:\<retu\%[rn]\>:\<\%(endf\%[unction]\|enddef\)\>,' .
|
||||
\ '\<\(wh\%[ile]\|for\)\>:\<brea\%[k]\>:\<con\%[tinue]\>:\<end\(w\%[hile]\|fo\%[r]\)\>,' .
|
||||
\ '\<if\>:\<el\%[seif]\>:\<en\%[dif]\>,' .
|
||||
\ '{:},' .
|
||||
|
@ -2,7 +2,7 @@
|
||||
" Header: "{{{
|
||||
" Maintainer: Bram Moolenaar
|
||||
" Original Author: Andy Wokula <anwoku@yahoo.de>
|
||||
" Last Change: 2019 Mar 20
|
||||
" Last Change: 2020 Jun 18
|
||||
" Version: 1.0
|
||||
" Description: HTML indent script with cached state for faster indenting on a
|
||||
" range of lines.
|
||||
@ -223,7 +223,7 @@ endfunc "}}}
|
||||
call s:AddITags(s:indent_tags, [
|
||||
\ 'a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big',
|
||||
\ 'blockquote', 'body', 'button', 'caption', 'center', 'cite', 'code',
|
||||
\ 'colgroup', 'del', 'dfn', 'dir', 'div', 'dl', 'em', 'fieldset', 'font',
|
||||
\ 'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'fieldset', 'font',
|
||||
\ 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html',
|
||||
\ 'i', 'iframe', 'ins', 'kbd', 'label', 'legend', 'li',
|
||||
\ 'map', 'menu', 'noframes', 'noscript', 'object', 'ol',
|
||||
|
@ -23,4 +23,14 @@ bar">
|
||||
text
|
||||
</div>
|
||||
|
||||
<dl>
|
||||
<dd>
|
||||
dd text
|
||||
</dd>
|
||||
<dt>
|
||||
dt text
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
|
||||
" END_INDENT
|
||||
|
@ -23,4 +23,14 @@
|
||||
text
|
||||
</div>
|
||||
|
||||
<dl>
|
||||
<dd>
|
||||
dd text
|
||||
</dd>
|
||||
<dt>
|
||||
dt text
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
|
||||
" END_INDENT
|
||||
|
@ -1,6 +1,6 @@
|
||||
" Vim plugin for showing matching parens
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2019 Oct 28
|
||||
" Last Change: 2020 Jun 18
|
||||
|
||||
" Exit quickly when:
|
||||
" - this plugin was already loaded (or disabled)
|
||||
@ -21,6 +21,7 @@ endif
|
||||
augroup matchparen
|
||||
" Replace all matchparen autocommands
|
||||
autocmd! CursorMoved,CursorMovedI,WinEnter * call s:Highlight_Matching_Pair()
|
||||
autocmd! WinLeave * call s:Remove_Matches()
|
||||
if exists('##TextChanged')
|
||||
autocmd! TextChanged,TextChangedI * call s:Highlight_Matching_Pair()
|
||||
endif
|
||||
@ -38,10 +39,7 @@ set cpo-=C
|
||||
" for any matching paren.
|
||||
func s:Highlight_Matching_Pair()
|
||||
" Remove any previous match.
|
||||
if exists('w:paren_hl_on') && w:paren_hl_on
|
||||
silent! call matchdelete(3)
|
||||
let w:paren_hl_on = 0
|
||||
endif
|
||||
call s:Remove_Matches()
|
||||
|
||||
" Avoid that we remove the popup menu.
|
||||
" Return when there are no colors (looks like the cursor jumps).
|
||||
@ -195,6 +193,14 @@ func s:Highlight_Matching_Pair()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
func s:Remove_Matches()
|
||||
if exists('w:paren_hl_on') && w:paren_hl_on
|
||||
silent! call matchdelete(3)
|
||||
let w:paren_hl_on = 0
|
||||
endif
|
||||
endfunc
|
||||
|
||||
|
||||
" Define commands that will disable and enable the plugin.
|
||||
command DoMatchParen call s:DoMatchParen()
|
||||
command NoMatchParen call s:NoMatchParen()
|
||||
|
@ -253,7 +253,7 @@ eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
|
||||
return FAIL;
|
||||
|
||||
if (partial->pt_func != NULL
|
||||
&& partial->pt_func->uf_dfunc_idx != UF_NOT_COMPILED)
|
||||
&& partial->pt_func->uf_def_status != UF_NOT_COMPILED)
|
||||
{
|
||||
if (call_def_function(partial->pt_func, argc, argv,
|
||||
partial, rettv) == FAIL)
|
||||
|
@ -6002,11 +6002,11 @@ static int srand_seed_for_testing_is_used = FALSE;
|
||||
f_test_srand_seed(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
if (argvars[0].v_type == VAR_UNKNOWN)
|
||||
srand_seed_for_testing_is_used = FALSE;
|
||||
srand_seed_for_testing_is_used = FALSE;
|
||||
else
|
||||
{
|
||||
srand_seed_for_testing = (UINT32_T)tv_get_number(&argvars[0]);
|
||||
srand_seed_for_testing_is_used = TRUE;
|
||||
srand_seed_for_testing = (UINT32_T)tv_get_number(&argvars[0]);
|
||||
srand_seed_for_testing_is_used = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6019,7 +6019,7 @@ init_srand(UINT32_T *x)
|
||||
|
||||
if (srand_seed_for_testing_is_used)
|
||||
{
|
||||
*x = srand_seed_for_testing;
|
||||
*x = srand_seed_for_testing;
|
||||
return;
|
||||
}
|
||||
#ifndef MSWIN
|
||||
@ -7268,6 +7268,37 @@ f_setpos(typval_T *argvars, typval_T *rettv)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a register type string to the yank type and block length
|
||||
*/
|
||||
static int
|
||||
get_yank_type(char_u **pp, char_u *yank_type, long *block_len)
|
||||
{
|
||||
char_u *stropt = *pp;
|
||||
switch (*stropt)
|
||||
{
|
||||
case 'v': case 'c': // character-wise selection
|
||||
*yank_type = MCHAR;
|
||||
break;
|
||||
case 'V': case 'l': // line-wise selection
|
||||
*yank_type = MLINE;
|
||||
break;
|
||||
case 'b': case Ctrl_V: // block-wise selection
|
||||
*yank_type = MBLOCK;
|
||||
if (VIM_ISDIGIT(stropt[1]))
|
||||
{
|
||||
++stropt;
|
||||
*block_len = getdigits(&stropt) - 1;
|
||||
--stropt;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FAIL;
|
||||
}
|
||||
*pp = stropt;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* "setreg()" function
|
||||
*/
|
||||
@ -7302,30 +7333,31 @@ f_setreg(typval_T *argvars, typval_T *rettv)
|
||||
if (argvars[1].v_type == VAR_DICT)
|
||||
{
|
||||
dict_T *d = argvars[1].vval.v_dict;
|
||||
dictitem_T *di = dict_find(d, (char_u *)"regcontents", -1);
|
||||
dictitem_T *di;
|
||||
|
||||
if (d == NULL || d->dv_hashtab.ht_used == 0)
|
||||
{
|
||||
// Empty dict, clear the register (like setreg(0, []))
|
||||
char_u *lstval[2] = {NULL, NULL};
|
||||
write_reg_contents_lst(regname, lstval, 0, FALSE, MAUTO, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
di = dict_find(d, (char_u *)"regcontents", -1);
|
||||
if (di != NULL)
|
||||
regcontents = &di->di_tv;
|
||||
|
||||
stropt = dict_get_string(d, (char_u *)"regtype", FALSE);
|
||||
if (stropt != NULL)
|
||||
switch (*stropt)
|
||||
{
|
||||
int ret = get_yank_type(&stropt, &yank_type, &block_len);
|
||||
|
||||
if (ret == FAIL || *++stropt != NUL)
|
||||
{
|
||||
case 'v': // character-wise selection
|
||||
yank_type = MCHAR;
|
||||
break;
|
||||
case 'V': // line-wise selection
|
||||
yank_type = MLINE;
|
||||
break;
|
||||
case Ctrl_V: // block-wise selection
|
||||
yank_type = MBLOCK;
|
||||
if (VIM_ISDIGIT(stropt[1]))
|
||||
{
|
||||
++stropt;
|
||||
block_len = getdigits(&stropt) - 1;
|
||||
--stropt;
|
||||
}
|
||||
break;
|
||||
semsg(_(e_invargval), "value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (regname == '"')
|
||||
{
|
||||
@ -7344,6 +7376,12 @@ f_setreg(typval_T *argvars, typval_T *rettv)
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
if (yank_type != MAUTO)
|
||||
{
|
||||
semsg(_(e_toomanyarg), "setreg");
|
||||
return;
|
||||
}
|
||||
|
||||
stropt = tv_get_string_chk(&argvars[2]);
|
||||
if (stropt == NULL)
|
||||
return; // type error
|
||||
@ -7353,21 +7391,8 @@ f_setreg(typval_T *argvars, typval_T *rettv)
|
||||
case 'a': case 'A': // append
|
||||
append = TRUE;
|
||||
break;
|
||||
case 'v': case 'c': // character-wise selection
|
||||
yank_type = MCHAR;
|
||||
break;
|
||||
case 'V': case 'l': // line-wise selection
|
||||
yank_type = MLINE;
|
||||
break;
|
||||
case 'b': case Ctrl_V: // block-wise selection
|
||||
yank_type = MBLOCK;
|
||||
if (VIM_ISDIGIT(stropt[1]))
|
||||
{
|
||||
++stropt;
|
||||
block_len = getdigits(&stropt) - 1;
|
||||
--stropt;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
get_yank_type(&stropt, &yank_type, &block_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1204,6 +1204,13 @@ ex_let_one(
|
||||
emsg(_("E996: Cannot lock an environment variable"));
|
||||
return NULL;
|
||||
}
|
||||
if (current_sctx.sc_version == SCRIPT_VERSION_VIM9
|
||||
&& (flags & LET_NO_COMMAND) == 0)
|
||||
{
|
||||
vim9_declare_error(arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find the end of the name.
|
||||
++arg;
|
||||
name = arg;
|
||||
@ -2628,7 +2635,7 @@ find_var_ht(char_u *name, char_u **varname)
|
||||
if (*name == 'v') // v: variable
|
||||
return &vimvarht;
|
||||
if (get_current_funccal() != NULL
|
||||
&& get_current_funccal()->func->uf_dfunc_idx == UF_NOT_COMPILED)
|
||||
&& get_current_funccal()->func->uf_def_status == UF_NOT_COMPILED)
|
||||
{
|
||||
// a: and l: are only used in functions defined with ":function"
|
||||
if (*name == 'a') // a: function argument
|
||||
@ -2866,6 +2873,15 @@ set_var_const(
|
||||
}
|
||||
is_script_local = ht == get_script_local_ht();
|
||||
|
||||
if (current_sctx.sc_version == SCRIPT_VERSION_VIM9
|
||||
&& !is_script_local
|
||||
&& (flags & LET_NO_COMMAND) == 0
|
||||
&& name[1] == ':')
|
||||
{
|
||||
vim9_declare_error(name);
|
||||
return;
|
||||
}
|
||||
|
||||
di = find_var_in_ht(ht, 0, varname, TRUE);
|
||||
|
||||
// Search in parent scope which is possible to reference from lambda
|
||||
@ -2886,10 +2902,6 @@ set_var_const(
|
||||
return;
|
||||
}
|
||||
|
||||
if (var_check_ro(di->di_flags, name, FALSE)
|
||||
|| var_check_lock(di->di_tv.v_lock, name, FALSE))
|
||||
return;
|
||||
|
||||
if (is_script_local
|
||||
&& current_sctx.sc_version == SCRIPT_VERSION_VIM9)
|
||||
{
|
||||
@ -2900,8 +2912,13 @@ set_var_const(
|
||||
}
|
||||
|
||||
// check the type
|
||||
check_script_var_type(&di->di_tv, tv, name);
|
||||
if (check_script_var_type(&di->di_tv, tv, name) == FAIL)
|
||||
return;
|
||||
}
|
||||
|
||||
if (var_check_ro(di->di_flags, name, FALSE)
|
||||
|| var_check_lock(di->di_tv.v_lock, name, FALSE))
|
||||
return;
|
||||
}
|
||||
else
|
||||
// can only redefine once
|
||||
|
@ -1788,6 +1788,8 @@ EXTERN char e_no_white_before[] INIT(= N_("E1068: No white space allowed before
|
||||
EXTERN char e_lock_unlock[] INIT(= N_("E940: Cannot lock or unlock variable %s"));
|
||||
EXTERN char e_const_req_value[] INIT(= N_("E1021: const requires a value"));
|
||||
EXTERN char e_type_req[] INIT(= N_("E1022: type or initialization required"));
|
||||
EXTERN char e_declare_var[] INIT(= N_("E1016: Cannot declare a %s variable: %s"));
|
||||
EXTERN char e_declare_env_var[] INIT(= N_("E1016: Cannot declare an environment variable: %s"));
|
||||
#endif
|
||||
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
|
||||
EXTERN char e_alloc_color[] INIT(= N_("E254: Cannot allocate color %s"));
|
||||
|
@ -1211,15 +1211,19 @@ key_press_event(GtkWidget *widget UNUSED,
|
||||
if (len == 0) // Unrecognized key
|
||||
return TRUE;
|
||||
|
||||
// Handle modifiers.
|
||||
modifiers = modifiers_gdk2vim(state);
|
||||
|
||||
// For some keys a shift modifier is translated into another key code.
|
||||
if (len == -3)
|
||||
key = TO_SPECIAL(string[1], string[2]);
|
||||
else
|
||||
key = string[0];
|
||||
{
|
||||
string[len] = NUL;
|
||||
key = mb_ptr2char(string);
|
||||
}
|
||||
|
||||
// Handle modifiers.
|
||||
modifiers = modifiers_gdk2vim(state);
|
||||
|
||||
// Recognize special keys.
|
||||
key = simplify_key(key, &modifiers);
|
||||
if (key == CSI)
|
||||
key = K_CSI;
|
||||
@ -1235,8 +1239,11 @@ key_press_event(GtkWidget *widget UNUSED,
|
||||
// <C-H> and <C-h> mean the same thing, always use "H"
|
||||
if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key))
|
||||
key = TOUPPER_ASC(key);
|
||||
string[0] = key;
|
||||
len = 1;
|
||||
|
||||
// May remove the shift modifier if it's included in the key.
|
||||
modifiers = may_remove_shift_modifier(modifiers, key);
|
||||
|
||||
len = mb_char2bytes(key, string);
|
||||
}
|
||||
|
||||
if (modifiers != 0)
|
||||
|
@ -938,7 +938,10 @@ gui_x11_key_hit_cb(
|
||||
if (len == -3)
|
||||
key = TO_SPECIAL(string[1], string[2]);
|
||||
else
|
||||
key = string[0];
|
||||
{
|
||||
string[len] = NUL;
|
||||
key = mb_ptr2char(string);
|
||||
}
|
||||
key = simplify_key(key, &modifiers);
|
||||
if (key == CSI)
|
||||
key = K_CSI;
|
||||
@ -951,8 +954,7 @@ gui_x11_key_hit_cb(
|
||||
}
|
||||
else
|
||||
{
|
||||
string[0] = key;
|
||||
len = 1;
|
||||
len = mb_char2bytes(key, string);
|
||||
|
||||
// Remove the SHIFT modifier for keys where it's already included,
|
||||
// e.g., '(', '!' and '*'.
|
||||
|
@ -658,6 +658,11 @@ S_SvREFCNT_dec(pTHX_ SV *sv)
|
||||
}
|
||||
# endif
|
||||
|
||||
/* perl-5.32 needs Perl_SvREFCNT_dec */
|
||||
# if (PERL_REVISION == 5) && (PERL_VERSION >= 32)
|
||||
# define Perl_SvREFCNT_dec S_SvREFCNT_dec
|
||||
# endif
|
||||
|
||||
/* perl-5.26 also needs S_TOPMARK and S_POPMARK. */
|
||||
# if (PERL_REVISION == 5) && (PERL_VERSION >= 26)
|
||||
PERL_STATIC_INLINE I32
|
||||
@ -682,6 +687,20 @@ S_POPMARK(pTHX)
|
||||
}
|
||||
# endif
|
||||
|
||||
/* perl-5.32 needs Perl_POPMARK */
|
||||
# if (PERL_REVISION == 5) && (PERL_VERSION >= 32)
|
||||
# define Perl_POPMARK S_POPMARK
|
||||
|
||||
/* perl-5.32 needs Perl_SvTRUE */
|
||||
PERL_STATIC_INLINE bool
|
||||
Perl_SvTRUE(pTHX_ SV *sv) {
|
||||
if (!LIKELY(sv))
|
||||
return FALSE;
|
||||
SvGETMAGIC(sv);
|
||||
return SvTRUE_nomg_NN(sv);
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Make all runtime-links of perl.
|
||||
*
|
||||
|
@ -646,6 +646,12 @@ static int setlineinfo(int row, const VTermLineInfo *newinfo, const VTermLineInf
|
||||
newinfo->doubleheight != oldinfo->doubleheight) {
|
||||
for(col = 0; col < screen->cols; col++) {
|
||||
ScreenCell *cell = getcell(screen, row, col);
|
||||
if (cell == NULL)
|
||||
{
|
||||
DEBUG_LOG2("libvterm: setlineinfo() position invalid: %d / %d",
|
||||
row, col);
|
||||
return 1;
|
||||
}
|
||||
cell->pen.dwl = newinfo->doublewidth;
|
||||
cell->pen.dhl = newinfo->doubleheight;
|
||||
}
|
||||
@ -773,6 +779,12 @@ static size_t _get_chars(const VTermScreen *screen, const int utf8, void *buffer
|
||||
ScreenCell *cell = getcell(screen, row, col);
|
||||
int i;
|
||||
|
||||
if (cell == NULL)
|
||||
{
|
||||
DEBUG_LOG2("libvterm: _get_chars() position invalid: %d / %d",
|
||||
row, col);
|
||||
return 1;
|
||||
}
|
||||
if(cell->chars[0] == 0)
|
||||
// Erased cell, might need a space
|
||||
padding++;
|
||||
|
@ -17,11 +17,6 @@ static void putglyph(VTermState *state, const uint32_t chars[], int width, VTerm
|
||||
{
|
||||
VTermGlyphInfo info;
|
||||
|
||||
if (pos.row >= state->rows)
|
||||
{
|
||||
DEBUG_LOG2("libvterm: putglyph() pos.row %d out of range (rows = %d)\n", pos.row, state.rows);
|
||||
return;
|
||||
}
|
||||
info.chars = chars;
|
||||
info.width = width;
|
||||
info.protected_cell = state->protected_cell;
|
||||
@ -289,11 +284,6 @@ static int on_text(const char bytes[], size_t len, void *user)
|
||||
|
||||
VTermPos oldpos = state->pos;
|
||||
|
||||
if (state->pos.row >= state->rows)
|
||||
{
|
||||
DEBUG_LOG2("libvterm: on_text() pos.row %d out of range (rows = %d)\n", state->pos.row, state.rows);
|
||||
return 0;
|
||||
}
|
||||
// We'll have at most len codepoints, plus one from a previous incomplete
|
||||
// sequence.
|
||||
codepoints = vterm_allocator_malloc(state->vt, (len + 1) * sizeof(uint32_t));
|
||||
@ -1856,8 +1846,12 @@ static int on_resize(int rows, int cols, void *user)
|
||||
|
||||
if(state->pos.row >= rows)
|
||||
state->pos.row = rows - 1;
|
||||
if(state->pos.row < 0)
|
||||
state->pos.row = 0;
|
||||
if(state->pos.col >= cols)
|
||||
state->pos.col = cols - 1;
|
||||
if(state->pos.col < 0)
|
||||
state->pos.col = 0;
|
||||
|
||||
updatecursor(state, &oldpos, 1);
|
||||
|
||||
|
27
src/misc2.c
27
src/misc2.c
@ -2910,6 +2910,25 @@ find_special_key(
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Some keys already have Shift included, pass them as normal keys.
|
||||
* Not when Ctrl is also used, because <C-H> and <C-S-H> are different.
|
||||
* Also for <A-S-a> and <M-S-a>.
|
||||
*/
|
||||
int
|
||||
may_remove_shift_modifier(int modifiers, int key)
|
||||
{
|
||||
if ((modifiers == MOD_MASK_SHIFT
|
||||
|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_ALT)
|
||||
|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_META))
|
||||
&& ((key >= '@' && key <= 'Z')
|
||||
|| key == '^' || key == '_'
|
||||
|| (key >= '{' && key <= '~')))
|
||||
return modifiers & ~MOD_MASK_SHIFT;
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to include modifiers in the key.
|
||||
* Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc.
|
||||
@ -2929,9 +2948,11 @@ extract_modifiers(int key, int *modp, int simplify, int *did_simplify)
|
||||
if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key))
|
||||
{
|
||||
key = TOUPPER_ASC(key);
|
||||
// With <C-S-a> and <A-S-a> we keep the shift modifier.
|
||||
// With <S-a> and <S-A> we don't keep the shift modifier.
|
||||
if (simplify || modifiers == MOD_MASK_SHIFT)
|
||||
// With <C-S-a> we keep the shift modifier.
|
||||
// With <S-a>, <A-S-a> and <S-A> we don't keep the shift modifier.
|
||||
if (simplify || modifiers == MOD_MASK_SHIFT
|
||||
|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_ALT)
|
||||
|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_META))
|
||||
modifiers &= ~MOD_MASK_SHIFT;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ char_u *get_special_key_name(int c, int modifiers);
|
||||
int trans_special(char_u **srcp, char_u *dst, int flags, int *did_simplify);
|
||||
int special_to_buf(int key, int modifiers, int keycode, char_u *dst);
|
||||
int find_special_key(char_u **srcp, int *modp, int flags, int *did_simplify);
|
||||
int may_remove_shift_modifier(int modifiers, int key);
|
||||
int extract_modifiers(int key, int *modp, int simplify, int *did_simplify);
|
||||
int find_special_key_in_table(int c);
|
||||
int get_special_key_code(char_u *name);
|
||||
|
@ -10,10 +10,11 @@ int get_script_item_idx(int sid, char_u *name, int check_writable);
|
||||
imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx);
|
||||
char_u *to_name_const_end(char_u *arg);
|
||||
int assignment_len(char_u *p, int *heredoc);
|
||||
void vim9_declare_error(char_u *name);
|
||||
int check_vim9_unlet(char_u *name);
|
||||
int compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx);
|
||||
void set_function_type(ufunc_T *ufunc);
|
||||
void delete_instr(isn_T *isn);
|
||||
void delete_def_function(ufunc_T *ufunc);
|
||||
void clear_def_function(ufunc_T *ufunc);
|
||||
void free_def_functions(void);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -7,5 +7,5 @@ void ex_import(exarg_T *eap);
|
||||
int find_exported(int sid, char_u **argp, int *name_len, ufunc_T **ufunc, type_T **type);
|
||||
char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, void *cctx);
|
||||
char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg);
|
||||
void check_script_var_type(typval_T *dest, typval_T *value, char_u *name);
|
||||
int check_script_var_type(typval_T *dest, typval_T *value, char_u *name);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -1343,7 +1343,7 @@ do_source(
|
||||
|
||||
// Allocate the local script variables to use for this script.
|
||||
new_script_vars(script_items.ga_len);
|
||||
ga_init2(&si->sn_var_vals, sizeof(typval_T), 10);
|
||||
ga_init2(&si->sn_var_vals, sizeof(svar_T), 10);
|
||||
ga_init2(&si->sn_imports, sizeof(imported_T), 10);
|
||||
ga_init2(&si->sn_type_list, sizeof(type_T), 10);
|
||||
# ifdef FEAT_PROFILE
|
||||
@ -1873,7 +1873,7 @@ ex_scriptversion(exarg_T *eap UNUSED)
|
||||
nr = getdigits(&eap->arg);
|
||||
if (nr == 0 || *eap->arg != NUL)
|
||||
emsg(_(e_invarg));
|
||||
else if (nr > 4)
|
||||
else if (nr > SCRIPT_VERSION_MAX)
|
||||
semsg(_("E999: scriptversion not supported: %d"), nr);
|
||||
else
|
||||
{
|
||||
|
@ -67,6 +67,8 @@ typedef struct terminal_S term_T;
|
||||
typedef struct VimMenu vimmenu_T;
|
||||
#endif
|
||||
|
||||
// maximum value for sc_version
|
||||
#define SCRIPT_VERSION_MAX 4
|
||||
// value for sc_version in a Vim9 script file
|
||||
#define SCRIPT_VERSION_VIM9 999999
|
||||
|
||||
@ -1531,8 +1533,11 @@ struct blobvar_S
|
||||
typedef struct funccall_S funccall_T;
|
||||
|
||||
// values used for "uf_dfunc_idx"
|
||||
# define UF_NOT_COMPILED -2
|
||||
# define UF_TO_BE_COMPILED -1
|
||||
typedef enum {
|
||||
UF_NOT_COMPILED,
|
||||
UF_TO_BE_COMPILED,
|
||||
UF_COMPILED
|
||||
} def_status_T;
|
||||
|
||||
/*
|
||||
* Structure to hold info for a user function.
|
||||
@ -1543,7 +1548,8 @@ typedef struct
|
||||
int uf_flags; // FC_ flags
|
||||
int uf_calls; // nr of active calls
|
||||
int uf_cleared; // func_clear() was already called
|
||||
int uf_dfunc_idx; // UF_NOT_COMPILED, UF_TO_BE_COMPILED or >= 0
|
||||
def_status_T uf_def_status; // UF_NOT_COMPILED, UF_TO_BE_COMPILED, etc.
|
||||
int uf_dfunc_idx; // only valid if uf_def_status is UF_COMPILED
|
||||
garray_T uf_args; // arguments, including optional arguments
|
||||
garray_T uf_def_args; // default argument expressions
|
||||
|
||||
|
10
src/term.c
10
src/term.c
@ -4769,14 +4769,8 @@ handle_key_with_modifier(
|
||||
|
||||
modifiers = decode_modifiers(arg[1]);
|
||||
|
||||
// Some keys already have Shift included, pass them as
|
||||
// normal keys. Not when Ctrl is also used, because <C-H>
|
||||
// and <C-S-H> are different.
|
||||
if (modifiers == MOD_MASK_SHIFT
|
||||
&& ((key >= '@' && key <= 'Z')
|
||||
|| key == '^' || key == '_'
|
||||
|| (key >= '{' && key <= '~')))
|
||||
modifiers = 0;
|
||||
// May remove the shift modifier if it's already included in the key.
|
||||
modifiers = may_remove_shift_modifier(modifiers, key);
|
||||
|
||||
// When used with Ctrl we always make a letter upper case,
|
||||
// so that mapping <C-H> and <C-h> are the same. Typing
|
||||
|
@ -216,7 +216,15 @@ func RunTheTest(test)
|
||||
|
||||
let message = 'Executed ' . a:test
|
||||
if has('reltime')
|
||||
let message ..= ' in ' .. reltimestr(reltime(func_start)) .. ' seconds'
|
||||
let message ..= repeat(' ', 50 - len(message))
|
||||
let time = reltime(func_start)
|
||||
if has('float') && reltimefloat(time) > 0.1
|
||||
let message = &t_md .. message
|
||||
endif
|
||||
let message ..= ' in ' .. reltimestr(time) .. ' seconds'
|
||||
if has('float') && reltimefloat(time) > 0.1
|
||||
let message ..= &t_me
|
||||
endif
|
||||
endif
|
||||
call add(s:messages, message)
|
||||
let s:done += 1
|
||||
@ -284,7 +292,9 @@ func FinishTesting()
|
||||
let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
|
||||
endif
|
||||
if s:done > 0 && has('reltime')
|
||||
let message = &t_md .. message .. repeat(' ', 40 - len(message))
|
||||
let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
|
||||
let message ..= &t_me
|
||||
endif
|
||||
echo message
|
||||
call add(s:messages, message)
|
||||
|
@ -254,6 +254,7 @@ func Test_blob_func_remove()
|
||||
call assert_fails("call remove(b, 3, 2)", 'E979:')
|
||||
call assert_fails("call remove(1, 0)", 'E896:')
|
||||
call assert_fails("call remove(b, b)", 'E974:')
|
||||
call assert_fails("call remove(b, 1, [])", 'E745:')
|
||||
call assert_fails("call remove(test_null_blob(), 1, 2)", 'E979:')
|
||||
endfunc
|
||||
|
||||
|
@ -29,14 +29,14 @@ func SetUp()
|
||||
endif
|
||||
let s:chopt = {}
|
||||
call ch_log(g:testfunc)
|
||||
|
||||
" Most tests use job_start(), which can be flaky
|
||||
let g:test_is_flaky = 1
|
||||
endfunc
|
||||
|
||||
" Run "testfunc" after starting the server and stop the server afterwards.
|
||||
func s:run_server(testfunc, ...)
|
||||
call RunServer(s:testscript, a:testfunc, a:000)
|
||||
|
||||
" communicating with a server can be flaky
|
||||
let g:test_is_flaky = 1
|
||||
endfunc
|
||||
|
||||
" Return a list of open files.
|
||||
@ -455,7 +455,6 @@ endfunc
|
||||
func Test_connect_waittime()
|
||||
CheckFunction reltimefloat
|
||||
" this is timing sensitive
|
||||
let g:test_is_flaky = 1
|
||||
|
||||
let start = reltime()
|
||||
let handle = ch_open('localhost:9876', s:chopt)
|
||||
@ -1762,9 +1761,8 @@ func Test_write_to_deleted_buffer()
|
||||
endfunc
|
||||
|
||||
func Test_cmd_parsing()
|
||||
if !has('unix')
|
||||
return
|
||||
endif
|
||||
CheckUnix
|
||||
|
||||
call assert_false(filereadable("file with space"))
|
||||
let job = job_start('touch "file with space"')
|
||||
call WaitForAssert({-> assert_true(filereadable("file with space"))})
|
||||
@ -1963,9 +1961,7 @@ func Test_list_args()
|
||||
endfunc
|
||||
|
||||
func Test_keep_pty_open()
|
||||
if !has('unix')
|
||||
return
|
||||
endif
|
||||
CheckUnix
|
||||
|
||||
let job = job_start(s:python . ' -c "import time;time.sleep(0.2)"',
|
||||
\ {'out_io': 'null', 'err_io': 'null', 'pty': 1})
|
||||
@ -2047,9 +2043,7 @@ func Test_no_hang_windows()
|
||||
endfunc
|
||||
|
||||
func Test_job_exitval_and_termsig()
|
||||
if !has('unix')
|
||||
return
|
||||
endif
|
||||
CheckUnix
|
||||
|
||||
" Terminate job normally
|
||||
let cmd = ['echo']
|
||||
@ -2123,6 +2117,7 @@ endfunc
|
||||
|
||||
" Do this last, it stops any channel log.
|
||||
func Test_zz_nl_err_to_out_pipe()
|
||||
|
||||
eval 'Xlog'->ch_logfile()
|
||||
call ch_log('Test_zz_nl_err_to_out_pipe()')
|
||||
let job = job_start(s:python . " test_channel_pipe.py", {'err_io': 'out'})
|
||||
@ -2214,6 +2209,7 @@ endfunc
|
||||
func Test_job_trailing_space_unix()
|
||||
CheckUnix
|
||||
CheckExecutable cat
|
||||
|
||||
let job = job_start("cat ", #{in_io: 'null'})
|
||||
call WaitForAssert({-> assert_equal("dead", job_status(job))})
|
||||
call assert_equal(0, job_info(job).exitval)
|
||||
|
@ -246,6 +246,7 @@ func Test_cpo_H()
|
||||
endfunc
|
||||
|
||||
" TODO: Add a test for the 'i' flag in 'cpo'
|
||||
" Interrupting the reading of a file will leave it modified.
|
||||
|
||||
" Test for the 'I' flag in 'cpo' (deleting autoindent when using arrow keys)
|
||||
func Test_cpo_I()
|
||||
@ -294,9 +295,12 @@ func Test_cpo_J()
|
||||
let &cpo = save_cpo
|
||||
endfunc
|
||||
|
||||
" TODO: Add a test for the 'k' flag in 'cpo'
|
||||
" TODO: Add a test for the 'k' flag in 'cpo'.
|
||||
" Disable the recognition of raw key codes in mappings, abbreviations, and the
|
||||
" "to" part of menu commands.
|
||||
|
||||
" TODO: Add a test for the 'K' flag in 'cpo'
|
||||
" TODO: Add a test for the 'K' flag in 'cpo'.
|
||||
" Don't wait for a key code to complete when it is halfway a mapping.
|
||||
|
||||
" Test for the 'l' flag in 'cpo' (backslash in a [] range)
|
||||
func Test_cpo_l()
|
||||
@ -334,7 +338,9 @@ func Test_cpo_L()
|
||||
let &cpo = save_cpo
|
||||
endfunc
|
||||
|
||||
" TODO: Add a test for the 'm' flag in 'cpo'
|
||||
" TODO: Add a test for the 'm' flag in 'cpo'.
|
||||
" When included, a showmatch will always wait half a second. When not
|
||||
" included, a showmatch will wait half a second or until a character is typed.
|
||||
|
||||
" Test for the 'M' flag in 'cpo' (% with escape parenthesis)
|
||||
func Test_cpo_M()
|
||||
@ -498,7 +504,9 @@ func Test_cpo_R()
|
||||
let &cpo = save_cpo
|
||||
endfunc
|
||||
|
||||
" TODO: Add a test for the 's' flag in 'cpo'
|
||||
" TODO: Add a test for the 's' flag in 'cpo'.
|
||||
" Set buffer options when entering the buffer for the first time. If not
|
||||
" present the options are set when the buffer is created.
|
||||
|
||||
" Test for the 'S' flag in 'cpo' (copying buffer options)
|
||||
func Test_cpo_S()
|
||||
@ -543,8 +551,8 @@ func Test_cpo_u()
|
||||
let &cpo = save_cpo
|
||||
endfunc
|
||||
|
||||
" TODO: Add a test for the 'v' flag in 'cpo' (backspace doesn't remove
|
||||
" characters from the screen)
|
||||
" TODO: Add a test for the 'v' flag in 'cpo'.
|
||||
" Backspaced characters remain visible on the screen in Insert mode.
|
||||
|
||||
" Test for the 'w' flag in 'cpo' ('cw' on a blank character changes only one
|
||||
" character)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
source check.vim
|
||||
CheckFeature digraphs
|
||||
source term_util.vim
|
||||
|
||||
func Put_Dig(chars)
|
||||
exe "norm! o\<c-k>".a:chars
|
||||
@ -502,4 +503,20 @@ func Test_loadkeymap_error()
|
||||
call delete('Xkeymap')
|
||||
endfunc
|
||||
|
||||
" Test for the characters displayed on the screen when entering a digraph
|
||||
func Test_entering_digraph()
|
||||
CheckRunVimInTerminal
|
||||
let buf = RunVimInTerminal('', {'rows': 6})
|
||||
call term_sendkeys(buf, "i\<C-K>")
|
||||
call term_wait(buf)
|
||||
call assert_equal('?', term_getline(buf, 1))
|
||||
call term_sendkeys(buf, "1")
|
||||
call term_wait(buf)
|
||||
call assert_equal('1', term_getline(buf, 1))
|
||||
call term_sendkeys(buf, "2")
|
||||
call term_wait(buf)
|
||||
call assert_equal('½', term_getline(buf, 1))
|
||||
call StopVimInTerminal(buf)
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -401,6 +401,14 @@ func Test_edit_13()
|
||||
call assert_equal("", getline(2))
|
||||
call assert_equal(" baz", getline(3))
|
||||
set autoindent&
|
||||
|
||||
" pressing <C-U> to erase line should keep the indent with 'autoindent'
|
||||
set backspace=2 autoindent
|
||||
%d
|
||||
exe "normal i\tone\<CR>three\<C-U>two"
|
||||
call assert_equal(["\tone", "\ttwo"], getline(1, '$'))
|
||||
set backspace& autoindent&
|
||||
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
@ -1301,9 +1309,7 @@ endfunc
|
||||
|
||||
func Test_edit_rightleft()
|
||||
" Cursor in rightleft mode moves differently
|
||||
if !exists("+rightleft")
|
||||
return
|
||||
endif
|
||||
CheckFeature rightleft
|
||||
call NewWindow(10, 20)
|
||||
call setline(1, ['abc', 'def', 'ghi'])
|
||||
call cursor(1, 2)
|
||||
@ -1348,6 +1354,13 @@ func Test_edit_rightleft()
|
||||
\" ihg",
|
||||
\" ~"]
|
||||
call assert_equal(join(expect, "\n"), join(lines, "\n"))
|
||||
%d _
|
||||
call test_override('redraw_flag', 1)
|
||||
call test_override('char_avail', 1)
|
||||
call feedkeys("a\<C-V>x41", "xt")
|
||||
redraw!
|
||||
call assert_equal(repeat(' ', 19) .. 'A', Screenline(1))
|
||||
call test_override('ALL', 0)
|
||||
set norightleft
|
||||
bw!
|
||||
endfunc
|
||||
@ -1683,4 +1696,103 @@ func Test_edit_file_no_read_perm()
|
||||
call delete('Xfile')
|
||||
endfunc
|
||||
|
||||
" Pressing escape in 'insertmode' should beep
|
||||
func Test_edit_insertmode_esc_beeps()
|
||||
new
|
||||
set insertmode
|
||||
call assert_beeps("call feedkeys(\"one\<Esc>\", 'xt')")
|
||||
set insertmode&
|
||||
" unsupported CTRL-G command should beep in insert mode.
|
||||
call assert_beeps("normal i\<C-G>l")
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" Test for 'hkmap' and 'hkmapp'
|
||||
func Test_edit_hkmap()
|
||||
CheckFeature rightleft
|
||||
if has('win32') && !has('gui')
|
||||
" Test fails on the MS-Windows terminal version
|
||||
return
|
||||
endif
|
||||
new
|
||||
|
||||
set revins hkmap
|
||||
let str = 'abcdefghijklmnopqrstuvwxyz'
|
||||
let str ..= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
let str ..= '`/'',.;'
|
||||
call feedkeys('i' .. str, 'xt')
|
||||
let expected = "óõú,.;"
|
||||
let expected ..= "ZYXWVUTSRQPONMLKJIHGFEDCBA"
|
||||
let expected ..= "æèñ'äåàãø/ôíîöêìçïéòë÷âáðù"
|
||||
call assert_equal(expected, getline(1))
|
||||
|
||||
%d
|
||||
set revins hkmap hkmapp
|
||||
let str = 'abcdefghijklmnopqrstuvwxyz'
|
||||
let str ..= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
call feedkeys('i' .. str, 'xt')
|
||||
let expected = "õYXWVUTSRQóOïíLKJIHGFEDêBA"
|
||||
let expected ..= "öòXùåèúæø'ôñðîì÷çéäâóǟãëáà"
|
||||
call assert_equal(expected, getline(1))
|
||||
|
||||
set revins& hkmap& hkmapp&
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" Test for 'allowrevins' and using CTRL-_ in insert mode
|
||||
func Test_edit_allowrevins()
|
||||
CheckFeature rightleft
|
||||
new
|
||||
set allowrevins
|
||||
call feedkeys("iABC\<C-_>DEF\<C-_>GHI", 'xt')
|
||||
call assert_equal('ABCFEDGHI', getline(1))
|
||||
set allowrevins&
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" Test for inserting a register in insert mode using CTRL-R
|
||||
func Test_edit_insert_reg()
|
||||
new
|
||||
let g:Line = ''
|
||||
func SaveFirstLine()
|
||||
let g:Line = Screenline(1)
|
||||
return 'r'
|
||||
endfunc
|
||||
inoremap <expr> <buffer> <F2> SaveFirstLine()
|
||||
call test_override('redraw_flag', 1)
|
||||
call test_override('char_avail', 1)
|
||||
let @r = 'sample'
|
||||
call feedkeys("a\<C-R>=SaveFirstLine()\<CR>", "xt")
|
||||
call assert_equal('"', g:Line)
|
||||
call test_override('ALL', 0)
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" When a character is inserted at the last position of the last line in a
|
||||
" window, the window contents should be scrolled one line up. If the top line
|
||||
" is part of a fold, then the entire fold should be scrolled up.
|
||||
func Test_edit_lastline_scroll()
|
||||
new
|
||||
let h = winheight(0)
|
||||
let lines = ['one', 'two', 'three']
|
||||
let lines += repeat(['vim'], h - 4)
|
||||
call setline(1, lines)
|
||||
call setline(h, repeat('x', winwidth(0) - 1))
|
||||
call feedkeys("GAx", 'xt')
|
||||
redraw!
|
||||
call assert_equal(h - 1, winline())
|
||||
call assert_equal(2, line('w0'))
|
||||
|
||||
" scroll with a fold
|
||||
1,2fold
|
||||
normal gg
|
||||
call setline(h + 1, repeat('x', winwidth(0) - 1))
|
||||
call feedkeys("GAx", 'xt')
|
||||
redraw!
|
||||
call assert_equal(h - 1, winline())
|
||||
call assert_equal(3, line('w0'))
|
||||
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -7,7 +7,7 @@ let s:imstatus_active = 0
|
||||
|
||||
func IM_activatefunc(active)
|
||||
let s:imactivatefunc_called = 1
|
||||
let s:imstatus_active = a:active
|
||||
let s:imstatus_active = a:active
|
||||
endfunc
|
||||
|
||||
func IM_statusfunc()
|
||||
@ -83,4 +83,30 @@ func Test_lmap_in_insert_mode()
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" Test for using CTRL-^ to toggle iminsert in insert mode
|
||||
func Test_iminsert_toggle()
|
||||
CheckGui
|
||||
if has('win32')
|
||||
CheckFeature multi_byte_ime
|
||||
elseif !has('gui_mac')
|
||||
CheckFeature xim
|
||||
endif
|
||||
if has('gui_running') && !has('win32')
|
||||
" this works only in Win32 GUI version (for some reason)
|
||||
return
|
||||
endif
|
||||
new
|
||||
let save_imdisable = &imdisable
|
||||
let save_iminsert = &iminsert
|
||||
set noimdisable
|
||||
set iminsert=0
|
||||
exe "normal i\<C-^>"
|
||||
call assert_equal(2, &iminsert)
|
||||
exe "normal i\<C-^>"
|
||||
call assert_equal(0, &iminsert)
|
||||
let &iminsert = save_iminsert
|
||||
let &imdisable = save_imdisable
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -79,11 +79,27 @@ func Test_paste_clipboard()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" bracketed paste in command line
|
||||
func Test_paste_cmdline()
|
||||
call feedkeys(":a\<Esc>[200~foo\<CR>bar\<Esc>[201~b\<Home>\"\<CR>", 'xt')
|
||||
call assert_equal("\"afoo\<CR>barb", getreg(':'))
|
||||
endfunc
|
||||
|
||||
" bracketed paste in Ex-mode
|
||||
func Test_paste_ex_mode()
|
||||
unlet! foo
|
||||
call feedkeys("Qlet foo=\"\<Esc>[200~foo\<CR>bar\<Esc>[201~\"\<CR>vi\<CR>", 'xt')
|
||||
call assert_equal("foo\rbar", foo)
|
||||
endfunc
|
||||
|
||||
func Test_paste_onechar()
|
||||
new
|
||||
let @f='abc'
|
||||
call feedkeys("i\<C-R>\<Esc>[200~foo\<CR>bar\<Esc>[201~", 'xt')
|
||||
call assert_equal("abc", getline(1))
|
||||
close!
|
||||
endfunc
|
||||
|
||||
func Test_paste_visual_mode()
|
||||
new
|
||||
call setline(1, 'here are some words')
|
||||
@ -134,3 +150,5 @@ func Test_xrestore()
|
||||
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -2079,9 +2079,9 @@ func Test_popup_scrollbar()
|
||||
" check size with wrapping lines
|
||||
call term_sendkeys(buf, "j")
|
||||
call VerifyScreenDump(buf, 'Test_popupwin_scroll_12', {})
|
||||
call term_sendkeys(buf, "x")
|
||||
|
||||
" clean up
|
||||
call term_sendkeys(buf, "x")
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('XtestPopupScroll')
|
||||
endfunc
|
||||
@ -2454,9 +2454,11 @@ func Test_popupwin_terminal_buffer()
|
||||
call term_sendkeys(termbuf2, "exit\<CR>")
|
||||
|
||||
" Exiting shell closes popup window
|
||||
let pupwin = win_getid()
|
||||
call feedkeys("exit\<CR>", 'xt')
|
||||
" Wait for shell to exit
|
||||
sleep 100m
|
||||
call WaitForAssert({-> assert_notequal(pupwin, win_getid())})
|
||||
|
||||
call feedkeys(":quit\<CR>", 'xt')
|
||||
call assert_equal(origwin, win_getid())
|
||||
endfunc
|
||||
@ -3347,6 +3349,16 @@ func Test_popupwin_filter_input_multibyte()
|
||||
call feedkeys("\u301b", 'xt')
|
||||
call assert_equal([0xe3, 0x80, 0x9b], g:bytes)
|
||||
|
||||
if has('unix')
|
||||
" with modifyOtherKeys <M-S-a> does not include a modifier sequence
|
||||
if has('gui_running')
|
||||
call feedkeys("\x9b\xfc\x08A", 'Lx!')
|
||||
else
|
||||
call feedkeys("\<Esc>[27;4;65~", 'Lx!')
|
||||
endif
|
||||
call assert_equal([0xc3, 0x81], g:bytes)
|
||||
endif
|
||||
|
||||
call popup_clear()
|
||||
delfunc MyPopupFilter
|
||||
unlet g:bytes
|
||||
|
@ -147,6 +147,11 @@ func Test_prompt_buffer_edit()
|
||||
call assert_beeps('normal! S')
|
||||
call assert_beeps("normal! \<C-A>")
|
||||
call assert_beeps("normal! \<C-X>")
|
||||
" pressing CTRL-W in the prompt buffer should trigger the window commands
|
||||
call assert_equal(1, winnr())
|
||||
exe "normal A\<C-W>\<C-W>"
|
||||
call assert_equal(2, winnr())
|
||||
wincmd w
|
||||
close!
|
||||
call assert_equal(0, prompt_setprompt([], ''))
|
||||
endfunc
|
||||
|
@ -485,6 +485,14 @@ func Test_set_register_dict()
|
||||
call assert_equal(['six'], getreginfo('0').regcontents)
|
||||
call assert_equal(['six'], getreginfo('"').regcontents)
|
||||
|
||||
let @x = 'one'
|
||||
call setreg('x', {})
|
||||
call assert_equal(1, len(split(execute('reg x'), '\n')))
|
||||
|
||||
call assert_fails("call setreg('0', #{regtype: 'V'}, 'v')", 'E118:')
|
||||
call assert_fails("call setreg('0', #{regtype: 'X'})", 'E475:')
|
||||
call assert_fails("call setreg('0', #{regtype: 'vy'})", 'E475:')
|
||||
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
|
@ -26,6 +26,18 @@ func Test_rubydo()
|
||||
%bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_rubydo_dollar_underscore()
|
||||
new
|
||||
call setline(1, ['one', 'two', 'three', 'four'])
|
||||
2,3rubydo $_ = '[' + $_ + ']'
|
||||
call assert_equal(['one', '[two]', '[three]', 'four'], getline(1, '$'))
|
||||
bwipe!
|
||||
|
||||
call assert_fails('rubydo $_ = 0', 'E265:')
|
||||
call assert_fails('rubydo (')
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_rubyfile()
|
||||
" Check :rubyfile does not SEGV with Ruby level exception but just fails
|
||||
let tempfile = tempname() . '.rb'
|
||||
@ -395,6 +407,15 @@ func Test_ruby_p()
|
||||
call assert_equal(0, len(messages))
|
||||
endfunc
|
||||
|
||||
func Test_rubyeval_error()
|
||||
" On Linux or Windows the error matches:
|
||||
" "syntax error, unexpected end-of-input"
|
||||
" whereas on macOS in CI, the error message makes less sense:
|
||||
" "SyntaxError: array length must be 2"
|
||||
" Unclear why. The test does not check the error message.
|
||||
call assert_fails('call rubyeval("(")')
|
||||
endfunc
|
||||
|
||||
" Test for various heredoc syntax
|
||||
func Test_ruby_heredoc()
|
||||
ruby << END
|
||||
|
@ -38,6 +38,9 @@ func Test_selectmode_start()
|
||||
set selectmode=cmd
|
||||
call feedkeys('gvabc', 'xt')
|
||||
call assert_equal('abctdef', getline(1))
|
||||
" arrow keys without shift should not start selection
|
||||
call feedkeys("A\<Home>\<Right>\<Left>ro", 'xt')
|
||||
call assert_equal('roabctdef', getline(1))
|
||||
set selectmode= keymodel=
|
||||
bw!
|
||||
endfunc
|
||||
|
@ -623,4 +623,93 @@ func Test_tabpage_close_cmdwin()
|
||||
tabonly
|
||||
endfunc
|
||||
|
||||
" Pressing <C-PageUp> in insert mode should go to the previous tab page
|
||||
" and <C-PageDown> should go to the next tab page
|
||||
func Test_tabpage_Ctrl_Pageup()
|
||||
tabnew
|
||||
call feedkeys("i\<C-PageUp>", 'xt')
|
||||
call assert_equal(1, tabpagenr())
|
||||
call feedkeys("i\<C-PageDown>", 'xt')
|
||||
call assert_equal(2, tabpagenr())
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" Return the terminal key code for selecting a tab page from the tabline. This
|
||||
" sequence contains the following codes: a CSI (0x9b), KS_TABLINE (0xf0),
|
||||
" KS_FILLER (0x58) and then the tab page number.
|
||||
func TabLineSelectPageCode(tabnr)
|
||||
return "\x9b\xf0\x58" .. nr2char(a:tabnr)
|
||||
endfunc
|
||||
|
||||
" Return the terminal key code for opening a new tabpage from the tabpage
|
||||
" menu. This sequence consists of the following codes: a CSI (0x9b),
|
||||
" KS_TABMENU (0xef), KS_FILLER (0x58), the tab page number and
|
||||
" TABLINE_MENU_NEW (2).
|
||||
func TabMenuNewItemCode(tabnr)
|
||||
return "\x9b\xef\x58" .. nr2char(a:tabnr) .. nr2char(2)
|
||||
endfunc
|
||||
|
||||
" Return the terminal key code for closing a tabpage from the tabpage menu.
|
||||
" This sequence consists of the following codes: a CSI (0x9b), KS_TABMENU
|
||||
" (0xef), KS_FILLER (0x58), the tab page number and TABLINE_MENU_CLOSE (1).
|
||||
func TabMenuCloseItemCode(tabnr)
|
||||
return "\x9b\xef\x58" .. nr2char(a:tabnr) .. nr2char(1)
|
||||
endfunc
|
||||
|
||||
" Test for using the tabpage menu from the insert and normal modes
|
||||
func Test_tabline_tabmenu()
|
||||
" only works in GUI
|
||||
CheckGui
|
||||
|
||||
%bw!
|
||||
tabnew
|
||||
tabnew
|
||||
call assert_equal(3, tabpagenr())
|
||||
|
||||
" go to tab page 2 in normal mode
|
||||
call feedkeys(TabLineSelectPageCode(2), "Lx!")
|
||||
call assert_equal(2, tabpagenr())
|
||||
|
||||
" close tab page 3 in normal mode
|
||||
call feedkeys(TabMenuCloseItemCode(3), "Lx!")
|
||||
call assert_equal(2, tabpagenr('$'))
|
||||
call assert_equal(2, tabpagenr())
|
||||
|
||||
" open new tab page before tab page 1 in normal mode
|
||||
call feedkeys(TabMenuNewItemCode(1), "Lx!")
|
||||
call assert_equal(1, tabpagenr())
|
||||
call assert_equal(3, tabpagenr('$'))
|
||||
|
||||
" go to tab page 2 in operator-pending mode (should beep)
|
||||
call assert_beeps('call feedkeys("f" .. TabLineSelectPageCode(2), "Lx!")')
|
||||
|
||||
" open new tab page before tab page 1 in operator-pending mode (should beep)
|
||||
call assert_beeps('call feedkeys("f" .. TabMenuNewItemCode(1), "Lx!")')
|
||||
|
||||
" open new tab page after tab page 3 in normal mode
|
||||
call feedkeys(TabMenuNewItemCode(4), "Lx!")
|
||||
call assert_equal(4, tabpagenr())
|
||||
call assert_equal(4, tabpagenr('$'))
|
||||
|
||||
" go to tab page 2 in insert mode
|
||||
call feedkeys("i" .. TabLineSelectPageCode(2) .. "\<C-C>", "Lx!")
|
||||
call assert_equal(2, tabpagenr())
|
||||
|
||||
" close tab page 2 in insert mode
|
||||
call feedkeys("i" .. TabMenuCloseItemCode(2) .. "\<C-C>", "Lx!")
|
||||
call assert_equal(3, tabpagenr('$'))
|
||||
|
||||
" open new tab page before tab page 3 in insert mode
|
||||
call feedkeys("i" .. TabMenuNewItemCode(3) .. "\<C-C>", "Lx!")
|
||||
call assert_equal(3, tabpagenr())
|
||||
call assert_equal(4, tabpagenr('$'))
|
||||
|
||||
" open new tab page after tab page 4 in insert mode
|
||||
call feedkeys("i" .. TabMenuNewItemCode(5) .. "\<C-C>", "Lx!")
|
||||
call assert_equal(5, tabpagenr())
|
||||
call assert_equal(5, tabpagenr('$'))
|
||||
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -240,6 +240,7 @@ func Test_tag_file_encoding()
|
||||
call delete('Xtags1')
|
||||
endfunc
|
||||
|
||||
" Test for emacs-style tags file (TAGS)
|
||||
func Test_tagjump_etags()
|
||||
if !has('emacs_tags')
|
||||
return
|
||||
@ -1055,7 +1056,7 @@ func Test_tselect_listing()
|
||||
call writefile([
|
||||
\ "!_TAG_FILE_ENCODING\tutf-8\t//",
|
||||
\ "first\tXfoo\t1" .. ';"' .. "\tv\ttyperef:typename:int\tfile:",
|
||||
\ "first\tXfoo\t2" .. ';"' .. "\tv\ttyperef:typename:char\tfile:"],
|
||||
\ "first\tXfoo\t2" .. ';"' .. "\tkind:v\ttyperef:typename:char\tfile:"],
|
||||
\ 'Xtags')
|
||||
set tags=Xtags
|
||||
|
||||
@ -1337,4 +1338,56 @@ func Test_tag_length()
|
||||
set tags& taglength&
|
||||
endfunc
|
||||
|
||||
" Tests for errors in a tags file
|
||||
func Test_tagfile_errors()
|
||||
set tags=Xtags
|
||||
|
||||
" missing search pattern or line number for a tag
|
||||
call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
|
||||
\ "foo\tXfile\t"], 'Xtags', 'b')
|
||||
call writefile(['foo'], 'Xfile')
|
||||
|
||||
enew
|
||||
tag foo
|
||||
call assert_equal('', @%)
|
||||
let caught_431 = v:false
|
||||
try
|
||||
eval taglist('.*')
|
||||
catch /:E431:/
|
||||
let caught_431 = v:true
|
||||
endtry
|
||||
call assert_equal(v:true, caught_431)
|
||||
|
||||
call delete('Xtags')
|
||||
call delete('Xfile')
|
||||
set tags&
|
||||
endfunc
|
||||
|
||||
" When :stag fails to open the file, should close the new window
|
||||
func Test_stag_close_window_on_error()
|
||||
new | only
|
||||
set tags=Xtags
|
||||
call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
|
||||
\ "foo\tXfile\t1"], 'Xtags')
|
||||
call writefile(['foo'], 'Xfile')
|
||||
call writefile([], '.Xfile.swp')
|
||||
" Remove the catch-all that runtest.vim adds
|
||||
au! SwapExists
|
||||
augroup StagTest
|
||||
au!
|
||||
autocmd SwapExists Xfile let v:swapchoice='q'
|
||||
augroup END
|
||||
|
||||
stag foo
|
||||
call assert_equal(1, winnr('$'))
|
||||
call assert_equal('', @%)
|
||||
|
||||
augroup StagTest
|
||||
au!
|
||||
augroup END
|
||||
call delete('Xfile')
|
||||
call delete('.Xfile.swp')
|
||||
set tags&
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -1116,6 +1116,20 @@ func Test_fo_a_w()
|
||||
call feedkeys("iabc abc a abc\<Esc>k0weade", 'xt')
|
||||
call assert_equal(['abc abcde ', 'a abc'], getline(1, '$'))
|
||||
|
||||
" when a line ends with space, it is not broken up.
|
||||
%d
|
||||
call feedkeys("ione two to ", 'xt')
|
||||
call assert_equal('one two to ', getline(1))
|
||||
|
||||
" when a line ends with spaces and backspace is used in the next line, the
|
||||
" last space in the previous line should be removed.
|
||||
%d
|
||||
set backspace=indent,eol,start
|
||||
call setline(1, ['one ', 'two'])
|
||||
exe "normal 2Gi\<BS>"
|
||||
call assert_equal(['one two'], getline(1, '$'))
|
||||
set backspace&
|
||||
|
||||
" Test for 'a', 'w' and '1' options.
|
||||
setlocal textwidth=0
|
||||
setlocal fo=1aw
|
||||
|
@ -185,6 +185,42 @@ def Test_disassemble_store_member()
|
||||
res)
|
||||
enddef
|
||||
|
||||
def s:ListAssign()
|
||||
let x: string
|
||||
let y: string
|
||||
let l: list<any>
|
||||
[x, y; l] = g:stringlist
|
||||
enddef
|
||||
|
||||
def Test_disassemble_list_assign()
|
||||
let res = execute('disass s:ListAssign')
|
||||
assert_match('<SNR>\d*_ListAssign\_s*' ..
|
||||
'let x: string\_s*' ..
|
||||
'\d PUSHS "\[NULL\]"\_s*' ..
|
||||
'\d STORE $0\_s*' ..
|
||||
'let y: string\_s*' ..
|
||||
'\d PUSHS "\[NULL\]"\_s*' ..
|
||||
'\d STORE $1\_s*' ..
|
||||
'let l: list<any>\_s*' ..
|
||||
'\d NEWLIST size 0\_s*' ..
|
||||
'\d STORE $2\_s*' ..
|
||||
'\[x, y; l\] = g:stringlist\_s*' ..
|
||||
'\d LOADG g:stringlist\_s*' ..
|
||||
'\d CHECKTYPE list stack\[-1\]\_s*' ..
|
||||
'\d CHECKLEN >= 2\_s*' ..
|
||||
'\d\+ ITEM 0\_s*' ..
|
||||
'\d\+ CHECKTYPE string stack\[-1\]\_s*' ..
|
||||
'\d\+ STORE $0\_s*' ..
|
||||
'\d\+ ITEM 1\_s*' ..
|
||||
'\d\+ CHECKTYPE string stack\[-1\]\_s*' ..
|
||||
'\d\+ STORE $1\_s*' ..
|
||||
'\d\+ SLICE 2\_s*' ..
|
||||
'\d\+ STORE $2\_s*' ..
|
||||
'\d\+ PUSHNR 0\_s*' ..
|
||||
'\d\+ RETURN',
|
||||
res)
|
||||
enddef
|
||||
|
||||
def s:ScriptFuncUnlet()
|
||||
g:somevar = "value"
|
||||
unlet g:somevar
|
||||
@ -1154,7 +1190,7 @@ def Test_vim9script_forward_func()
|
||||
def FuncTwo(): string
|
||||
return 'two'
|
||||
enddef
|
||||
let g:res_FuncOne: string = execute('disass FuncOne')
|
||||
g:res_FuncOne = execute('disass FuncOne')
|
||||
END
|
||||
writefile(lines, 'Xdisassemble')
|
||||
source Xdisassemble
|
||||
|
@ -524,6 +524,7 @@ def Test_expr5()
|
||||
g:anint)
|
||||
assert_equal(9, g:alsoint + 5)
|
||||
assert_equal(14, g:alsoint + g:anint)
|
||||
assert_equal([1, 2, 3, 4], [1] + g:alist)
|
||||
|
||||
assert_equal(54, 60 - 6)
|
||||
assert_equal(50, 60 -
|
||||
@ -1028,6 +1029,39 @@ def Test_expr7_trailing()
|
||||
assert_equal(123, d.key)
|
||||
enddef
|
||||
|
||||
def Test_expr7_subscript_linebreak()
|
||||
let range = range(
|
||||
3)
|
||||
let l = range->
|
||||
map('string(v:key)')
|
||||
assert_equal(['0', '1', '2'], l)
|
||||
|
||||
l = range
|
||||
->map('string(v:key)')
|
||||
assert_equal(['0', '1', '2'], l)
|
||||
|
||||
l = range # comment
|
||||
->map('string(v:key)')
|
||||
assert_equal(['0', '1', '2'], l)
|
||||
|
||||
l = range
|
||||
|
||||
->map('string(v:key)')
|
||||
assert_equal(['0', '1', '2'], l)
|
||||
|
||||
l = range
|
||||
# comment
|
||||
->map('string(v:key)')
|
||||
assert_equal(['0', '1', '2'], l)
|
||||
|
||||
assert_equal('1', l[
|
||||
1])
|
||||
|
||||
let d = #{one: 33}
|
||||
assert_equal(33, d.
|
||||
one)
|
||||
enddef
|
||||
|
||||
|
||||
func Test_expr7_trailing_fails()
|
||||
call CheckDefFailure(['let l = [2]', 'l->{l -> add(l, 8)}'], 'E107')
|
||||
@ -1043,7 +1077,7 @@ func Test_expr_fails()
|
||||
call CheckDefFailure(["CallMe2('yes' , 'no')"], 'E1068:')
|
||||
|
||||
call CheckDefFailure(["v:nosuch += 3"], 'E1001:')
|
||||
call CheckDefFailure(["let v:statusmsg = ''"], 'E1064:')
|
||||
call CheckDefFailure(["let v:statusmsg = ''"], 'E1016: Cannot declare a v: variable:')
|
||||
call CheckDefFailure(["let asdf = v:nosuch"], 'E1001:')
|
||||
|
||||
call CheckDefFailure(["echo len('asdf'"], 'E110:')
|
||||
|
@ -323,7 +323,7 @@ def Test_vim9script_call()
|
||||
str->MyFunc()
|
||||
assert_equal('barfoo', var)
|
||||
|
||||
let g:value = 'value'
|
||||
g:value = 'value'
|
||||
g:value->MyFunc()
|
||||
assert_equal('value', var)
|
||||
|
||||
|
@ -109,6 +109,41 @@ def Test_assignment()
|
||||
call CheckDefFailure(['v:errmsg += 123'], 'E1013:')
|
||||
enddef
|
||||
|
||||
def Test_vim9_single_char_vars()
|
||||
let lines =<< trim END
|
||||
vim9script
|
||||
|
||||
" single character variable declarations work
|
||||
let a: string
|
||||
let b: number
|
||||
let l: list<any>
|
||||
let s: string
|
||||
let t: number
|
||||
let v: number
|
||||
let w: number
|
||||
|
||||
" script-local variables can be used without s: prefix
|
||||
a = 'script-a'
|
||||
b = 111
|
||||
l = [1, 2, 3]
|
||||
s = 'script-s'
|
||||
t = 222
|
||||
v = 333
|
||||
w = 444
|
||||
|
||||
assert_equal('script-a', a)
|
||||
assert_equal(111, b)
|
||||
assert_equal([1, 2, 3], l)
|
||||
assert_equal('script-s', s)
|
||||
assert_equal(222, t)
|
||||
assert_equal(333, v)
|
||||
assert_equal(444, w)
|
||||
END
|
||||
writefile(lines, 'Xsinglechar')
|
||||
source Xsinglechar
|
||||
delete('Xsinglechar')
|
||||
enddef
|
||||
|
||||
def Test_assignment_list()
|
||||
let list1: list<bool> = [false, true, false]
|
||||
let list2: list<number> = [1, 2, 3]
|
||||
@ -127,6 +162,7 @@ def Test_assignment_list()
|
||||
list2[-3] = 77
|
||||
assert_equal([77, 88, 99], list2)
|
||||
call CheckDefExecFailure(['let ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
|
||||
call CheckDefExecFailure(['let [v1, v2] = [1, 2]'], 'E1092:')
|
||||
|
||||
# type becomes list<any>
|
||||
let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
|
||||
@ -139,6 +175,9 @@ def Test_assignment_dict()
|
||||
let dict4: dict<any> = #{one: 1, two: '2'}
|
||||
let dict5: dict<blob> = #{one: 0z01, two: 0z02}
|
||||
|
||||
" overwrite
|
||||
dict3['key'] = 'another'
|
||||
|
||||
call CheckDefExecFailure(['let dd = {}', 'dd[""] = 6'], 'E713:')
|
||||
|
||||
# type becomes dict<any>
|
||||
@ -218,6 +257,13 @@ def Test_assignment_default()
|
||||
|
||||
let thechannel: channel
|
||||
assert_equal(test_null_channel(), thechannel)
|
||||
|
||||
if has('unix') && executable('cat')
|
||||
" check with non-null job and channel, types must match
|
||||
thejob = job_start("cat ", #{})
|
||||
thechannel = job_getchannel(thejob)
|
||||
job_stop(thejob, 'kill')
|
||||
endif
|
||||
endif
|
||||
|
||||
let nr = 1234 | nr = 5678
|
||||
@ -276,15 +322,15 @@ def Test_assignment_failure()
|
||||
call CheckDefFailure(['let &option'], 'E1052:')
|
||||
call CheckDefFailure(['&g:option = 5'], 'E113:')
|
||||
|
||||
call CheckDefFailure(['let $VAR = 5'], 'E1065:')
|
||||
call CheckDefFailure(['let $VAR = 5'], 'E1016: Cannot declare an environment variable:')
|
||||
|
||||
call CheckDefFailure(['let @~ = 5'], 'E354:')
|
||||
call CheckDefFailure(['let @a = 5'], 'E1066:')
|
||||
|
||||
call CheckDefFailure(['let g:var = 5'], 'E1016:')
|
||||
call CheckDefFailure(['let w:var = 5'], 'E1079:')
|
||||
call CheckDefFailure(['let b:var = 5'], 'E1078:')
|
||||
call CheckDefFailure(['let t:var = 5'], 'E1080:')
|
||||
call CheckDefFailure(['let g:var = 5'], 'E1016: Cannot declare a global variable:')
|
||||
call CheckDefFailure(['let w:var = 5'], 'E1016: Cannot declare a window variable:')
|
||||
call CheckDefFailure(['let b:var = 5'], 'E1016: Cannot declare a buffer variable:')
|
||||
call CheckDefFailure(['let t:var = 5'], 'E1016: Cannot declare a tab variable:')
|
||||
|
||||
call CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:')
|
||||
call CheckDefFailure(['let xnr += 4'], 'E1020:')
|
||||
@ -774,6 +820,9 @@ def Test_vim9script_fails()
|
||||
CheckScriptFailure(['vim9script', 'export let g:some'], 'E1044:')
|
||||
CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
|
||||
|
||||
CheckScriptFailure(['vim9script', 'let str: string', 'str = 1234'], 'E1013:')
|
||||
CheckScriptFailure(['vim9script', 'const str = "asdf"', 'str = "xxx"'], 'E46:')
|
||||
|
||||
assert_fails('vim9script', 'E1038')
|
||||
assert_fails('export something', 'E1043')
|
||||
enddef
|
||||
@ -1050,11 +1099,11 @@ def Test_if_const_expr()
|
||||
|
||||
g:glob = 2
|
||||
if false
|
||||
execute('let g:glob = 3')
|
||||
execute('g:glob = 3')
|
||||
endif
|
||||
assert_equal(2, g:glob)
|
||||
if true
|
||||
execute('let g:glob = 3')
|
||||
execute('g:glob = 3')
|
||||
endif
|
||||
assert_equal(3, g:glob)
|
||||
|
||||
@ -1741,8 +1790,8 @@ def Test_vim9_comment_gui()
|
||||
enddef
|
||||
|
||||
def Test_vim9_comment_not_compiled()
|
||||
au TabEnter *.vim let g:entered = 1
|
||||
au TabEnter *.x let g:entered = 2
|
||||
au TabEnter *.vim g:entered = 1
|
||||
au TabEnter *.x g:entered = 2
|
||||
|
||||
edit test.vim
|
||||
doautocmd TabEnter #comment
|
||||
@ -1762,14 +1811,46 @@ def Test_vim9_comment_not_compiled()
|
||||
|
||||
CheckScriptSuccess([
|
||||
'vim9script',
|
||||
'let g:var = 123',
|
||||
'let w:var = 777',
|
||||
'g:var = 123',
|
||||
'b:var = 456',
|
||||
'w:var = 777',
|
||||
't:var = 888',
|
||||
'unlet g:var w:var # something',
|
||||
])
|
||||
|
||||
CheckScriptFailure([
|
||||
'vim9script',
|
||||
'let g:var = 123',
|
||||
], 'E1016: Cannot declare a global variable:')
|
||||
|
||||
CheckScriptFailure([
|
||||
'vim9script',
|
||||
'let b:var = 123',
|
||||
], 'E1016: Cannot declare a buffer variable:')
|
||||
|
||||
CheckScriptFailure([
|
||||
'vim9script',
|
||||
'let w:var = 123',
|
||||
], 'E1016: Cannot declare a window variable:')
|
||||
|
||||
CheckScriptFailure([
|
||||
'vim9script',
|
||||
'let t:var = 123',
|
||||
], 'E1016: Cannot declare a tab variable:')
|
||||
|
||||
CheckScriptFailure([
|
||||
'vim9script',
|
||||
'let v:version = 123',
|
||||
], 'E1016: Cannot declare a v: variable:')
|
||||
|
||||
CheckScriptFailure([
|
||||
'vim9script',
|
||||
'let $VARIABLE = "text"',
|
||||
], 'E1016: Cannot declare an environment variable:')
|
||||
|
||||
CheckScriptFailure([
|
||||
'vim9script',
|
||||
'g:var = 123',
|
||||
'unlet g:var# comment1',
|
||||
], 'E108:')
|
||||
|
||||
@ -1840,11 +1921,11 @@ enddef
|
||||
def Test_finish()
|
||||
let lines =<< trim END
|
||||
vim9script
|
||||
let g:res = 'one'
|
||||
g:res = 'one'
|
||||
if v:false | finish | endif
|
||||
let g:res = 'two'
|
||||
g:res = 'two'
|
||||
finish
|
||||
let g:res = 'three'
|
||||
g:res = 'three'
|
||||
END
|
||||
writefile(lines, 'Xfinished')
|
||||
source Xfinished
|
||||
@ -1920,6 +2001,20 @@ def Test_let_declaration()
|
||||
unlet g:other_var
|
||||
enddef
|
||||
|
||||
def Test_let_declaration_fails()
|
||||
let lines =<< trim END
|
||||
vim9script
|
||||
const var: string
|
||||
END
|
||||
CheckScriptFailure(lines, 'E1021:')
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
let 9var: string
|
||||
END
|
||||
CheckScriptFailure(lines, 'E475:')
|
||||
enddef
|
||||
|
||||
def Test_let_type_check()
|
||||
let lines =<< trim END
|
||||
vim9script
|
||||
@ -1933,6 +2028,12 @@ def Test_let_type_check()
|
||||
let var:string
|
||||
END
|
||||
CheckScriptFailure(lines, 'E1069:')
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
let var: asdf
|
||||
END
|
||||
CheckScriptFailure(lines, 'E1010:')
|
||||
enddef
|
||||
|
||||
def Test_forward_declaration()
|
||||
|
@ -87,6 +87,28 @@ func Test_global_vars()
|
||||
call assert_equal(test_null, g:MY_GLOBAL_NULL)
|
||||
call assert_equal(test_none, g:MY_GLOBAL_NONE)
|
||||
|
||||
" Test for invalid values for a blob, list, dict in a viminfo file
|
||||
call writefile([
|
||||
\ "!GLOB_BLOB_1\tBLO\t123",
|
||||
\ "!GLOB_BLOB_2\tBLO\t012",
|
||||
\ "!GLOB_BLOB_3\tBLO\t0z1x",
|
||||
\ "!GLOB_BLOB_4\tBLO\t0z12 ab",
|
||||
\ "!GLOB_LIST_1\tLIS\t1 2",
|
||||
\ "!GLOB_DICT_1\tDIC\t1 2"], 'Xviminfo')
|
||||
call assert_fails('rv! Xviminfo', 'E15:')
|
||||
call assert_equal('123', g:GLOB_BLOB_1)
|
||||
call assert_equal(1, type(g:GLOB_BLOB_1))
|
||||
call assert_equal('012', g:GLOB_BLOB_2)
|
||||
call assert_equal(1, type(g:GLOB_BLOB_2))
|
||||
call assert_equal('0z1x', g:GLOB_BLOB_3)
|
||||
call assert_equal(1, type(g:GLOB_BLOB_3))
|
||||
call assert_equal('0z12 ab', g:GLOB_BLOB_4)
|
||||
call assert_equal(1, type(g:GLOB_BLOB_4))
|
||||
call assert_equal('1 2', g:GLOB_LIST_1)
|
||||
call assert_equal(1, type(g:GLOB_LIST_1))
|
||||
call assert_equal('1 2', g:GLOB_DICT_1)
|
||||
call assert_equal(1, type(g:GLOB_DICT_1))
|
||||
|
||||
call delete('Xviminfo')
|
||||
set viminfo-=!
|
||||
endfunc
|
||||
|
@ -357,4 +357,22 @@ func Test_delete_break_tab()
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" Test for using <BS>, <C-W> and <C-U> in virtual edit mode
|
||||
" to erase character, word and line.
|
||||
func Test_ve_backspace()
|
||||
new
|
||||
call setline(1, 'sample')
|
||||
set virtualedit=all
|
||||
set backspace=indent,eol,start
|
||||
exe "normal 15|i\<BS>\<BS>"
|
||||
call assert_equal([0, 1, 7, 5], getpos('.'))
|
||||
exe "normal 15|i\<C-W>"
|
||||
call assert_equal([0, 1, 6, 0], getpos('.'))
|
||||
exe "normal 15|i\<C-U>"
|
||||
call assert_equal([0, 1, 1, 0], getpos('.'))
|
||||
set backspace&
|
||||
set virtualedit&
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -208,6 +208,15 @@ func Test_virtual_replace()
|
||||
exe "normal iabcdefghijklmnopqrst\<Esc>0gRAB\tIJKLMNO\tQR"
|
||||
call assert_equal(['AB......CDEFGHI.Jkl',
|
||||
\ 'AB IJKLMNO QRst'], getline(12, 13))
|
||||
|
||||
" Test inserting Tab with 'noexpandtab' and 'softabstop' set to 4
|
||||
%d
|
||||
call setline(1, 'aaaaaaaaaaaaa')
|
||||
set softtabstop=4
|
||||
exe "normal gggR\<Tab>\<Tab>x"
|
||||
call assert_equal("\txaaaa", getline(1))
|
||||
set softtabstop&
|
||||
|
||||
enew!
|
||||
set noai bs&vim
|
||||
if exists('save_t_kD')
|
||||
|
49
src/typval.c
49
src/typval.c
@ -1182,7 +1182,7 @@ get_number_tv(
|
||||
get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *name;
|
||||
char_u *end;
|
||||
int extra = 0;
|
||||
int len;
|
||||
|
||||
@ -1216,12 +1216,12 @@ get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
|
||||
// Copy the string into allocated memory, handling backslashed
|
||||
// characters.
|
||||
len = (int)(p - *arg + extra);
|
||||
name = alloc(len);
|
||||
if (name == NULL)
|
||||
return FAIL;
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = name;
|
||||
len = (int)(p - *arg + extra);
|
||||
rettv->vval.v_string = alloc(len);
|
||||
if (rettv->vval.v_string == NULL)
|
||||
return FAIL;
|
||||
end = rettv->vval.v_string;
|
||||
|
||||
for (p = *arg + 1; *p != NUL && *p != '"'; )
|
||||
{
|
||||
@ -1229,12 +1229,12 @@ get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
{
|
||||
switch (*++p)
|
||||
{
|
||||
case 'b': *name++ = BS; ++p; break;
|
||||
case 'e': *name++ = ESC; ++p; break;
|
||||
case 'f': *name++ = FF; ++p; break;
|
||||
case 'n': *name++ = NL; ++p; break;
|
||||
case 'r': *name++ = CAR; ++p; break;
|
||||
case 't': *name++ = TAB; ++p; break;
|
||||
case 'b': *end++ = BS; ++p; break;
|
||||
case 'e': *end++ = ESC; ++p; break;
|
||||
case 'f': *end++ = FF; ++p; break;
|
||||
case 'n': *end++ = NL; ++p; break;
|
||||
case 'r': *end++ = CAR; ++p; break;
|
||||
case 't': *end++ = TAB; ++p; break;
|
||||
|
||||
case 'X': // hex: "\x1", "\x12"
|
||||
case 'x':
|
||||
@ -1261,9 +1261,9 @@ get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
// For "\u" store the number according to
|
||||
// 'encoding'.
|
||||
if (c != 'X')
|
||||
name += (*mb_char2bytes)(nr, name);
|
||||
end += (*mb_char2bytes)(nr, end);
|
||||
else
|
||||
*name++ = nr;
|
||||
*end++ = nr;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1275,14 +1275,14 @@ get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': *name = *p++ - '0';
|
||||
case '7': *end = *p++ - '0';
|
||||
if (*p >= '0' && *p <= '7')
|
||||
{
|
||||
*name = (*name << 3) + *p++ - '0';
|
||||
*end = (*end << 3) + *p++ - '0';
|
||||
if (*p >= '0' && *p <= '7')
|
||||
*name = (*name << 3) + *p++ - '0';
|
||||
*end = (*end << 3) + *p++ - '0';
|
||||
}
|
||||
++name;
|
||||
++end;
|
||||
break;
|
||||
|
||||
// Special key, e.g.: "\<C-W>"
|
||||
@ -1292,26 +1292,25 @@ get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
|
||||
if (p[1] != '*')
|
||||
flags |= FSK_SIMPLIFY;
|
||||
extra = trans_special(&p, name, flags, NULL);
|
||||
extra = trans_special(&p, end, flags, NULL);
|
||||
if (extra != 0)
|
||||
{
|
||||
name += extra;
|
||||
if (name >= rettv->vval.v_string + len)
|
||||
end += extra;
|
||||
if (end >= rettv->vval.v_string + len)
|
||||
iemsg("get_string_tv() used more space than allocated");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// FALLTHROUGH
|
||||
|
||||
default: MB_COPY_CHAR(p, name);
|
||||
default: MB_COPY_CHAR(p, end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
MB_COPY_CHAR(p, name);
|
||||
|
||||
MB_COPY_CHAR(p, end);
|
||||
}
|
||||
*name = NUL;
|
||||
*end = NUL;
|
||||
if (*p != NUL) // just in case
|
||||
++p;
|
||||
*arg = p;
|
||||
|
@ -409,7 +409,7 @@ get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
|
||||
fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
|
||||
if (fp == NULL)
|
||||
goto errret;
|
||||
fp->uf_dfunc_idx = UF_NOT_COMPILED;
|
||||
fp->uf_def_status = UF_NOT_COMPILED;
|
||||
pt = ALLOC_CLEAR_ONE(partial_T);
|
||||
if (pt == NULL)
|
||||
goto errret;
|
||||
@ -1001,7 +1001,7 @@ func_remove(ufunc_T *fp)
|
||||
{
|
||||
// When there is a def-function index do not actually remove the
|
||||
// function, so we can find the index when defining the function again.
|
||||
if (fp->uf_dfunc_idx >= 0)
|
||||
if (fp->uf_def_status == UF_COMPILED)
|
||||
fp->uf_flags |= FC_DEAD;
|
||||
else
|
||||
hash_remove(&func_hashtab, hi);
|
||||
@ -1046,7 +1046,7 @@ func_clear(ufunc_T *fp, int force)
|
||||
// clear this function
|
||||
func_clear_items(fp);
|
||||
funccal_unref(fp->uf_scoped, fp, force);
|
||||
delete_def_function(fp);
|
||||
clear_def_function(fp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1074,7 +1074,8 @@ func_free(ufunc_T *fp, int force)
|
||||
func_clear_free(ufunc_T *fp, int force)
|
||||
{
|
||||
func_clear(fp, force);
|
||||
func_free(fp, force);
|
||||
if (force || fp->uf_dfunc_idx == 0)
|
||||
func_free(fp, force);
|
||||
}
|
||||
|
||||
|
||||
@ -1137,7 +1138,7 @@ call_user_func(
|
||||
ga_init2(&fc->fc_funcs, sizeof(ufunc_T *), 1);
|
||||
func_ptr_ref(fp);
|
||||
|
||||
if (fp->uf_dfunc_idx != UF_NOT_COMPILED)
|
||||
if (fp->uf_def_status != UF_NOT_COMPILED)
|
||||
{
|
||||
estack_push_ufunc(fp, 1);
|
||||
save_current_sctx = current_sctx;
|
||||
@ -1662,7 +1663,7 @@ free_all_functions(void)
|
||||
// clear the def function index now
|
||||
fp = HI2UF(hi);
|
||||
fp->uf_flags &= ~FC_DEAD;
|
||||
fp->uf_dfunc_idx = UF_NOT_COMPILED;
|
||||
fp->uf_def_status = UF_NOT_COMPILED;
|
||||
|
||||
// Only free functions that are not refcounted, those are
|
||||
// supposed to be freed when no longer referenced.
|
||||
@ -2058,7 +2059,7 @@ list_func_head(ufunc_T *fp, int indent)
|
||||
msg_start();
|
||||
if (indent)
|
||||
msg_puts(" ");
|
||||
if (fp->uf_dfunc_idx != UF_NOT_COMPILED)
|
||||
if (fp->uf_def_status != UF_NOT_COMPILED)
|
||||
msg_puts("def ");
|
||||
else
|
||||
msg_puts("function ");
|
||||
@ -2107,7 +2108,7 @@ list_func_head(ufunc_T *fp, int indent)
|
||||
}
|
||||
msg_putchar(')');
|
||||
|
||||
if (fp->uf_dfunc_idx != UF_NOT_COMPILED)
|
||||
if (fp->uf_def_status != UF_NOT_COMPILED)
|
||||
{
|
||||
if (fp->uf_ret_type != &t_void)
|
||||
{
|
||||
@ -2624,7 +2625,7 @@ def_function(exarg_T *eap, char_u *name_arg)
|
||||
if (!got_int)
|
||||
{
|
||||
msg_putchar('\n');
|
||||
if (fp->uf_dfunc_idx != UF_NOT_COMPILED)
|
||||
if (fp->uf_def_status != UF_NOT_COMPILED)
|
||||
msg_puts(" enddef");
|
||||
else
|
||||
msg_puts(" endfunction");
|
||||
@ -3097,6 +3098,7 @@ def_function(exarg_T *eap, char_u *name_arg)
|
||||
fp->uf_profiling = FALSE;
|
||||
fp->uf_prof_initialized = FALSE;
|
||||
#endif
|
||||
clear_def_function(fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3162,7 +3164,7 @@ def_function(exarg_T *eap, char_u *name_arg)
|
||||
fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
|
||||
if (fp == NULL)
|
||||
goto erret;
|
||||
fp->uf_dfunc_idx = eap->cmdidx == CMD_def ? UF_TO_BE_COMPILED
|
||||
fp->uf_def_status = eap->cmdidx == CMD_def ? UF_TO_BE_COMPILED
|
||||
: UF_NOT_COMPILED;
|
||||
|
||||
if (fudi.fd_dict != NULL)
|
||||
@ -3219,7 +3221,7 @@ def_function(exarg_T *eap, char_u *name_arg)
|
||||
{
|
||||
int lnum_save = SOURCING_LNUM;
|
||||
|
||||
fp->uf_dfunc_idx = UF_TO_BE_COMPILED;
|
||||
fp->uf_def_status = UF_TO_BE_COMPILED;
|
||||
|
||||
// error messages are for the first function line
|
||||
SOURCING_LNUM = sourcing_lnum_top;
|
||||
@ -3289,7 +3291,7 @@ def_function(exarg_T *eap, char_u *name_arg)
|
||||
SOURCING_LNUM = lnum_save;
|
||||
}
|
||||
else
|
||||
fp->uf_dfunc_idx = UF_NOT_COMPILED;
|
||||
fp->uf_def_status = UF_NOT_COMPILED;
|
||||
|
||||
fp->uf_lines = newlines;
|
||||
if ((flags & FC_CLOSURE) != 0)
|
||||
@ -3323,6 +3325,9 @@ def_function(exarg_T *eap, char_u *name_arg)
|
||||
|
||||
if (eap->cmdidx == CMD_def)
|
||||
set_function_type(fp);
|
||||
else if (fp->uf_script_ctx.sc_version == SCRIPT_VERSION_VIM9)
|
||||
// :func does not use Vim9 script syntax, even in a Vim9 script file
|
||||
fp->uf_script_ctx.sc_version = SCRIPT_VERSION_MAX;
|
||||
|
||||
goto ret_free;
|
||||
|
||||
@ -3372,7 +3377,7 @@ ex_defcompile(exarg_T *eap UNUSED)
|
||||
--todo;
|
||||
ufunc = HI2UF(hi);
|
||||
if (ufunc->uf_script_ctx.sc_sid == current_sctx.sc_sid
|
||||
&& ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED)
|
||||
&& ufunc->uf_def_status == UF_TO_BE_COMPILED)
|
||||
{
|
||||
compile_def_function(ufunc, FALSE, NULL);
|
||||
|
||||
|
@ -754,6 +754,64 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1036,
|
||||
/**/
|
||||
1035,
|
||||
/**/
|
||||
1034,
|
||||
/**/
|
||||
1033,
|
||||
/**/
|
||||
1032,
|
||||
/**/
|
||||
1031,
|
||||
/**/
|
||||
1030,
|
||||
/**/
|
||||
1029,
|
||||
/**/
|
||||
1028,
|
||||
/**/
|
||||
1027,
|
||||
/**/
|
||||
1026,
|
||||
/**/
|
||||
1025,
|
||||
/**/
|
||||
1024,
|
||||
/**/
|
||||
1023,
|
||||
/**/
|
||||
1022,
|
||||
/**/
|
||||
1021,
|
||||
/**/
|
||||
1020,
|
||||
/**/
|
||||
1019,
|
||||
/**/
|
||||
1018,
|
||||
/**/
|
||||
1017,
|
||||
/**/
|
||||
1016,
|
||||
/**/
|
||||
1015,
|
||||
/**/
|
||||
1014,
|
||||
/**/
|
||||
1013,
|
||||
/**/
|
||||
1012,
|
||||
/**/
|
||||
1011,
|
||||
/**/
|
||||
1010,
|
||||
/**/
|
||||
1009,
|
||||
/**/
|
||||
1008,
|
||||
/**/
|
||||
1007,
|
||||
/**/
|
||||
|
@ -27,7 +27,7 @@
|
||||
typedef enum {
|
||||
SKIP_NOT, // condition is a constant, produce code
|
||||
SKIP_YES, // condition is a constant, do NOT produce code
|
||||
SKIP_UNKNONW // condition is not a constant, produce code
|
||||
SKIP_UNKNOWN // condition is not a constant, produce code
|
||||
} skip_T;
|
||||
|
||||
/*
|
||||
@ -1493,7 +1493,7 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (ufunc->uf_dfunc_idx != UF_NOT_COMPILED)
|
||||
if (ufunc->uf_def_status != UF_NOT_COMPILED)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1517,16 +1517,16 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
if (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED)
|
||||
if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
|
||||
if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if ((isn = generate_instr(cctx,
|
||||
ufunc->uf_dfunc_idx != UF_NOT_COMPILED ? ISN_DCALL
|
||||
ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
|
||||
: ISN_UCALL)) == NULL)
|
||||
return FAIL;
|
||||
if (ufunc->uf_dfunc_idx != UF_NOT_COMPILED)
|
||||
if (ufunc->uf_def_status != UF_NOT_COMPILED)
|
||||
{
|
||||
isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
|
||||
isn->isn_arg.dfunc.cdf_argcount = argcount;
|
||||
@ -2380,12 +2380,43 @@ free_imported(cctx_T *cctx)
|
||||
ga_clear(&cctx->ctx_imports);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if "p" points at a "#" but not at "#{".
|
||||
*/
|
||||
static int
|
||||
comment_start(char_u *p)
|
||||
{
|
||||
return p[0] == '#' && p[1] != '{';
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a pointer to the next line that isn't empty or only contains a
|
||||
* comment. Skips over white space.
|
||||
* Returns NULL if there is none.
|
||||
*/
|
||||
static char_u *
|
||||
peek_next_line(cctx_T *cctx)
|
||||
{
|
||||
int lnum = cctx->ctx_lnum;
|
||||
|
||||
while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
|
||||
{
|
||||
char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum];
|
||||
char_u *p = skipwhite(line);
|
||||
|
||||
if (*p != NUL && !comment_start(p))
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next line of the function from "cctx".
|
||||
* Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE.
|
||||
* Returns NULL when at the end.
|
||||
*/
|
||||
static char_u *
|
||||
next_line_from_context(cctx_T *cctx)
|
||||
next_line_from_context(cctx_T *cctx, int skip_comment)
|
||||
{
|
||||
char_u *line;
|
||||
|
||||
@ -2400,19 +2431,11 @@ next_line_from_context(cctx_T *cctx)
|
||||
line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
|
||||
cctx->ctx_line_start = line;
|
||||
SOURCING_LNUM = cctx->ctx_lnum + 1;
|
||||
} while (line == NULL || *skipwhite(line) == NUL);
|
||||
} while (line == NULL || *skipwhite(line) == NUL
|
||||
|| (skip_comment && comment_start(skipwhite(line))));
|
||||
return line;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if "p" points at a "#" but not at "#{".
|
||||
*/
|
||||
static int
|
||||
comment_start(char_u *p)
|
||||
{
|
||||
return p[0] == '#' && p[1] != '{';
|
||||
}
|
||||
|
||||
/*
|
||||
* If "*arg" is at the end of the line, advance to the next line.
|
||||
* Also when "whitep" points to white space and "*arg" is on a "#".
|
||||
@ -2423,7 +2446,7 @@ may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
|
||||
{
|
||||
if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
|
||||
{
|
||||
char_u *next = next_line_from_context(cctx);
|
||||
char_u *next = next_line_from_context(cctx, TRUE);
|
||||
|
||||
if (next == NULL)
|
||||
return FAIL;
|
||||
@ -2752,14 +2775,8 @@ compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
|
||||
{
|
||||
p = next_line_from_context(cctx);
|
||||
if (p == NULL)
|
||||
goto failret;
|
||||
whitep = (char_u *)" ";
|
||||
p = skipwhite(p);
|
||||
}
|
||||
if (may_get_next_line(whitep, &p, cctx) == FAIL)
|
||||
goto failret;
|
||||
if (*p == ')')
|
||||
{
|
||||
*arg = p + 1;
|
||||
@ -2986,16 +3003,10 @@ compile_list(char_u **arg, cctx_T *cctx)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
|
||||
if (may_get_next_line(whitep, &p, cctx) == FAIL)
|
||||
{
|
||||
p = next_line_from_context(cctx);
|
||||
if (p == NULL)
|
||||
{
|
||||
semsg(_(e_list_end), *arg);
|
||||
return FAIL;
|
||||
}
|
||||
whitep = (char_u *)" ";
|
||||
p = skipwhite(p);
|
||||
semsg(_(e_list_end), *arg);
|
||||
return FAIL;
|
||||
}
|
||||
if (*p == ']')
|
||||
{
|
||||
@ -3042,7 +3053,7 @@ compile_lambda(char_u **arg, cctx_T *cctx)
|
||||
// Compile it into instructions.
|
||||
compile_def_function(ufunc, TRUE, cctx);
|
||||
|
||||
if (ufunc->uf_dfunc_idx >= 0)
|
||||
if (ufunc->uf_def_status == UF_COMPILED)
|
||||
return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
|
||||
return FAIL;
|
||||
}
|
||||
@ -3112,14 +3123,10 @@ compile_dict(char_u **arg, cctx_T *cctx, int literal)
|
||||
{
|
||||
char_u *key = NULL;
|
||||
|
||||
while (**arg == NUL || (literal && **arg == '"')
|
||||
|| (VIM_ISWHITE(*whitep) && comment_start(*arg)))
|
||||
if (may_get_next_line(whitep, arg, cctx) == FAIL)
|
||||
{
|
||||
*arg = next_line_from_context(cctx);
|
||||
if (*arg == NULL)
|
||||
goto failret;
|
||||
whitep = (char_u *)" ";
|
||||
*arg = skipwhite(*arg);
|
||||
*arg = NULL;
|
||||
goto failret;
|
||||
}
|
||||
|
||||
if (**arg == '}')
|
||||
@ -3179,13 +3186,10 @@ compile_dict(char_u **arg, cctx_T *cctx, int literal)
|
||||
|
||||
whitep = *arg + 1;
|
||||
*arg = skipwhite(*arg + 1);
|
||||
while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
|
||||
if (may_get_next_line(whitep, arg, cctx) == FAIL)
|
||||
{
|
||||
*arg = next_line_from_context(cctx);
|
||||
if (*arg == NULL)
|
||||
goto failret;
|
||||
whitep = (char_u *)" ";
|
||||
*arg = skipwhite(*arg);
|
||||
*arg = NULL;
|
||||
goto failret;
|
||||
}
|
||||
|
||||
if (compile_expr0(arg, cctx) == FAIL)
|
||||
@ -3193,15 +3197,11 @@ compile_dict(char_u **arg, cctx_T *cctx, int literal)
|
||||
++count;
|
||||
|
||||
whitep = *arg;
|
||||
p = skipwhite(*arg);
|
||||
while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
|
||||
*arg = skipwhite(*arg);
|
||||
if (may_get_next_line(whitep, arg, cctx) == FAIL)
|
||||
{
|
||||
*arg = next_line_from_context(cctx);
|
||||
if (*arg == NULL)
|
||||
goto failret;
|
||||
whitep = (char_u *)" ";
|
||||
*arg = skipwhite(*arg);
|
||||
p = *arg;
|
||||
*arg = NULL;
|
||||
goto failret;
|
||||
}
|
||||
if (**arg == '}')
|
||||
break;
|
||||
@ -3506,6 +3506,24 @@ compile_subscript(
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
char_u *p = skipwhite(*arg);
|
||||
|
||||
if (*p == NUL || (VIM_ISWHITE(**arg) && comment_start(p)))
|
||||
{
|
||||
char_u *next = peek_next_line(cctx);
|
||||
|
||||
// If a following line starts with "->{" or "->X" advance to that
|
||||
// line, so that a line break before "->" is allowed.
|
||||
if (next != NULL && next[0] == '-' && next[1] == '>'
|
||||
&& (next[2] == '{' || ASCII_ISALPHA(next[2])))
|
||||
{
|
||||
next = next_line_from_context(cctx, TRUE);
|
||||
if (next == NULL)
|
||||
return FAIL;
|
||||
*arg = skipwhite(next);
|
||||
}
|
||||
}
|
||||
|
||||
if (**arg == '(')
|
||||
{
|
||||
garray_T *stack = &cctx->ctx_type_stack;
|
||||
@ -3526,8 +3544,6 @@ compile_subscript(
|
||||
}
|
||||
else if (**arg == '-' && (*arg)[1] == '>')
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
if (generate_ppconst(cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
@ -3538,7 +3554,10 @@ compile_subscript(
|
||||
return FAIL;
|
||||
*start_leader = end_leader; // don't apply again later
|
||||
|
||||
*arg = skipwhite(*arg + 2);
|
||||
p = *arg + 2;
|
||||
*arg = skipwhite(p);
|
||||
if (may_get_next_line(p, arg, cctx) == FAIL)
|
||||
return FAIL;
|
||||
if (**arg == '{')
|
||||
{
|
||||
// lambda call: list->{lambda}
|
||||
@ -3576,7 +3595,10 @@ compile_subscript(
|
||||
if (generate_ppconst(cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
*arg = skipwhite(*arg + 1);
|
||||
p = *arg + 1;
|
||||
*arg = skipwhite(p);
|
||||
if (may_get_next_line(p, arg, cctx) == FAIL)
|
||||
return FAIL;
|
||||
if (compile_expr0(arg, cctx) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
@ -3611,14 +3633,14 @@ compile_subscript(
|
||||
}
|
||||
else if (**arg == '.' && (*arg)[1] != '.')
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
if (generate_ppconst(cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
++*arg;
|
||||
p = *arg;
|
||||
if (may_get_next_line(*arg, arg, cctx) == FAIL)
|
||||
return FAIL;
|
||||
// dictionary member: dict.name
|
||||
p = *arg;
|
||||
if (eval_isnamec1(*p))
|
||||
while (eval_isnamec(*p))
|
||||
MB_PTR_ADV(p);
|
||||
@ -4335,9 +4357,9 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
garray_T *instr = &cctx->ctx_instr;
|
||||
garray_T *stack = &cctx->ctx_type_stack;
|
||||
int alt_idx = instr->ga_len;
|
||||
int end_idx;
|
||||
int end_idx = 0;
|
||||
isn_T *isn;
|
||||
type_T *type1;
|
||||
type_T *type1 = NULL;
|
||||
type_T *type2;
|
||||
int has_const_expr = FALSE;
|
||||
int const_value = FALSE;
|
||||
@ -4539,7 +4561,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
||||
|
||||
if (ufunc == NULL)
|
||||
return NULL;
|
||||
if (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED
|
||||
if (ufunc->uf_def_status == UF_TO_BE_COMPILED
|
||||
&& compile_def_function(ufunc, TRUE, cctx) == FAIL)
|
||||
return NULL;
|
||||
|
||||
@ -4650,6 +4672,24 @@ generate_loadvar(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vim9_declare_error(char_u *name)
|
||||
{
|
||||
char *scope = "";
|
||||
|
||||
switch (*name)
|
||||
{
|
||||
case 'g': scope = _("global"); break;
|
||||
case 'b': scope = _("buffer"); break;
|
||||
case 'w': scope = _("window"); break;
|
||||
case 't': scope = _("tab"); break;
|
||||
case 'v': scope = "v:"; break;
|
||||
case '$': semsg(_(e_declare_env_var), name); return;
|
||||
default: return;
|
||||
}
|
||||
semsg(_(e_declare_var), scope, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile declaration and assignment:
|
||||
* "let var", "let var = expr", "const var = expr" and "var = expr"
|
||||
@ -4846,8 +4886,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
type = &t_string;
|
||||
if (is_decl)
|
||||
{
|
||||
semsg(_("E1065: Cannot declare an environment variable: %s"),
|
||||
name);
|
||||
vim9_declare_error(name);
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
@ -4871,8 +4910,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
dest = dest_global;
|
||||
if (is_decl)
|
||||
{
|
||||
semsg(_("E1016: Cannot declare a global variable: %s"),
|
||||
name);
|
||||
vim9_declare_error(name);
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
@ -4881,8 +4919,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
dest = dest_buffer;
|
||||
if (is_decl)
|
||||
{
|
||||
semsg(_("E1078: Cannot declare a buffer variable: %s"),
|
||||
name);
|
||||
vim9_declare_error(name);
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
@ -4891,8 +4928,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
dest = dest_window;
|
||||
if (is_decl)
|
||||
{
|
||||
semsg(_("E1079: Cannot declare a window variable: %s"),
|
||||
name);
|
||||
vim9_declare_error(name);
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
@ -4901,7 +4937,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
dest = dest_tab;
|
||||
if (is_decl)
|
||||
{
|
||||
semsg(_("E1080: Cannot declare a tab variable: %s"), name);
|
||||
vim9_declare_error(name);
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
@ -4924,7 +4960,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
type = typval2type(vtv);
|
||||
if (is_decl)
|
||||
{
|
||||
semsg(_("E1064: Cannot declare a v: variable: %s"), name);
|
||||
vim9_declare_error(name);
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
@ -5688,7 +5724,7 @@ compile_if(char_u *arg, cctx_T *cctx)
|
||||
else
|
||||
{
|
||||
// Not a constant, generate instructions for the expression.
|
||||
cctx->ctx_skip = SKIP_UNKNONW;
|
||||
cctx->ctx_skip = SKIP_UNKNOWN;
|
||||
if (generate_ppconst(cctx, &ppconst) == FAIL)
|
||||
return NULL;
|
||||
}
|
||||
@ -5700,7 +5736,7 @@ compile_if(char_u *arg, cctx_T *cctx)
|
||||
// "is_had_return" will be reset if any block does not end in :return
|
||||
scope->se_u.se_if.is_had_return = TRUE;
|
||||
|
||||
if (cctx->ctx_skip == SKIP_UNKNONW)
|
||||
if (cctx->ctx_skip == SKIP_UNKNOWN)
|
||||
{
|
||||
// "where" is set when ":elseif", "else" or ":endif" is found
|
||||
scope->se_u.se_if.is_if_label = instr->ga_len;
|
||||
@ -5731,7 +5767,7 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
||||
if (!cctx->ctx_had_return)
|
||||
scope->se_u.se_if.is_had_return = FALSE;
|
||||
|
||||
if (cctx->ctx_skip == SKIP_UNKNONW)
|
||||
if (cctx->ctx_skip == SKIP_UNKNOWN)
|
||||
{
|
||||
if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
|
||||
JUMP_ALWAYS, cctx) == FAIL)
|
||||
@ -5761,7 +5797,7 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
||||
else
|
||||
{
|
||||
// Not a constant, generate instructions for the expression.
|
||||
cctx->ctx_skip = SKIP_UNKNONW;
|
||||
cctx->ctx_skip = SKIP_UNKNOWN;
|
||||
if (generate_ppconst(cctx, &ppconst) == FAIL)
|
||||
return NULL;
|
||||
|
||||
@ -5794,7 +5830,7 @@ compile_else(char_u *arg, cctx_T *cctx)
|
||||
if (scope->se_skip_save != SKIP_YES)
|
||||
{
|
||||
// jump from previous block to the end, unless the else block is empty
|
||||
if (cctx->ctx_skip == SKIP_UNKNONW)
|
||||
if (cctx->ctx_skip == SKIP_UNKNOWN)
|
||||
{
|
||||
if (!cctx->ctx_had_return
|
||||
&& compile_jump_to_end(&scope->se_u.se_if.is_end_label,
|
||||
@ -5802,7 +5838,7 @@ compile_else(char_u *arg, cctx_T *cctx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cctx->ctx_skip == SKIP_UNKNONW)
|
||||
if (cctx->ctx_skip == SKIP_UNKNOWN)
|
||||
{
|
||||
if (scope->se_u.se_if.is_if_label >= 0)
|
||||
{
|
||||
@ -5813,7 +5849,7 @@ compile_else(char_u *arg, cctx_T *cctx)
|
||||
}
|
||||
}
|
||||
|
||||
if (cctx->ctx_skip != SKIP_UNKNONW)
|
||||
if (cctx->ctx_skip != SKIP_UNKNOWN)
|
||||
cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
|
||||
}
|
||||
|
||||
@ -6517,13 +6553,22 @@ theend:
|
||||
|
||||
/*
|
||||
* Add a function to the list of :def functions.
|
||||
* This "sets ufunc->uf_dfunc_idx" but the function isn't compiled yet.
|
||||
* This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet.
|
||||
*/
|
||||
static int
|
||||
add_def_function(ufunc_T *ufunc)
|
||||
{
|
||||
dfunc_T *dfunc;
|
||||
|
||||
if (def_functions.ga_len == 0)
|
||||
{
|
||||
// The first position is not used, so that a zero uf_dfunc_idx means it
|
||||
// wasn't set.
|
||||
if (ga_grow(&def_functions, 1) == FAIL)
|
||||
return FAIL;
|
||||
++def_functions.ga_len;
|
||||
}
|
||||
|
||||
// Add the function to "def_functions".
|
||||
if (ga_grow(&def_functions, 1) == FAIL)
|
||||
return FAIL;
|
||||
@ -6563,7 +6608,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
|
||||
// When using a function that was compiled before: Free old instructions.
|
||||
// Otherwise add a new entry in "def_functions".
|
||||
if (ufunc->uf_dfunc_idx >= 0)
|
||||
if (ufunc->uf_dfunc_idx > 0)
|
||||
{
|
||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||
+ ufunc->uf_dfunc_idx;
|
||||
@ -6656,7 +6701,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
if (line != NULL && *line == '|')
|
||||
// the line continues after a '|'
|
||||
++line;
|
||||
else if (line != NULL && *line != NUL
|
||||
else if (line != NULL && *skipwhite(line) != NUL
|
||||
&& !(*line == '#' && (line == cctx.ctx_line_start
|
||||
|| VIM_ISWHITE(line[-1]))))
|
||||
{
|
||||
@ -6665,7 +6710,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
}
|
||||
else
|
||||
{
|
||||
line = next_line_from_context(&cctx);
|
||||
line = next_line_from_context(&cctx, FALSE);
|
||||
if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
|
||||
// beyond the last line
|
||||
break;
|
||||
@ -6838,6 +6883,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
p = skipwhite(p);
|
||||
|
||||
if (cctx.ctx_skip == SKIP_YES
|
||||
&& ea.cmdidx != CMD_if
|
||||
&& ea.cmdidx != CMD_elseif
|
||||
&& ea.cmdidx != CMD_else
|
||||
&& ea.cmdidx != CMD_endif)
|
||||
@ -7013,6 +7059,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
dfunc->df_closure_count = cctx.ctx_closure_count;
|
||||
if (cctx.ctx_outer_used)
|
||||
ufunc->uf_flags |= FC_CLOSURE;
|
||||
ufunc->uf_def_status = UF_COMPILED;
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
@ -7032,7 +7079,7 @@ erret:
|
||||
if (!dfunc->df_deleted
|
||||
&& ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
|
||||
--def_functions.ga_len;
|
||||
ufunc->uf_dfunc_idx = UF_NOT_COMPILED;
|
||||
ufunc->uf_def_status = UF_NOT_COMPILED;
|
||||
|
||||
while (cctx.ctx_scope != NULL)
|
||||
drop_scope(&cctx);
|
||||
@ -7260,17 +7307,19 @@ delete_def_function_contents(dfunc_T *dfunc)
|
||||
}
|
||||
|
||||
/*
|
||||
* When a user function is deleted, delete any associated def function.
|
||||
* When a user function is deleted, clear the contents of any associated def
|
||||
* function. The position in def_functions can be re-used.
|
||||
*/
|
||||
void
|
||||
delete_def_function(ufunc_T *ufunc)
|
||||
clear_def_function(ufunc_T *ufunc)
|
||||
{
|
||||
if (ufunc->uf_dfunc_idx >= 0)
|
||||
if (ufunc->uf_dfunc_idx > 0)
|
||||
{
|
||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||
+ ufunc->uf_dfunc_idx;
|
||||
|
||||
delete_def_function_contents(dfunc);
|
||||
ufunc->uf_def_status = UF_NOT_COMPILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,10 +487,10 @@ call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr)
|
||||
int error;
|
||||
int idx;
|
||||
|
||||
if (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED
|
||||
if (ufunc->uf_def_status == UF_TO_BE_COMPILED
|
||||
&& compile_def_function(ufunc, FALSE, NULL) == FAIL)
|
||||
return FAIL;
|
||||
if (ufunc->uf_dfunc_idx >= 0)
|
||||
if (ufunc->uf_def_status == UF_COMPILED)
|
||||
{
|
||||
// The function has been compiled, can call it quickly. For a function
|
||||
// that was defined later: we can call it directly next time.
|
||||
@ -671,8 +671,8 @@ call_def_function(
|
||||
// Like STACK_TV_VAR but use the outer scope
|
||||
#define STACK_OUT_TV_VAR(idx) (((typval_T *)ectx.ec_outer_stack->ga_data) + ectx.ec_outer_frame + STACK_FRAME_SIZE + idx)
|
||||
|
||||
if (ufunc->uf_dfunc_idx == UF_NOT_COMPILED
|
||||
|| (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED
|
||||
if (ufunc->uf_def_status == UF_NOT_COMPILED
|
||||
|| (ufunc->uf_def_status == UF_TO_BE_COMPILED
|
||||
&& compile_def_function(ufunc, FALSE, NULL) == FAIL))
|
||||
{
|
||||
if (called_emsg == called_emsg_before)
|
||||
@ -2119,12 +2119,8 @@ call_def_function(
|
||||
list_T *list;
|
||||
int count = iptr->isn_arg.number;
|
||||
|
||||
// type will have been checked to be a list
|
||||
tv = STACK_TV_BOT(-1);
|
||||
if (tv->v_type != VAR_LIST)
|
||||
{
|
||||
emsg(_(e_listreq));
|
||||
goto failed;
|
||||
}
|
||||
list = tv->vval.v_list;
|
||||
|
||||
// no error for short list, expect it to be checked earlier
|
||||
@ -2148,18 +2144,10 @@ call_def_function(
|
||||
listitem_T *li;
|
||||
int index = iptr->isn_arg.number;
|
||||
|
||||
// get list item: list is at stack-1, push item
|
||||
// Get list item: list is at stack-1, push item.
|
||||
// List type and length is checked for when compiling.
|
||||
tv = STACK_TV_BOT(-1);
|
||||
if (tv->v_type != VAR_LIST)
|
||||
{
|
||||
emsg(_(e_listreq));
|
||||
goto failed;
|
||||
}
|
||||
if ((li = list_find(tv->vval.v_list, index)) == NULL)
|
||||
{
|
||||
semsg(_(e_listidx), index);
|
||||
goto failed;
|
||||
}
|
||||
li = list_find(tv->vval.v_list, index);
|
||||
|
||||
if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
|
||||
goto failed;
|
||||
@ -2391,10 +2379,10 @@ ex_disassemble(exarg_T *eap)
|
||||
semsg(_("E1061: Cannot find function %s"), eap->arg);
|
||||
return;
|
||||
}
|
||||
if (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED
|
||||
if (ufunc->uf_def_status == UF_TO_BE_COMPILED
|
||||
&& compile_def_function(ufunc, FALSE, NULL) == FAIL)
|
||||
return;
|
||||
if (ufunc->uf_dfunc_idx < 0)
|
||||
if (ufunc->uf_def_status != UF_COMPILED)
|
||||
{
|
||||
semsg(_("E1062: Function %s is not compiled"), eap->arg);
|
||||
return;
|
||||
|
@ -471,7 +471,7 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg)
|
||||
}
|
||||
|
||||
for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
|
||||
if (*p == ':' && p != arg + 1)
|
||||
if (*p == ':' && (VIM_ISWHITE(p[1]) || p != arg + 1))
|
||||
break;
|
||||
|
||||
if (*p != ':')
|
||||
@ -507,7 +507,7 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg)
|
||||
/*
|
||||
* Check if the type of script variable "dest" allows assigning "value".
|
||||
*/
|
||||
void
|
||||
int
|
||||
check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
|
||||
{
|
||||
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
|
||||
@ -521,13 +521,15 @@ check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
|
||||
if (sv->sv_tv == dest)
|
||||
{
|
||||
if (sv->sv_const)
|
||||
{
|
||||
semsg(_(e_readonlyvar), name);
|
||||
else
|
||||
check_type(sv->sv_type, typval2type(value), TRUE);
|
||||
return;
|
||||
return FAIL;
|
||||
}
|
||||
return check_type(sv->sv_type, typval2type(value), TRUE);
|
||||
}
|
||||
}
|
||||
iemsg("check_script_var_type(): not found");
|
||||
return OK; // not really
|
||||
}
|
||||
|
||||
#endif // FEAT_EVAL
|
||||
|
Reference in New Issue
Block a user