Merge remote-tracking branch 'vim/master'

This commit is contained in:
ichizok
2021-01-17 07:05:35 +09:00
88 changed files with 1839 additions and 452 deletions
View File
+6
View File
@@ -0,0 +1,6 @@
coverage:
range: "80...100"
status:
project:
default:
threshold: 0.05%
+1
View File
@@ -164,6 +164,7 @@ runtime/syntax/nsis.vim @k-takata
runtime/syntax/pdf.vim @tpope
runtime/syntax/php.vim @TysonAndre
runtime/syntax/privoxy.vim @dkearns
runtime/syntax/prolog.vim @XVilka
runtime/syntax/rc.vim @chrisbra
runtime/syntax/rpcgen.vim @cecamp
runtime/syntax/ruby.vim @dkearns
+21 -2
View File
@@ -362,6 +362,10 @@ func dist#ft#FTinc()
setf aspvbs
elseif lines =~ "<?"
setf php
" Pascal supports // comments but they're vary rarely used for file
" headers so assume POV-Ray
elseif lines =~ '^\s*\%({\|(\*\)' || lines =~? s:ft_pascal_keywords
setf pascal
else
call dist#ft#FTasmsyntax()
if exists("b:asmsyntax")
@@ -408,6 +412,9 @@ func dist#ft#FTprogress_asm()
setf progress
endfunc
let s:ft_pascal_comments = '^\s*\%({\|(\*\|//\)'
let s:ft_pascal_keywords = '^\s*\%(program\|unit\|library\|uses\|begin\|procedure\|function\|const\|type\|var\)\>'
func dist#ft#FTprogress_pascal()
if exists("g:filetype_p")
exe "setf " . g:filetype_p
@@ -419,8 +426,7 @@ func dist#ft#FTprogress_pascal()
let lnum = 1
while lnum <= 10 && lnum < line('$')
let line = getline(lnum)
if line =~ '^\s*\(program\|unit\|procedure\|function\|const\|type\|var\)\>'
\ || line =~ '^\s*{' || line =~ '^\s*(\*'
if line =~ s:ft_pascal_comments || line =~? s:ft_pascal_keywords
setf pascal
return
elseif line !~ '^\s*$' || line =~ '^/\*'
@@ -433,6 +439,19 @@ func dist#ft#FTprogress_pascal()
setf progress
endfunc
func dist#ft#FTpp()
if exists("g:filetype_pp")
exe "setf " . g:filetype_pp
else
let line = getline(nextnonblank(1))
if line =~ s:ft_pascal_comments || line =~? s:ft_pascal_keywords
setf pascal
else
setf puppet
endif
endif
endfunc
func dist#ft#FTr()
let max = line("$") > 50 ? 50 : line("$")
+2 -2
View File
@@ -1,4 +1,4 @@
*editing.txt* For Vim version 8.2. Last change: 2020 Dec 19
*editing.txt* For Vim version 8.2. Last change: 2021 Jan 08
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1014,7 +1014,7 @@ to write anyway add a '!' to the command.
*write-permissions*
When writing a new file the permissions are read-write. For unix the mask is
0666 with additionally umask applied. When writing a file that was read Vim
0o666 with additionally umask applied. When writing a file that was read Vim
will preserve the permissions, but clear the s-bit.
*write-readonly*
+57 -5
View File
@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.2. Last change: 2021 Jan 10
*eval.txt* For Vim version 8.2. Last change: 2021 Jan 13
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -314,6 +314,9 @@ similar to -1. >
:let shortlist = mylist[2:2] " List with one item: [3]
:let otherlist = mylist[:] " make a copy of the List
Notice that the last index is inclusive. If you prefer using an exclusive
index use the |slice()| method.
If the first index is beyond the last item of the List or the second item is
before the first item, the result is an empty list. There is no error
message.
@@ -1217,6 +1220,9 @@ a Number it is first converted to a String.
In Vim9 script the indexes are character indexes. To use byte indexes use
|strpart()|.
The item at index expr1b is included, it is inclusive. For an exclusive index
use the |slice()| function.
If expr1a is omitted zero is used. If expr1b is omitted the length of the
string minus one is used.
@@ -2536,6 +2542,9 @@ expand({expr} [, {nosuf} [, {list}]])
expandcmd({expr}) String expand {expr} like with `:edit`
extend({expr1}, {expr2} [, {expr3}])
List/Dict insert items of {expr2} into {expr1}
extendnew({expr1}, {expr2} [, {expr3}])
List/Dict like |extend()| but creates a new
List or Dictionary
feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer
filereadable({file}) Number |TRUE| if {file} is a readable file
filewritable({file}) Number |TRUE| if {file} is a writable file
@@ -2784,6 +2793,7 @@ pyxeval({expr}) any evaluate |python_x| expression
rand([{expr}]) Number get pseudo-random number
range({expr} [, {max} [, {stride}]])
List items from {expr} to {max}
readblob({fname}) Blob read a |Blob| from {fname}
readdir({dir} [, {expr} [, {dict}]])
List file names in {dir} selected by {expr}
readdirex({dir} [, {expr} [, {dict}]])
@@ -2892,6 +2902,8 @@ sign_unplacelist({list}) List unplace a list of signs
simplify({filename}) String simplify filename as much as possible
sin({expr}) Float sine of {expr}
sinh({expr}) Float hyperbolic sine of {expr}
slice({expr}, {start} [, {end}]) String, List or Blob
slice of a String, List or Blob
sort({list} [, {func} [, {dict}]])
List sort {list}, using {func} to compare
sound_clear() none stop playing all sounds
@@ -3025,7 +3037,8 @@ tr({src}, {fromstr}, {tostr}) String translate chars of {src} in {fromstr}
trim({text} [, {mask} [, {dir}]])
String trim characters in {mask} from {text}
trunc({expr}) Float truncate Float {expr}
type({name}) Number type of variable {name}
type({expr}) Number type of value {expr}
typename({expr}) String representation of the type of {expr}
undofile({name}) String undo file name for {name}
undotree() List undo file tree
uniq({list} [, {func} [, {dict}]])
@@ -4532,6 +4545,13 @@ extend({expr1}, {expr2} [, {expr3}]) *extend()*
mylist->extend(otherlist)
extendnew({expr1}, {expr2} [, {expr3}]) *extendnew()*
Like |extend()| but instead of adding items to {expr1} a new
List or Dictionary is created and returned. {expr1} remains
unchanged. Items can still be changed by {expr2}, if you
don't want that use |deepcopy()| first.
feedkeys({string} [, {mode}]) *feedkeys()*
Characters in {string} are queued for processing as if they
come from a mapping or were typed by the user.
@@ -8266,6 +8286,14 @@ rand([{expr}]) *rand()* *random*
:echo rand(seed)
:echo rand(seed) % 16 " random number 0 - 15
<
readblob({fname}) *readblob()*
Read file {fname} in binary mode and return a |Blob|.
When the file can't be opened an error message is given and
the result is an empty |Blob|.
Also see |readfile()| and |writefile()|.
readdir({directory} [, {expr} [, {dict}]]) *readdir()*
Return a list with file and directory names in {directory}.
You can also use |glob()| if you don't need to do complicated
@@ -8380,6 +8408,7 @@ readdirex({directory} [, {expr} [, {dict}]]) *readdirex()*
Can also be used as a |method|: >
GetDirName()->readdirex()
<
*readfile()*
readfile({fname} [, {type} [, {max}]])
Read file {fname} and return a |List|, each line of the file
@@ -8391,8 +8420,6 @@ readfile({fname} [, {type} [, {max}]])
- When the last line ends in a NL an extra empty list item is
added.
- No CR characters are removed.
When {type} contains "B" a |Blob| is returned with the binary
data of the file unmodified.
Otherwise:
- CR characters that appear before a NL are removed.
- Whether the last line ends in a NL or not does not matter.
@@ -8410,6 +8437,9 @@ readfile({fname} [, {type} [, {max}]])
Note that without {max} the whole file is read into memory.
Also note that there is no recognition of encoding. Read a
file into a buffer if you need to.
Deprecated (use |readblob()| instead): When {type} contains
"B" a |Blob| is returned with the binary data of the file
unmodified.
When the file can't be opened an error message is given and
the result is an empty list.
Also see |writefile()|.
@@ -9852,6 +9882,18 @@ sinh({expr}) *sinh()*
{only available when compiled with the |+float| feature}
slice({expr}, {start} [, {end}]) *slice()*
Similar to using a |slice| "expr[start : end]", but "end" is
used exclusive. And for a string the indexes are used as
character indexes instead of byte indexes, like in
|vim9script|.
When {end} is omitted the slice continues to the last item.
When {end} is -1 the last item is omitted.
Can also be used as a |method|: >
GetList()->slice(offset)
sort({list} [, {func} [, {dict}]]) *sort()* *E702*
Sort the items in {list} in-place. Returns {list}.
@@ -11131,6 +11173,14 @@ type({expr}) The result is a Number representing the type of {expr}.
< Can also be used as a |method|: >
mylist->type()
typename({expr}) *typename()*
Return a string representation of the type of {expr}.
Example: >
echo typename([1, 2, 3])
list<number>
undofile({name}) *undofile()*
Return the name of the undo file that would be used for a file
with name {name} when writing. This uses the 'undodir'
@@ -11288,9 +11338,11 @@ win_execute({id}, {command} [, {silent}]) *win_execute()*
call win_execute(winid, 'set syntax=python')
< Doing the same with `setwinvar()` would not trigger
autocommands and not actually show syntax highlighting.
*E994*
Not all commands are allowed in popup windows.
When window {id} does not exist then no error is given.
When window {id} does not exist then no error is given and
an empty string is returned.
Can also be used as a |method|, the base is passed as the
second argument: >
+2
View File
@@ -1592,6 +1592,8 @@ tag command action ~
|:sign| :sig[n] manipulate signs
|:silent| :sil[ent] run a command silently
|:sleep| :sl[eep] do nothing for a few seconds
|:sleep!| :sl[eep]! do nothing for a few seconds, without the
cursor visible
|:slast| :sla[st] split window and go to last file in the
argument list
|:smagic| :sm[agic] :substitute with 'magic'
+2 -2
View File
@@ -1,4 +1,4 @@
*options.txt* For Vim version 8.2. Last change: 2020 Dec 21
*options.txt* For Vim version 8.2. Last change: 2021 Jan 08
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -438,7 +438,7 @@ the system, mostly it is something like 256 or 1024 characters.
CTRL-? CTRL-H
not CTRL-? CTRL-?
(CTRL-? is 0177 octal, 0x7f hex)
(CTRL-? is 0o177 octal, 0x7f hex)
If your delete key terminal code is wrong, but the
code for backspace is alright, you can put this in
+5 -3
View File
@@ -1,4 +1,4 @@
*os_vms.txt* For Vim version 8.2. Last change: 2020 Dec 30
*os_vms.txt* For Vim version 8.2. Last change: 2021 Jan 04
VIM REFERENCE MANUAL
@@ -767,8 +767,10 @@ GNU_TOOLS.ZIP package downloadable from http://www.polarhome.com/vim/
Version 8.2
- make all changes needed for clean compile build of v8.2 on VMS on all platforms
- test on VSI OpenVMS platforms
- added XPM support - Motif GUI with toolbar on all platforms
- fix the call mkdir bug (vicente_polo@yahoo.es)
- test on VSI OpenVMS Alpha and Itanium platforms
- added LUA support
- added XPM support - Motif GUI with toolbar on all platforms
- XPM v3.4.11 libraries for IA64, AXP and VAX are added
- start integrating the new test scripts
+4 -3
View File
@@ -1,4 +1,4 @@
*pattern.txt* For Vim version 8.2. Last change: 2020 Dec 25
*pattern.txt* For Vim version 8.2. Last change: 2021 Jan 08
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1179,7 +1179,7 @@ x A single character, with no special meaning, matches itself
\b <BS>
\n line break, see above |/[\n]|
\d123 decimal number of character
\o40 octal number of character up to 0377
\o40 octal number of character up to 0o377
\x20 hexadecimal number of character up to 0xff
\u20AC hex. number of multibyte character up to 0xffff
\U1234 hex. number of multibyte character up to 0xffffffff
@@ -1217,7 +1217,8 @@ x A single character, with no special meaning, matches itself
\%d123 Matches the character specified with a decimal number. Must be
followed by a non-digit.
\%o40 Matches the character specified with an octal number up to 0377.
Numbers below 040 must be followed by a non-octal digit or a non-digit.
Numbers below 0o40 must be followed by a non-octal digit or a
non-digit.
\%x2a Matches the character specified with up to two hexadecimal characters.
\%u20AC Matches the character specified with up to four hexadecimal
characters.
+11
View File
@@ -1806,6 +1806,8 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX*
09.2 usr_09.txt /*09.2*
09.3 usr_09.txt /*09.3*
09.4 usr_09.txt /*09.4*
0o eval.txt /*0o*
0x eval.txt /*0x*
10.1 usr_10.txt /*10.1*
10.2 usr_10.txt /*10.2*
10.3 usr_10.txt /*10.3*
@@ -2017,6 +2019,7 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX*
:AdaTagFile ft_ada.txt /*:AdaTagFile*
:AdaTypes ft_ada.txt /*:AdaTypes*
:Arguments terminal.txt /*:Arguments*
:Asm terminal.txt /*:Asm*
:Break terminal.txt /*:Break*
:Cfilter quickfix.txt /*:Cfilter*
:Clear terminal.txt /*:Clear*
@@ -5840,6 +5843,7 @@ characterwise motion.txt /*characterwise*
characterwise-register change.txt /*characterwise-register*
characterwise-visual visual.txt /*characterwise-visual*
charclass() eval.txt /*charclass()*
charcol() eval.txt /*charcol()*
charconvert_from-variable eval.txt /*charconvert_from-variable*
charconvert_to-variable eval.txt /*charconvert_to-variable*
charidx() eval.txt /*charidx()*
@@ -7041,6 +7045,7 @@ getbufvar() eval.txt /*getbufvar()*
getchangelist() eval.txt /*getchangelist()*
getchar() eval.txt /*getchar()*
getcharmod() eval.txt /*getcharmod()*
getcharpos() eval.txt /*getcharpos()*
getcharsearch() eval.txt /*getcharsearch()*
getcmdline() eval.txt /*getcmdline()*
getcmdpos() eval.txt /*getcmdpos()*
@@ -7048,6 +7053,7 @@ getcmdtype() eval.txt /*getcmdtype()*
getcmdwintype() eval.txt /*getcmdwintype()*
getcompletion() eval.txt /*getcompletion()*
getcurpos() eval.txt /*getcurpos()*
getcursorcharpos() eval.txt /*getcursorcharpos()*
getcwd() eval.txt /*getcwd()*
getenv() eval.txt /*getenv()*
getfontname() eval.txt /*getfontname()*
@@ -8404,6 +8410,7 @@ notation intro.txt /*notation*
notepad gui_w32.txt /*notepad*
nr2char() eval.txt /*nr2char()*
nroff.vim syntax.txt /*nroff.vim*
null vim9.txt /*null*
null-variable eval.txt /*null-variable*
number_relativenumber options.txt /*number_relativenumber*
numbered-function eval.txt /*numbered-function*
@@ -9017,8 +9024,10 @@ set-spc-auto spell.txt /*set-spc-auto*
setbufline() eval.txt /*setbufline()*
setbufvar() eval.txt /*setbufvar()*
setcellwidths() eval.txt /*setcellwidths()*
setcharpos() eval.txt /*setcharpos()*
setcharsearch() eval.txt /*setcharsearch()*
setcmdpos() eval.txt /*setcmdpos()*
setcursorcharpos() eval.txt /*setcursorcharpos()*
setenv() eval.txt /*setenv()*
setfperm() eval.txt /*setfperm()*
setline() eval.txt /*setline()*
@@ -9699,6 +9708,7 @@ termdebug-prompt terminal.txt /*termdebug-prompt*
termdebug-starting terminal.txt /*termdebug-starting*
termdebug-stepping terminal.txt /*termdebug-stepping*
termdebug-variables terminal.txt /*termdebug-variables*
termdebug_disasm_window terminal.txt /*termdebug_disasm_window*
termdebug_map_K terminal.txt /*termdebug_map_K*
termdebug_popup terminal.txt /*termdebug_popup*
termdebug_shortcuts terminal.txt /*termdebug_shortcuts*
@@ -10233,6 +10243,7 @@ vim9-reload vim9.txt /*vim9-reload*
vim9-scopes vim9.txt /*vim9-scopes*
vim9-script-intro usr_46.txt /*vim9-script-intro*
vim9-types vim9.txt /*vim9-types*
vim9-user-command vim9.txt /*vim9-user-command*
vim9.txt vim9.txt /*vim9.txt*
vim9script vim9.txt /*vim9script*
vim: options.txt /*vim:*
+14
View File
@@ -373,6 +373,10 @@ Added by Vim (there are no standard codes for these):
t_Ri restore icon text from stack *t_Ri* *'t_Ri'*
t_TE end of "raw" mode *t_TE* *'t_TE'*
t_TI put terminal into "raw" mode *t_TI* *'t_TI'*
t_fd disable focus-event tracking *t_TI* *'t_TI'*
|xterm-focus-event|
t_fe enable focus-event tracking *t_TI* *'t_TI'*
|xterm-focus-event|
Some codes have a start, middle and end part. The start and end are defined
by the termcap option, the middle part is text.
@@ -546,6 +550,16 @@ And run "xrdb -merge .Xresources" to make it effective. You can check the
value with the context menu (right mouse button while CTRL key is pressed),
there should be a tick at allow-window-ops.
*xterm-focus-event*
Some terminals including xterm support the focus event tracking feature.
If this feature is enabled by the 't_fe' sequence, special key sequences are
sent from the terminal to Vim every time the terminal gains or loses focus.
Vim fires focus events (|FocusGained|/|FocusLost|) by handling them accordingly.
Focus event tracking is disabled by a 't_fd' sequence when exiting "raw" mode.
If you would like to disable this feature, add the following to your .vimrc:
`set t_fd=`
`set t_fe=`
*termcap-colors*
Note about colors: The 't_Co' option tells Vim the number of colors available.
When it is non-zero, the 't_AB' and 't_AF' options are used to set the color.
+9 -1
View File
@@ -1,4 +1,4 @@
*terminal.txt* For Vim version 8.2. Last change: 2020 Dec 28
*terminal.txt* For Vim version 8.2. Last change: 2021 Jan 04
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1330,6 +1330,8 @@ Other commands ~
*:Program* jump to the window with the running program
*:Source* jump to the window with the source code, create it if there
isn't one
*:Asm* jump to the window with the disassembly, create it if there
isn't one
Prompt mode ~
@@ -1352,6 +1354,12 @@ Prompt mode can be used even when the |+terminal| feature is present with: >
The K key is normally mapped to :Evaluate. If you do not want this use: >
let g:termdebug_map_K = 0
<
*termdebug_disasm_window*
If you want the Asm window shown by default, set this to 1. Setting to
any value greater than 1 will set the Asm window height to that value: >
let g:termdebug_disasm_window = 15
<
Communication ~
*termdebug-communication*
+61 -46
View File
@@ -1,4 +1,4 @@
*todo.txt* For Vim version 8.2. Last change: 2021 Jan 02
*todo.txt* For Vim version 8.2. Last change: 2021 Jan 11
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -38,18 +38,29 @@ browser use: https://github.com/vim/vim/issues/1234
*known-bugs*
-------------------- Known bugs and current work -----------------------
Reload: How to make sure type of script function hasn't changed?
Valgrind: test_vim9_cmd: uses uninitialized var
no error for:
echo extend([0], ['a', true])
like it does for:
echo extend([0], ['a'])
At script level this does not give an error:
echo map([0], (_, v) => [])
Or:
var l: list<number> = [0]
echo map(l, (_, v) => [])
Vim9 - Make everything work:
- Expand `=expr` in :next, :argedit, :argadd, :argdelete, :drop
- Expand `=expr` in :vimgrep, :vimgrepadd, :lvimgrep, :lvimgrepadd
- Expand `=expr` in :mkspell
- Unlet with range: "unlet list[a : b]"
- Implement "export {one, two three}".
- Use "null" for v:null, like true and false? #7495
- ISN_CHECKTYPE could use check_argtype()
- Using a script variable inside a :def function doesn't work if the variable
is inside a block, see Test_nested_function(). Should it work?
- give error for variable name:
let p = function('NoSuchFunc')
- Make closures work better:
- Create closure in a loop. Need to make a list of them.
- If a :def function is called with a function reference, compile it to get
the function type.
def Filter(x: string, Cond: func(string): bool)
@@ -63,25 +74,18 @@ Vim9 - Make everything work:
statement
statement
}
- implement { cmd } compiled
- implement { cmd } at script level
- Expand `=expr` in :next, :argedit, :argadd, :argdelete, :drop
- Expand `=expr` in :vimgrep, :vimgrepadd, :lvimgrep, :lvimgrepadd
- Expand `=expr` in :mkspell
- Does this work already: can use func as reference:
def SomeFunc() ...
map(list, SomeFunc)
- For builtin functions using tv_get_string*() use check_for_string() to be
more strict about the argument type.
- Possible memory leaks in test_vim9_func
- Implement :lockvar and :unlockvar. How about local variables? Perhaps only
allow this for global variables. Use :final or :const otherwise.
- Allow function names that will be script-local to start with lower case
letter? Or also require names with s: prefix to use upper case?
Also apply this function references "var ref = SomeFunc"
- Support passing v:none to use the default argument value. (#6504)
- Make map() give an error if the resulting type of the first argument is
wrong. Only works if the type is known? Is this slow (need to go over all
items)?
- Run the same tests in :def and Vim9 script, like in Test_expr7_not()
- Check many more builtin function arguments at compile time.
- make 0 == 'string' fail on the script level, like inside :def.
@@ -105,57 +109,59 @@ Vim9 - Make everything work:
- Implement "as Name" in "import Item as Name from ..."
- Implement using imported items at script level from "import * as X" in
eval_variable(). Should pass the ".xxx" that follows and return that.
- Disallow unlet for local/script/imported vars
- Make "++nr" work. "++g:count" doesn't work, thinks it is a range.
- Make closures work:
- Create closure in a loop. Need to make a list of them.
- nested closure only uses one context, not all (#7150)
- Reload: How to make sure type of script function hasn't changed?
- expandcmd() with `=expr` in filename uses legacy expression.
- eval_expr() in ex_cexpr()
- eval_expr() call in dbg_parsearg() and debuggy_find()
Improve error checking:
- "echo Func()" is an error if Func() does not return anything.
Before launch:
- compile "skip" argument of searchpair()
- compile "expr" and "call" expression of a channel in channel_exe_cmd()?
- give an error for "echo Func()" if Func() does not return anything.
Once Vim9 is stable:
- Change the help to prefer Vim9 syntax where appropriate
- Use Vim9 for runtime files.
PR #7497 for autoload/ccomplete.vim
- Add all the error numbers in a good place in documentation.
- In the generic eval docs, point out the Vim9 syntax where it differs.
Also:
- For range: make table of first ASCII character with flag to quickly check if
it can be a Vim9 command. E.g. "+" can, but "." can't.
Also for Vim9:
- better implementation for partial and tests for that.
- Make "g:imported = Export.exported" work in Vim9 script.
- Make Foo.Bar() work to call the dict function. (#5676)
- Error in any command in "vim9script" aborts sourcing.
- Find a way to test expressions in legacy and Vim9 script without duplication
- Test each level of expressions properly, with type checking
- Test try/catch and throw better, also nested.
Test return inside try/finally jumps to finally and then returns.
Test that return inside try/finally jumps to finally and then returns.
- Test that a function defined inside a :def function is local to that
function, g: functions can be defined and script-local functions cannot be
defined.
- implement :type
- import type declaration?
- compile options that are an expression, e.g. "expr:" in 'spellsuggest',
'foldexpr', 'foldtext', 'printexpr', 'diffexpr', 'patchexpr', 'charconvert',
'balloonexpr', 'includeexpr', 'indentexpr', 'formatexpr'.
Give an error if compilation fails. (#7625)
Use the location where the option was set for deciding whether it's to be
evaluated in Vim9 script context.
- implement :type; import type declaration.
- implement enum; import enum.
- Future work: See |vim9-classes|
- implement enum
- Make accessing varargs faster: arg[expr]
EVAL expr
LOADVARARG (varargs idx)
Define the keywords and commands to make sure it will be backwards
compatible.
- Make debugging work - at least per function. Need to recompile a function
to step through it line-by-line? Evaluate the stack and variables on the
stack?
- Make profiling work - Add ISN_PROFILE instructions after every line?
- List commands when 'verbose' is set or :verbose is used.
Once Vim9 is stable:
- Change the help to prefer Vim9 syntax where appropriate
- Use Vim9 for runtime files.
PR #7497 for autoload/ccomplete.vim
Further improvements:
- compile options that are an expression, e.g. "expr:" in 'spellsuggest',
'foldexpr', 'foldtext', 'printexpr', 'diffexpr', 'patchexpr', 'charconvert',
'balloonexpr', 'includeexpr', 'indentexpr', 'formatexpr'.
Further Vim9 improvements, possibly after launch:
- For range: make table of first ASCII character with flag to quickly check if
it can be a Vim9 command. E.g. "+" can, but "." can't.
- compile get_lambda_tv() in popup_add_timeout()
- inline call to map() and filter()
- compile "skip" argument of searchpair()
- compile "expr" and "call" expression of a channel in channel_exe_cmd()?
- Make accessing varargs faster: arg[expr]
EVAL expr
LOADVARARG (varargs idx)
Popup windows:
- Add a flag to make a popup window focusable?
@@ -308,6 +314,18 @@ Any way to convert "$" back by using a special value? (#6901)
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.
Regexp to search for duplicate lines does not work correctly:
/\(^.*\n\)\1 (Chris Morgan, #6239)
Changing a capturing group to non-capturing changes the result: #7607
:echo matchstr('aaa bbb', '\(.\{-1,}\>\)\|.*')
aaa
:echo matchstr('aaa bbb', '\%(.\{-1,}\>\)\|.*')
aaa bbb
Should also work without any group:
:echo matchstr('aaa bbb', '.\{-1,}\>\|.*')
aaa bbb (should be aaa)
Check out PR #543 (Roland Puntaier).
Patch for multibyte characters in langmap and applying a mapping on them.
(Christian Brabandt, 2015 Jun 12, update July 25)
@@ -393,9 +411,6 @@ corruption. (#6631)
When 'lazyredraw' is set sometimes the title is not updated.
(Jason Franklin, 2020 Feb 3) Looks like a race condition.
Regexp to search for duplicate lines does not work correctly:
/\(^.*\n\)\1 (Chris Morgan, #6239)
With bash ":make" does not set v:shell_error. Possible solution: set
'shellpipe' to "2>&1| tee %s; exit ${PIPESTATUS[0]}" #5994
@@ -1152,7 +1167,7 @@ Overlong utf-8 sequence is displayed wrong. (Harm te Hennepe, 2017 Sep 14,
#2089) Patch with possible solution by Björn Linse.
The change list index is local to a buffer, but it doesn't make sense using it
for another buffer. (lacygolil) Copy w_changelistidx to wininfo_S and back.
for another buffer. (lacygoill) Copy w_changelistidx to wininfo_S and back.
X11: Putting more than about 262040 characters of text on the clipboard and
pasting it in another Vim doesn't work. (Dominique Pelle, 2008 Aug 21-23)
@@ -5474,7 +5489,7 @@ Mappings and Abbreviations:
not the <Space>.
8 Give a warning when using CTRL-C in the lhs of a mapping. It will never
(?) work.
7 Add <0x8f> (hex), <033> (octal) and <123> (decimal) to <> notation?
7 Add <0x8f> (hex), <0o33> (octal) and <123> (decimal) to <> notation?
7 When someone tries to unmap with a trailing space, and it fails, try
unmapping without the trailing space. Helps for ":unmap xx | unmap yy".
6 Context-sensitive abbreviations: Specify syntax group(s) in which the
+1 -1
View File
@@ -50,7 +50,7 @@ which moves to the previous end of a word:
This is a line with example text ~
<----<----x---->------------>
2ge ge e we
2ge ge e 2e
If you are at the last word of a line, the "w" command will take you to the
first word in the next line. Thus you can use this to move through a
+12 -5
View File
@@ -1,4 +1,4 @@
*usr_41.txt* For Vim version 8.2. Last change: 2020 Dec 19
*usr_41.txt* For Vim version 8.2. Last change: 2021 Jan 08
VIM USER MANUAL - by Bram Moolenaar
@@ -122,14 +122,14 @@ starts with a zero. "017" is decimal 15. A binary number starts with "0b" or
decimal number, it will be interpreted as an octal number!
The ":echo" command always prints decimal numbers. Example: >
:echo 0x7f 036
:echo 0x7f 0o36
< 127 30 ~
A number is made negative with a minus sign. This also works for hexadecimal,
octal and binary numbers. A minus sign is also used for subtraction. Compare
this with the previous example: >
:echo 0x7f -036
:echo 0x7f -0o36
< 97 ~
White space in an expression is ignored. However, it's recommended to use it
@@ -137,7 +137,7 @@ for separating items, to make the expression easier to read. For example, to
avoid the confusion with a negative number above, put a space between the
minus sign and the following number: >
:echo 0x7f - 036
:echo 0x7f - 0o36
==============================================================================
*41.2* Variables
@@ -619,6 +619,8 @@ String manipulation: *string-functions*
submatch() get a specific match in ":s" and substitute()
strpart() get part of a string using byte index
strcharpart() get part of a string using char index
slice() take a slice of a string, using char index in
Vim9 script
strgetchar() get character from a string using char index
expand() expand special keywords
expandcmd() expand a command like done for `:edit`
@@ -640,6 +642,7 @@ List manipulation: *list-functions*
insert() insert an item somewhere in a List
add() append an item to a List
extend() append a List to a List
extendnew() make a new List and append items
remove() remove one or more items from a List
copy() make a shallow copy of a List
deepcopy() make a full copy of a List
@@ -647,6 +650,7 @@ List manipulation: *list-functions*
map() change each List item
mapnew() make a new List with changed items
reduce() reduce a List to a value
slice() take a slice of a List
sort() sort a List
reverse() reverse the order of a List
uniq() remove copies of repeated adjacent items
@@ -669,6 +673,7 @@ Dictionary manipulation: *dict-functions*
empty() check if Dictionary is empty
remove() remove an entry from a Dictionary
extend() add entries from one Dictionary to another
extendnew() make a new Dictionary and append items
filter() remove selected entries from a Dictionary
map() change each Dictionary entry
mapnew() make a new Dictionary with changed items
@@ -718,7 +723,8 @@ Other computation: *bitwise-function*
srand() initialize seed used by rand()
Variables: *var-functions*
type() type of a variable
type() type of a variable as a number
typename() type of a variable as text
islocked() check if a variable is locked
funcref() get a Funcref for a function reference
function() get a Funcref for a function name
@@ -817,6 +823,7 @@ System functions and manipulation of files:
setenv() set an environment variable
hostname() name of the system
readfile() read a file into a List of lines
readblob() read a file into a Blob
readdir() get a List of file names in a directory
readdirex() get a List of file information in a directory
writefile() write a List of lines or Blob into a file
+2 -2
View File
@@ -710,12 +710,12 @@ K Run a program to lookup the keyword under the
not more than one line.
[N]gs *gs* *:sl* *:sleep*
:[N]sl[eep] [N] [m] Do nothing for [N] seconds. When [m] is included,
:[N]sl[eep] [N][m] Do nothing for [N] seconds. When [m] is included,
sleep for [N] milliseconds. The count for "gs" always
uses seconds. The default is one second. >
:sleep "sleep for one second
:5sleep "sleep for five seconds
:sleep 100m "sleep for a hundred milliseconds
:sleep 100m "sleep for 100 milliseconds
10gs "sleep for ten seconds
< Can be interrupted with CTRL-C (CTRL-Break on
MS-Windows). "gs" stands for "goto sleep".
+51 -16
View File
@@ -1,4 +1,4 @@
*vim9.txt* For Vim version 8.2. Last change: 2021 Jan 03
*vim9.txt* For Vim version 8.2. Last change: 2021 Jan 10
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -52,8 +52,9 @@ The Vim9 script syntax and semantics are used in:
- a script file where the first command is `vim9script`
- an autocommand defined in the context of the above
When using `:function` in a Vim9 script file the legacy syntax is used.
However, this can be confusing and is therefore discouraged.
When using `:function` in a Vim9 script file the legacy syntax is used, with
the highest |scriptversion|. However, this can be confusing and is therefore
discouraged.
Vim9 script and legacy Vim script can be mixed. There is no requirement to
rewrite old scripts, they keep working as before. You may want to use a few
@@ -70,28 +71,29 @@ Overview ~
Brief summary of the differences you will most often encounter when using Vim9
script and `:def` functions; details are below:
- Comments start with #, not ": >
echo "hello" # comment
echo "hello" # comment
- Using a backslash for line continuation is hardly ever needed: >
echo "hello "
echo "hello "
.. yourName
.. ", how are you?"
- White space is required in many places.
- Assign values without `:let`, declare variables with `:var`: >
var count = 0
var count = 0
count += 3
- Constants can be declared with `:final` and `:const`: >
final matches = [] # add matches
final matches = [] # add matches
const names = ['Betty', 'Peter'] # cannot be changed
- `:final` cannot be used as an abbreviation of `:finally`.
- Variables and functions are script-local by default.
- Functions are declared with argument types and return type: >
def CallMe(count: number, message: string): bool
- Call functions without `:call`: >
writefile(['done'], 'file.txt')
writefile(['done'], 'file.txt')
- You cannot use `:xit`, `:t`, `:append`, `:change`, `:insert` or curly-braces
names.
- A range before a command must be prefixed with a colon: >
:%s/this/that
:%s/this/that
- Unless mentioned specifically, the highest |scriptversion| is used.
Comments starting with # ~
@@ -315,7 +317,7 @@ The constant only applies to the value itself, not what it refers to. >
NAMES[0] = ["Jack"] # Error!
NAMES[0][0] = "Jack" # Error!
NAMES[1] = ["Emma"] # Error!
Names[1][0] = "Emma" # OK, now females[0] == "Emma"
NAMES[1][0] = "Emma" # OK, now females[0] == "Emma"
< *E1092*
Declaring more than one variable at a time, using the unpack notation, is
@@ -432,7 +434,7 @@ possible just before or after the operator. For example: >
.. middle
.. end
var total = start +
end -
end -
correction
var result = positive
? PosFunc(arg)
@@ -629,9 +631,9 @@ one: >
When using "!" for inverting, there is no error for using any type and the
result is a boolean. "!!" can be used to turn any value into boolean: >
!'yes' == false
!'yes' == false
!![] == false
!![1, 2, 3] == true
!![1, 2, 3] == true
When using "`.."` for string concatenation arguments of simple types are
always converted to string: >
@@ -651,6 +653,14 @@ byte indexes. Example: >
echo 'bár'[1]
In legacy script this results in the character 0xc3 (an illegal byte), in Vim9
script this results in the string 'á'.
A negative index is counting from the end, "[-1]" is the last character.
If the index is out of range then an empty string results.
In legacy script "++var" and "--var" would be silently accepted and have no
effect. This is an error in Vim9 script.
Numbers starting with zero are not considered to be octal, only numbers
starting with "0o" are octal: "0o744". |scriptversion-4|
What to watch out for ~
@@ -689,7 +699,7 @@ Vim9 functions are compiled as a whole: >
if !has('feature')
return
endif
use-feature # May give compilation error
use-feature # May give a compilation error
enddef
For a workaround, split it in two functions: >
func Maybe()
@@ -709,6 +719,25 @@ evaluates to false: >
use-feature
endif
enddef
< *vim9-user-command*
Another side effect of compiling a function is that the precense of a user
command is checked at compile time. If the user command is defined later an
error will result. This works: >
command -nargs=1 MyCommand echom <q-args>
def Works()
MyCommand 123
enddef
This will give an error for "MyCommand" not being defined: >
def Works()
command -nargs=1 MyCommand echom <q-args>
MyCommand 123
enddef
A workaround is to invoke the command indirectly with `:execute`: >
def Works()
command -nargs=1 MyCommand echom <q-args>
execute 'MyCommand 123'
enddef
Note that for unrecognized commands there is no check for "|" and a following
command. This will give an error for missing `endif`: >
def Maybe()
@@ -946,6 +975,12 @@ an error, thus breaking backwards compatibility. For example:
- Using a string value when setting a number options.
- Using a number where a string is expected. *E1024*
One consequence is that the item type of a list or dict given to map() must
not change. This will give an error in compiled code: >
map([1, 2, 3], (i, v) => 'item ' .. i)
E1012: Type mismatch; expected list<number> but got list<string>
Instead use |mapnew()|.
==============================================================================
5. Namespace, Import and Export
@@ -1055,14 +1090,14 @@ actually needed. A recommended mechanism:
1. In the plugin define user commands, functions and/or mappings that refer to
an autoload script. >
command -nargs=1 SearchForStuff call searchfor#Stuff(<f-args>)
command -nargs=1 SearchForStuff call searchfor#Stuff(<f-args>)
< This goes in .../plugin/anyname.vim. "anyname.vim" can be freely chosen.
2. In the autoload script do the actual work. You can import items from
other files to split up functionality in appropriate pieces. >
vim9script
import FilterFunc from "../import/someother.vim"
import FilterFunc from "../import/someother.vim"
def searchfor#Stuff(arg: string)
var filtered = FilterFunc(arg)
...
+6 -1
View File
@@ -1174,7 +1174,9 @@ au BufNewFile,BufRead *.papp,*.pxml,*.pxsl setf papp
au BufNewFile,BufRead */etc/passwd,*/etc/passwd-,*/etc/passwd.edit,*/etc/shadow,*/etc/shadow-,*/etc/shadow.edit,*/var/backups/passwd.bak,*/var/backups/shadow.bak setf passwd
" Pascal (also *.p)
au BufNewFile,BufRead *.pas,*.pp setf pascal
au BufNewFile,BufRead *.pas setf pascal
au BufNewFile,BufRead *.pp call dist#ft#FTpp()
" Delphi or Lazarus program file
au BufNewFile,BufRead *.dpr,*.lpr setf pascal
@@ -1616,6 +1618,9 @@ au BufNewFile,BufRead *.mib,*.my setf mib
au BufNewFile,BufRead *.hog,snort.conf,vision.conf setf hog
au BufNewFile,BufRead *.rules call dist#ft#FTRules()
" SPARQL queries
au BufNewFile,BufRead *.rq,*.sparql setf sparql
" Spec (Linux RPM)
au BufNewFile,BufRead *.spec setf spec
+55 -59
View File
@@ -1,87 +1,83 @@
" Vim ftplugin file
" Language: Erlang
" Language: Erlang (http://www.erlang.org)
" Maintainer: Csaba Hoch <csaba.hoch@gmail.com>
" Author: Oscar Hellström <oscar@oscarh.net>
" Contributors: Ricardo Catalinas Jiménez <jimenezrick@gmail.com>
" Eduardo Lopez (http://github.com/tapichu)
" Arvid Bjurklint (http://github.com/slarwise)
" Last Update: 2021-Jan-08
" License: Vim license
" Version: 2012/01/25
" URL: https://github.com/vim-erlang/vim-erlang-runtime
if exists('b:did_ftplugin')
finish
else
let b:did_ftplugin = 1
endif
if exists('s:did_function_definitions')
call s:SetErlangOptions()
finish
else
let s:did_function_definitions = 1
finish
endif
let b:did_ftplugin = 1
let s:cpo_save = &cpo
set cpo&vim
if !exists('g:erlang_keywordprg')
let g:erlang_keywordprg = 'erl -man'
let &l:keywordprg = get(g:, 'erlang_keywordprg', 'erl -man')
if get(g:, 'erlang_folding', 0)
setlocal foldmethod=expr
setlocal foldexpr=GetErlangFold(v:lnum)
setlocal foldtext=ErlangFoldText()
endif
if !exists('g:erlang_folding')
let g:erlang_folding = 0
endif
setlocal comments=:%%%,:%%,:%
setlocal commentstring=%%s
setlocal formatoptions+=ro
setlocal suffixesadd=.erl,.hrl
let &l:include = '^\s*-\%(include\|include_lib\)\s*("\zs\f*\ze")'
let &l:define = '^\s*-\%(define\|record\|type\|opaque\)'
let s:erlang_fun_begin = '^\a\w*(.*$'
let s:erlang_fun_end = '^[^%]*\.\s*\(%.*\)\?$'
function s:SetErlangOptions()
if g:erlang_folding
setlocal foldmethod=expr
setlocal foldexpr=GetErlangFold(v:lnum)
setlocal foldtext=ErlangFoldText()
endif
if !exists('*GetErlangFold')
function GetErlangFold(lnum)
let lnum = a:lnum
let line = getline(lnum)
setlocal comments=:%%%,:%%,:%
setlocal commentstring=%%s
if line =~ s:erlang_fun_end
return '<1'
endif
setlocal formatoptions+=ro
let &l:keywordprg = g:erlang_keywordprg
endfunction
if line =~ s:erlang_fun_begin && foldlevel(lnum - 1) == 1
return '1'
endif
function GetErlangFold(lnum)
let lnum = a:lnum
let line = getline(lnum)
if line =~ s:erlang_fun_begin
return '>1'
endif
if line =~ s:erlang_fun_end
return '<1'
endif
return '='
endfunction
endif
if line =~ s:erlang_fun_begin && foldlevel(lnum - 1) == 1
return '1'
endif
if !exists('*ErlangFoldText')
function ErlangFoldText()
let line = getline(v:foldstart)
let foldlen = v:foldend - v:foldstart + 1
let lines = ' ' . foldlen . ' lines: ' . substitute(line, "[\ \t]*", '', '')
if foldlen < 10
let lines = ' ' . lines
endif
let retval = '+' . v:folddashes . lines
if line =~ s:erlang_fun_begin
return '>1'
endif
return retval
endfunction
endif
return '='
endfunction
function ErlangFoldText()
let line = getline(v:foldstart)
let foldlen = v:foldend - v:foldstart + 1
let lines = ' ' . foldlen . ' lines: ' . substitute(line, "[\ \t]*", '', '')
if foldlen < 10
let lines = ' ' . lines
endif
let retval = '+' . v:folddashes . lines
return retval
endfunction
call s:SetErlangOptions()
let b:undo_ftplugin = "setlocal foldmethod< foldexpr< foldtext<"
\ . " comments< commentstring< formatoptions<"
let b:undo_ftplugin = "setlocal keywordprg< foldmethod< foldexpr< foldtext<"
\ . " comments< commentstring< formatoptions< suffixesadd< include<"
\ . " define<"
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: sw=2 et
+2 -2
View File
@@ -2,7 +2,7 @@
" Language: fstab file
" Maintainer: Radu Dineiu <radu.dineiu@gmail.com>
" URL: https://raw.github.com/rid9/vim-fstab/master/ftplugin/fstab.vim
" Last Change: 2020 Dec 29
" Last Change: 2021 Jan 02
" Version: 1.0
"
" Credits:
@@ -16,4 +16,4 @@ let b:did_ftplugin = 1
setlocal commentstring=#%s
let b:undo_ftplugin = "setlocal commentstring<"
" vim: ts=8 ft=vim
" vim: ts=8 ft=vim
+10 -1
View File
@@ -6,7 +6,16 @@
" See https://swift.org/LICENSE.txt for license information
" See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
"
" Vim maintainer: Emir SARI <bitigchi@me.com>
" Vim maintainer: Emir SARI <bitigchi@me.com>
" Last Change: 2021 Jan 08
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1
let b:undo_ftplugin = "setlocal comments< expandtab< tabstop< shiftwidth< smartindent<"
setlocal comments=s1:/*,mb:*,ex:*/,:///,://
setlocal expandtab
+12 -7
View File
@@ -1,7 +1,7 @@
" Vim filetype plugin
" Language: Vim
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2020 Aug 14
" Last Change: 2021 Jan 05
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -48,18 +48,23 @@ setlocal isk+=#
" Use :help to lookup the keyword under the cursor with K.
setlocal keywordprg=:help
" Set 'comments' to format dashed lists in comments
" Avoid that #{} starts a comment.
setlocal com=sO:\"\ -,mO:\"\ \ ,sO:#\ -,mO:#\ \ ,eO:##,:\",b:#
if "\n" .. getline(1, 10)->join("\n") =~# '\n\s*vim9\%[script]\>'
" Set 'comments' to format dashed lists in comments
setlocal com=sO:#\ -,mO:#\ \ ,eO:##,:#
" Comments start with a double quote in a legacy script;
" with # in a Vim9 script
setlocal commentstring=\"%s
else
setlocal com=sO:\"\ -,mO:\"\ \ ,:\"
setlocal commentstring=#%s
endif
" Format comments to be up to 78 characters long
if &tw == 0
setlocal tw=78
endif
" Comments start with a double quote; in Vim9 script # would also work
setlocal commentstring=\"%s
if !exists("no_plugin_maps") && !exists("no_vim_maps")
let b:did_add_maps = 1
+1 -1
View File
@@ -227,4 +227,4 @@ endfunction
let &cpo = s:cpo_save
unlet s:cpo_save
" vim:sw=2
" vim:sw=2
+19
View File
@@ -21,8 +21,27 @@ let cmd =
" END_INDENT
" START_INDENT
" INDENT_EXE let g:vim_indent_cont = 5
let list = [
\ 'one',
\ 'two']
" END_INDENT
" START_INDENT
" INDENT_EXE unlet g:vim_indent_cont
let list = [
'one',
'two',
]
echo
" END_INDENT
" START_INDENT
" INDENT_AT this-line
func Some()
let f = x " this-line
+19
View File
@@ -21,8 +21,27 @@ let cmd =
" END_INDENT
" START_INDENT
" INDENT_EXE let g:vim_indent_cont = 5
let list = [
\ 'one',
\ 'two']
" END_INDENT
" START_INDENT
" INDENT_EXE unlet g:vim_indent_cont
let list = [
'one',
'two',
]
echo
" END_INDENT
" START_INDENT
" INDENT_AT this-line
func Some()
let f = x " this-line
+44 -2
View File
@@ -1,7 +1,7 @@
" Vim indent file
" Language: Vim script
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2020 Sep 27
" Last Change: 2021 Jan 06
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
@@ -52,6 +52,7 @@ function GetVimIndentIntern()
return 0
endif
let prev_text = getline(lnum)
let found_cont = 0
" Add a 'shiftwidth' after :if, :while, :try, :catch, :finally, :function
" and :else. Add it three times for a line that starts with '\' or '"\ '
@@ -83,6 +84,7 @@ function GetVimIndentIntern()
endif
if cur_text =~ s:lineContPat && v:lnum > 1 && prev_text !~ s:lineContPat
let found_cont = 1
if exists("g:vim_indent_cont")
let ind = ind + g:vim_indent_cont
else
@@ -114,10 +116,50 @@ function GetVimIndentIntern()
endif
endif
" For a line starting with "}" find the matching "{". If it is at the start
" of the line align with it, probably end of a block.
" Use the mapped "%" from matchit to find the match, otherwise we may match
" a { inside a comment or string.
if cur_text =~ '^\s*}'
if maparg('%') != ''
exe v:lnum
silent! normal %
if line('.') < v:lnum && getline('.') =~ '^\s*{'
let ind = indent('.')
endif
else
" todo: use searchpair() to find a match
endif
endif
" Below a line starting with "}" find the matching "{". If it is at the
" end of the line we must be below the end of a dictionary.
if prev_text =~ '^\s*}'
if maparg('%') != ''
exe lnum
silent! normal %
if line('.') == lnum || getline('.') !~ '^\s*{'
let ind = ind - shiftwidth()
endif
else
" todo: use searchpair() to find a match
endif
endif
" Below a line starting with "]" we must be below the end of a list.
if prev_text =~ '^\s*]'
let ind = ind - shiftwidth()
endif
" A line ending in "{"/"[} is most likely the start of a dict/list literal,
" indent the next line more. Not for a continuation line.
if prev_text =~ '[{[]\s*$' && !found_cont
let ind = ind + shiftwidth()
endif
" Subtract a 'shiftwidth' on a :endif, :endwhile, :catch, :finally, :endtry,
" :endfun, :enddef, :else and :augroup END.
if cur_text =~ '^\s*\(ene\@!\|}\|cat\|finall\|el\|aug\%[roup]\s\+[eE][nN][dD]\)'
if cur_text =~ '^\s*\(ene\@!\|cat\|finall\|el\|aug\%[roup]\s\+[eE][nN][dD]\)'
let ind = ind - shiftwidth()
endif
+1 -1
View File
@@ -1,3 +1,3 @@
" Menu Translations: Turkish
source <sfile>:p:h/menu_tr_tr.cp1254.vim
source <sfile>:p:h/menu_tr_tr.cp1254.vim
+1 -1
View File
@@ -1,3 +1,3 @@
" Menu Translations: Turkish
source <sfile>:p:h/menu_tr_tr.iso_8859-9.vim
source <sfile>:p:h/menu_tr_tr.iso_8859-9.vim
+159 -3
View File
@@ -2,7 +2,7 @@
"
" Author: Bram Moolenaar
" Copyright: Vim license applies, see ":help license"
" Last Change: 2020 Dec 07
" Last Change: 2021 Jan 03
"
" WORK IN PROGRESS - Only the basics work
" Note: On MS-Windows you need a recent version of gdb. The one included with
@@ -70,9 +70,14 @@ if !exists('g:termdebugger')
endif
let s:pc_id = 12
let s:break_id = 13 " breakpoint number is added to this
let s:asm_id = 13
let s:break_id = 14 " breakpoint number is added to this
let s:stopped = 1
let s:parsing_disasm_msg = 0
let s:asm_lines = []
let s:asm_addr = ''
" Take a breakpoint number as used by GDB and turn it into an integer.
" The breakpoint may contain a dot: 123.4 -> 123004
" The main breakpoint has a zero subid.
@@ -114,6 +119,7 @@ func s:StartDebug_internal(dict)
let s:ptywin = 0
let s:pid = 0
let s:asmwin = 0
" Uncomment this line to write logging in "debuglog".
" call ch_logfile('debuglog', 'w')
@@ -153,6 +159,14 @@ func s:StartDebug_internal(dict)
else
call s:StartDebug_term(a:dict)
endif
if exists('g:termdebug_disasm_window')
if g:termdebug_disasm_window
let curwinid = win_getid(winnr())
call s:GotoAsmwinOrCreateIt()
call win_gotoid(curwinid)
endif
endif
endfunc
" Use when debugger didn't start or ended.
@@ -546,6 +560,14 @@ func s:GetFullname(msg)
return name
endfunc
" Extract the "addr" value from a gdb message with addr="0x0001234".
func s:GetAsmAddr(msg)
if a:msg !~ 'addr='
return ''
endif
let addr = s:DecodeMessage(substitute(a:msg, '.*addr=', '', ''))
return addr
endfunc
func s:EndTermDebug(job, status)
exe 'bwipe! ' . s:commbuf
unlet s:gdbwin
@@ -609,6 +631,69 @@ func s:EndPromptDebug(job, status)
call ch_log("Returning from EndPromptDebug()")
endfunc
" Disassembly window - added by Michael Sartain
"
" - CommOutput: disassemble $pc
" - CommOutput: &"disassemble $pc\n"
" - CommOutput: ~"Dump of assembler code for function main(int, char**):\n"
" - CommOutput: ~" 0x0000555556466f69 <+0>:\tpush rbp\n"
" ...
" - CommOutput: ~" 0x0000555556467cd0:\tpop rbp\n"
" - CommOutput: ~" 0x0000555556467cd1:\tret \n"
" - CommOutput: ~"End of assembler dump.\n"
" - CommOutput: ^done
" - CommOutput: disassemble $pc
" - CommOutput: &"disassemble $pc\n"
" - CommOutput: &"No function contains specified address.\n"
" - CommOutput: ^error,msg="No function contains specified address."
func s:HandleDisasmMsg(msg)
if a:msg =~ '^\^done'
let curwinid = win_getid(winnr())
if win_gotoid(s:asmwin)
silent normal! gg0"_dG
call setline(1, s:asm_lines)
set nomodified
set filetype=asm
let lnum = search('^' . s:asm_addr)
if lnum != 0
exe 'sign unplace ' . s:asm_id
exe 'sign place ' . s:asm_id . ' line=' . lnum . ' name=debugPC'
endif
call win_gotoid(curwinid)
endif
let s:parsing_disasm_msg = 0
let s:asm_lines = []
elseif a:msg =~ '^\^error,msg='
if s:parsing_disasm_msg == 1
" Disassemble call ran into an error. This can happen when gdb can't
" find the function frame address, so let's try to disassemble starting
" at current PC
call s:SendCommand('disassemble $pc,+100')
endif
let s:parsing_disasm_msg = 0
elseif a:msg =~ '\&\"disassemble \$pc'
if a:msg =~ '+100'
" This is our second disasm attempt
let s:parsing_disasm_msg = 2
endif
else
let value = substitute(a:msg, '^\~\"[ ]*', '', '')
let value = substitute(value, '^=>[ ]*', '', '')
let value = substitute(value, '\\n\" $', '', '')
let value = substitute(value, '\\n\"$', '', '')
let value = substitute(value, ' ', '', '')
let value = substitute(value, '\\t', ' ', 'g')
if value != '' || !empty(s:asm_lines)
call add(s:asm_lines, value)
endif
endif
endfunc
" Handle a message received from gdb on the GDB/MI interface.
func s:CommOutput(chan, msg)
let msgs = split(a:msg, "\r")
@@ -618,7 +703,10 @@ func s:CommOutput(chan, msg)
if msg[0] == "\n"
let msg = msg[1:]
endif
if msg != ''
if s:parsing_disasm_msg
call s:HandleDisasmMsg(msg)
elseif msg != ''
if msg =~ '^\(\*stopped\|\*running\|=thread-selected\)'
call s:HandleCursor(msg)
elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,'
@@ -631,6 +719,9 @@ func s:CommOutput(chan, msg)
call s:HandleEvaluate(msg)
elseif msg =~ '^\^error,msg='
call s:HandleError(msg)
elseif msg =~ '^disassemble'
let s:parsing_disasm_msg = 1
let s:asm_lines = []
endif
endif
endfor
@@ -671,6 +762,7 @@ func s:InstallCommands()
command Gdb call win_gotoid(s:gdbwin)
command Program call s:GotoProgram()
command Source call s:GotoSourcewinOrCreateIt()
command Asm call s:GotoAsmwinOrCreateIt()
command Winbar call s:InstallWinbar()
if !exists('g:termdebug_map_K') || g:termdebug_map_K
@@ -724,6 +816,7 @@ func s:DeleteCommands()
delcommand Gdb
delcommand Program
delcommand Source
delcommand Asm
delcommand Winbar
if exists('s:k_map_saved')
@@ -923,6 +1016,48 @@ func s:GotoSourcewinOrCreateIt()
endif
endfunc
func s:GotoAsmwinOrCreateIt()
if !win_gotoid(s:asmwin)
if win_gotoid(s:sourcewin)
exe 'rightbelow new'
else
exe 'new'
endif
let s:asmwin = win_getid(winnr())
setlocal nowrap
setlocal number
setlocal noswapfile
setlocal buftype=nofile
let asmbuf = bufnr('Termdebug-asm-listing')
if asmbuf > 0
exe 'buffer' . asmbuf
else
exe 'file Termdebug-asm-listing'
endif
if exists('g:termdebug_disasm_window')
if g:termdebug_disasm_window > 1
exe 'resize ' . g:termdebug_disasm_window
endif
endif
endif
if s:asm_addr != ''
let lnum = search('^' . s:asm_addr)
if lnum == 0
if s:stopped
call s:SendCommand('disassemble $pc')
endif
else
exe 'sign unplace ' . s:asm_id
exe 'sign place ' . s:asm_id . ' line=' . lnum . ' name=debugPC'
endif
endif
endfunc
" Handle stopping and running message from gdb.
" Will update the sign that shows the current position.
func s:HandleCursor(msg)
@@ -941,6 +1076,27 @@ func s:HandleCursor(msg)
else
let fname = ''
endif
if a:msg =~ 'addr='
let asm_addr = s:GetAsmAddr(a:msg)
if asm_addr != ''
let s:asm_addr = asm_addr
let curwinid = win_getid(winnr())
if win_gotoid(s:asmwin)
let lnum = search('^' . s:asm_addr)
if lnum == 0
call s:SendCommand('disassemble $pc')
else
exe 'sign unplace ' . s:asm_id
exe 'sign place ' . s:asm_id . ' line=' . lnum . ' name=debugPC'
endif
call win_gotoid(curwinid)
endif
endif
endif
if a:msg =~ '^\(\*stopped\|=thread-selected\)' && filereadable(fname)
let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
if lnum =~ '^[0-9]*$'
+4
View File
@@ -182,6 +182,10 @@ if s:line1 =~# "^#!"
elseif s:name =~# 'clojure'
set ft=clojure
" Free Pascal
elseif s:name =~# 'instantfpc\>'
set ft=pascal
endif
unlet s:name
+2 -2
View File
@@ -1,7 +1,7 @@
" Vim ABAP syntax file
" Language: SAP - ABAP/R4
" Maintainer: Marius Piedallu van Wyk <lailoken@gmail.com>
" Last Change: 2018 Dec 12
" Last Change: 2021 Jan 02
" Comment: Thanks to EPI-USE Labs for all your assistance. :)
" Quit when a syntax file was already loaded
@@ -193,4 +193,4 @@ hi def link abapHex Number
let b:current_syntax = "abap"
" vim: ts=8 sw=2
" vim: ts=8 sw=2
+5 -5
View File
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: PROLOG
" Maintainer: Anton Kochkov <anton.kochkov@gmail.com>
" Last Change: 2019 Aug 29
" Last Change: 2021 Jan 05
" There are two sets of highlighting in here:
" If the "prolog_highlighting_clean" variable exists, it is rather sparse.
@@ -21,16 +21,16 @@ syn case match
" Very simple highlighting for comments, clause heads and
" character codes. It respects prolog strings and atoms.
syn region prologCComment start=+/\*+ end=+\*/+
syn match prologComment +%.*+
syn region prologCComment start=+/\*+ end=+\*/+ contains=@Spell
syn match prologComment +%.*+ contains=@Spell
if !exists("prolog_highlighting_no_keyword")
syn keyword prologKeyword module meta_predicate multifile dynamic
endif
syn match prologCharCode +0'\\\=.+
syn region prologString start=+"+ skip=+\\\\\|\\"+ end=+"+
syn region prologString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@Spell
syn region prologAtom start=+'+ skip=+\\\\\|\\'+ end=+'+
syn region prologClause matchgroup=prologClauseHead start=+^\s*[a-z]\w*+ matchgroup=Normal end=+\.\s\|\.$+ contains=ALLBUT,prologClause
syn region prologClause matchgroup=prologClauseHead start=+^\s*[a-z]\w*+ matchgroup=Normal end=+\.\s\|\.$+ contains=ALLBUT,prologClause contains=@NoSpell
if !exists("prolog_highlighting_clean")
+4
View File
@@ -9791,6 +9791,8 @@ $as_echo_n "checking for GTK - version >= $min_gtk_version... " >&6; }
sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
}
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK -dev package" >&5
$as_echo_n "checking for GTK -dev package... " >&6; }
no_gtk=yes
fi
@@ -10044,6 +10046,8 @@ $as_echo_n "checking for GTK - version >= $min_gtk_version... " >&6; }
sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
}
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK -dev package" >&5
$as_echo_n "checking for GTK -dev package... " >&6; }
no_gtk=yes
fi
+12 -9
View File
@@ -492,8 +492,10 @@ can_unload_buffer(buf_T *buf)
* supposed to close the window but autocommands close all other windows.
*
* When "ignore_abort" is TRUE don't abort even when aborting() returns TRUE.
*
* Return TRUE when we got to the end and b_nwindows was decremented.
*/
void
int
close_buffer(
win_T *win, // if not NULL, set b_last_cursor
buf_T *buf,
@@ -540,7 +542,7 @@ close_buffer(
if (wipe_buf || unload_buf)
{
if (!can_unload_buffer(buf))
return;
return FALSE;
// Wiping out or unloading a terminal buffer kills the job.
free_terminal(buf);
@@ -571,7 +573,7 @@ close_buffer(
// Disallow deleting the buffer when it is locked (already being closed or
// halfway a command that relies on it). Unloading is allowed.
if ((del_buf || wipe_buf) && !can_unload_buffer(buf))
return;
return FALSE;
// check no autocommands closed the window
if (win != NULL && win_valid_any_tab(win))
@@ -600,7 +602,7 @@ close_buffer(
// Autocommands deleted the buffer.
aucmd_abort:
emsg(_(e_auabort));
return;
return FALSE;
}
--buf->b_locked;
if (abort_if_last && one_window())
@@ -625,7 +627,7 @@ aucmd_abort:
#ifdef FEAT_EVAL
// autocmds may abort script processing
if (!ignore_abort && aborting())
return;
return FALSE;
#endif
}
@@ -653,7 +655,7 @@ aucmd_abort:
// Return when a window is displaying the buffer or when it's not
// unloaded.
if (buf->b_nwindows > 0 || !unload_buf)
return;
return FALSE;
// Always remove the buffer when there is no file name.
if (buf->b_ffname == NULL)
@@ -683,11 +685,11 @@ aucmd_abort:
// Autocommands may have deleted the buffer.
if (!bufref_valid(&bufref))
return;
return FALSE;
#ifdef FEAT_EVAL
// autocmds may abort script processing
if (!ignore_abort && aborting())
return;
return FALSE;
#endif
/*
@@ -698,7 +700,7 @@ aucmd_abort:
* deleted buffer.
*/
if (buf == curbuf && !is_curbuf)
return;
return FALSE;
if (win_valid_any_tab(win) && win->w_buffer == buf)
win->w_buffer = NULL; // make sure we don't use the buffer now
@@ -759,6 +761,7 @@ aucmd_abort:
buf->b_p_bl = FALSE;
}
// NOTE: at this point "curbuf" may be invalid!
return TRUE;
}
/*
+3
View File
@@ -2768,6 +2768,9 @@ AC_DEFUN(AM_PATH_GTK,
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
}
else
dnl Put some text before the "no" to hint at installing the gtk-dev
dnl packages.
AC_MSG_CHECKING(for GTK -dev package)
no_gtk=yes
fi
+97 -46
View File
@@ -466,6 +466,45 @@ skip_expr_concatenate(
return res;
}
/*
* Convert "tv" to a string.
* When "convert" is TRUE convert a List into a sequence of lines and convert
* a Float to a String.
* Returns an allocated string (NULL when out of memory).
*/
char_u *
typval2string(typval_T *tv, int convert)
{
garray_T ga;
char_u *retval;
#ifdef FEAT_FLOAT
char_u numbuf[NUMBUFLEN];
#endif
if (convert && tv->v_type == VAR_LIST)
{
ga_init2(&ga, (int)sizeof(char), 80);
if (tv->vval.v_list != NULL)
{
list_join(&ga, tv->vval.v_list, (char_u *)"\n", TRUE, FALSE, 0);
if (tv->vval.v_list->lv_len > 0)
ga_append(&ga, NL);
}
ga_append(&ga, NUL);
retval = (char_u *)ga.ga_data;
}
#ifdef FEAT_FLOAT
else if (convert && tv->v_type == VAR_FLOAT)
{
vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
retval = vim_strsave(numbuf);
}
#endif
else
retval = vim_strsave(tv_get_string(tv));
return retval;
}
/*
* Top level evaluation function, returning a string. Does not handle line
* breaks.
@@ -481,10 +520,6 @@ eval_to_string_eap(
{
typval_T tv;
char_u *retval;
garray_T ga;
#ifdef FEAT_FLOAT
char_u numbuf[NUMBUFLEN];
#endif
evalarg_T evalarg;
fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip);
@@ -492,27 +527,7 @@ eval_to_string_eap(
retval = NULL;
else
{
if (convert && tv.v_type == VAR_LIST)
{
ga_init2(&ga, (int)sizeof(char), 80);
if (tv.vval.v_list != NULL)
{
list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, FALSE, 0);
if (tv.vval.v_list->lv_len > 0)
ga_append(&ga, NL);
}
ga_append(&ga, NUL);
retval = (char_u *)ga.ga_data;
}
#ifdef FEAT_FLOAT
else if (convert && tv.v_type == VAR_FLOAT)
{
vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float);
retval = vim_strsave(numbuf);
}
#endif
else
retval = vim_strsave(tv_get_string(&tv));
retval = typval2string(&tv, convert);
clear_tv(&tv);
}
clear_evalarg(&evalarg, NULL);
@@ -3877,8 +3892,9 @@ eval_index(
if (evaluate)
{
int res = eval_index_inner(rettv, range,
empty1 ? NULL : &var1, empty2 ? NULL : &var2,
empty1 ? NULL : &var1, empty2 ? NULL : &var2, FALSE,
key, keylen, verbose);
if (!empty1)
clear_tv(&var1);
if (range)
@@ -3937,10 +3953,27 @@ check_can_index(typval_T *rettv, int evaluate, int verbose)
return OK;
}
/*
* slice() function
*/
void
f_slice(typval_T *argvars, typval_T *rettv)
{
if (check_can_index(argvars, TRUE, FALSE) == OK)
{
copy_tv(argvars, rettv);
eval_index_inner(rettv, TRUE, argvars + 1,
argvars[2].v_type == VAR_UNKNOWN ? NULL : argvars + 2,
TRUE, NULL, 0, FALSE);
}
}
/*
* Apply index or range to "rettv".
* "var1" is the first index, NULL for [:expr].
* "var2" is the second index, NULL for [expr] and [expr: ]
* "exclusive" is TRUE for slice(): second index is exclusive, use character
* index for string.
* Alternatively, "key" is not NULL, then key[keylen] is the dict index.
*/
int
@@ -3949,12 +3982,13 @@ eval_index_inner(
int is_range,
typval_T *var1,
typval_T *var2,
int exclusive,
char_u *key,
int keylen,
int verbose)
{
long n1, n2 = 0;
long len;
varnumber_T n1, n2 = 0;
long len;
n1 = 0;
if (var1 != NULL && rettv->v_type != VAR_DICT)
@@ -3968,10 +4002,10 @@ eval_index_inner(
emsg(_(e_cannot_slice_dictionary));
return FAIL;
}
if (var2 == NULL)
n2 = -1;
else
if (var2 != NULL)
n2 = tv_get_number(var2);
else
n2 = VARNUM_MAX;
}
switch (rettv->v_type)
@@ -3994,10 +4028,10 @@ eval_index_inner(
char_u *s = tv_get_string(rettv);
len = (long)STRLEN(s);
if (in_vim9script())
if (in_vim9script() || exclusive)
{
if (is_range)
s = string_slice(s, n1, n2);
s = string_slice(s, n1, n2, exclusive);
else
s = char_from_string(s, n1);
}
@@ -4015,6 +4049,8 @@ eval_index_inner(
n2 = len + n2;
else if (n2 >= len)
n2 = len;
if (exclusive)
--n2;
if (n1 >= len || n2 < 0 || n1 > n2)
s = NULL;
else
@@ -4051,7 +4087,9 @@ eval_index_inner(
if (n2 < 0)
n2 = len + n2;
else if (n2 >= len)
n2 = len - 1;
n2 = len - (exclusive ? 0 : 1);
if (exclusive)
--n2;
if (n1 >= len || n2 < 0 || n1 > n2)
{
clear_tv(rettv);
@@ -4103,9 +4141,9 @@ eval_index_inner(
if (var1 == NULL)
n1 = 0;
if (var2 == NULL)
n2 = -1;
n2 = VARNUM_MAX;
if (list_slice_or_index(rettv->vval.v_list,
is_range, n1, n2, rettv, verbose) == FAIL)
is_range, n1, n2, exclusive, rettv, verbose) == FAIL)
return FAIL;
break;
@@ -5056,12 +5094,14 @@ string2float(
/*
* Convert the specified byte index of line 'lnum' in buffer 'buf' to a
* character index. Works only for loaded buffers. Returns -1 on failure.
* The index of the first character is one.
* The index of the first byte and the first character is zero.
*/
int
buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx)
{
char_u *str;
char_u *t;
int count;
if (buf == NULL || buf->b_ml.ml_mfp == NULL)
return -1;
@@ -5074,15 +5114,26 @@ buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx)
return -1;
if (*str == NUL)
return 1;
return 0;
return mb_charlen_len(str, byteidx + 1);
// count the number of characters
t = str;
for (count = 0; *t != NUL && t <= str + byteidx; count++)
t += mb_ptr2len(t);
// In insert mode, when the cursor is at the end of a non-empty line,
// byteidx points to the NUL character immediately past the end of the
// string. In this case, add one to the character count.
if (*t == NUL && byteidx != 0 && t == str + byteidx)
count++;
return count - 1;
}
/*
* Convert the specified character index of line 'lnum' in buffer 'buf' to a
* byte index. Works only for loaded buffers. Returns -1 on failure. The index
* of the first byte and the first character is one.
* byte index. Works only for loaded buffers. Returns -1 on failure.
* The index of the first byte and the first character is zero.
*/
int
buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx)
@@ -5105,7 +5156,7 @@ buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx)
while (*t != NUL && --charidx > 0)
t += mb_ptr2len(t);
return t - str + 1;
return t - str;
}
/*
@@ -5180,7 +5231,7 @@ var2fpos(
{
pos = curwin->w_cursor;
if (charcol)
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col);
return &pos;
}
if (name[0] == 'v' && name[1] == NUL) // Visual start
@@ -5190,7 +5241,7 @@ var2fpos(
else
pos = curwin->w_cursor;
if (charcol)
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col);
return &pos;
}
if (name[0] == '\'') // mark
@@ -5199,7 +5250,7 @@ var2fpos(
if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
return NULL;
if (charcol)
pp->col = buf_byteidx_to_charidx(curbuf, pp->lnum, pp->col) - 1;
pp->col = buf_byteidx_to_charidx(curbuf, pp->lnum, pp->col);
return pp;
}
@@ -5300,7 +5351,7 @@ list2fpos(
if (buf == NULL || buf->b_ml.ml_mfp == NULL)
return FAIL;
n = buf_charidx_to_byteidx(buf, posp->lnum, n);
n = buf_charidx_to_byteidx(buf, posp->lnum, n) + 1;
}
posp->col = n;
+70 -12
View File
@@ -275,6 +275,7 @@ typedef struct {
int arg_count; // actual argument count
type_T **arg_types; // list of argument types
int arg_idx; // current argument index (first arg is zero)
cctx_T *arg_cctx;
} argcontext_T;
// A function to check one argument type. The first argument is the type to
@@ -282,6 +283,22 @@ typedef struct {
// E.g. if "arg_idx" is 1, then (type - 1) is the first argument type.
typedef int (*argcheck_T)(type_T *, argcontext_T *);
/*
* Call need_type() to check an argument type.
*/
static int
check_arg_type(
type_T *expected,
type_T *actual,
argcontext_T *context)
{
// TODO: would be useful to know if "actual" is a constant and pass it to
// need_type() to get a compile time error if possible.
return need_type(actual, expected,
context->arg_idx - context->arg_count, context->arg_idx + 1,
context->arg_cctx, FALSE, FALSE);
}
/*
* Check "type" is a float or a number.
*/
@@ -301,7 +318,7 @@ arg_float_or_nr(type_T *type, argcontext_T *context)
static int
arg_number(type_T *type, argcontext_T *context)
{
return check_arg_type(&t_number, type, context->arg_idx + 1);
return check_arg_type(&t_number, type, context);
}
/*
@@ -310,7 +327,7 @@ arg_number(type_T *type, argcontext_T *context)
static int
arg_string(type_T *type, argcontext_T *context)
{
return check_arg_type(&t_string, type, context->arg_idx + 1);
return check_arg_type(&t_string, type, context);
}
/*
@@ -340,7 +357,7 @@ arg_list_or_dict(type_T *type, argcontext_T *context)
}
/*
* Check "type" is the same type as the previous argument
* Check "type" is the same type as the previous argument.
* Must not be used for the first argcheck_T entry.
*/
static int
@@ -348,7 +365,22 @@ arg_same_as_prev(type_T *type, argcontext_T *context)
{
type_T *prev_type = context->arg_types[context->arg_idx - 1];
return check_arg_type(prev_type, type, context->arg_idx + 1);
return check_arg_type(prev_type, type, context);
}
/*
* Check "type" is the same basic type as the previous argument, checks list or
* dict vs other type, but not member type.
* Must not be used for the first argcheck_T entry.
*/
static int
arg_same_struct_as_prev(type_T *type, argcontext_T *context)
{
type_T *prev_type = context->arg_types[context->arg_idx - 1];
if (prev_type->tt_type != context->arg_types[context->arg_idx]->tt_type)
return check_arg_type(prev_type, type, context);
return OK;
}
/*
@@ -369,7 +401,7 @@ arg_item_of_prev(type_T *type, argcontext_T *context)
// probably VAR_ANY, can't check
return OK;
return check_arg_type(expected, type, context->arg_idx + 1);
return check_arg_type(expected, type, context);
}
/*
@@ -394,6 +426,7 @@ arg_extend3(type_T *type, argcontext_T *context)
argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev};
argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3};
argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number};
/*
@@ -456,6 +489,13 @@ ret_dict_any(int argcount UNUSED, type_T **argtypes UNUSED)
return &t_dict_any;
}
static type_T *
ret_job_info(int argcount, type_T **argtypes UNUSED)
{
if (argcount == 0)
return &t_list_job;
return &t_dict_any;
}
static type_T *
ret_dict_number(int argcount UNUSED, type_T **argtypes UNUSED)
{
return &t_dict_number;
@@ -877,6 +917,8 @@ static funcentry_T global_functions[] =
ret_string, f_expandcmd},
{"extend", 2, 3, FEARG_1, arg23_extend,
ret_first_arg, f_extend},
{"extendnew", 2, 3, FEARG_1, arg23_extendnew,
ret_first_cont, f_extendnew},
{"feedkeys", 1, 2, FEARG_1, NULL,
ret_void, f_feedkeys},
{"file_readable", 1, 1, FEARG_1, NULL, // obsolete
@@ -1082,7 +1124,7 @@ static funcentry_T global_functions[] =
{"job_getchannel", 1, 1, FEARG_1, NULL,
ret_channel, JOB_FUNC(f_job_getchannel)},
{"job_info", 0, 1, FEARG_1, NULL,
ret_dict_any, JOB_FUNC(f_job_info)},
ret_job_info, JOB_FUNC(f_job_info)},
{"job_setoptions", 2, 2, FEARG_1, NULL,
ret_void, JOB_FUNC(f_job_setoptions)},
{"job_start", 1, 2, FEARG_1, NULL,
@@ -1319,12 +1361,14 @@ static funcentry_T global_functions[] =
ret_number, f_rand},
{"range", 1, 3, FEARG_1, NULL,
ret_list_number, f_range},
{"readblob", 1, 1, FEARG_1, NULL,
ret_blob, f_readblob},
{"readdir", 1, 3, FEARG_1, NULL,
ret_list_string, f_readdir},
{"readdirex", 1, 3, FEARG_1, NULL,
ret_list_dict_any, f_readdirex},
{"readfile", 1, 3, FEARG_1, NULL,
ret_any, f_readfile},
ret_list_string, f_readfile},
{"reduce", 2, 3, FEARG_1, NULL,
ret_any, f_reduce},
{"reg_executing", 0, 0, 0, NULL,
@@ -1473,6 +1517,8 @@ static funcentry_T global_functions[] =
ret_float, FLOAT_FUNC(f_sin)},
{"sinh", 1, 1, FEARG_1, NULL,
ret_float, FLOAT_FUNC(f_sinh)},
{"slice", 2, 3, FEARG_1, NULL,
ret_first_arg, f_slice},
{"sort", 1, 3, FEARG_1, NULL,
ret_first_arg, f_sort},
{"sound_clear", 0, 0, 0, NULL,
@@ -1717,6 +1763,8 @@ static funcentry_T global_functions[] =
ret_float, FLOAT_FUNC(f_trunc)},
{"type", 1, 1, FEARG_1, NULL,
ret_number, f_type},
{"typename", 1, 1, FEARG_1, NULL,
ret_string, f_typename},
{"undofile", 1, 1, FEARG_1, NULL,
ret_string, f_undofile},
{"undotree", 0, 0, 0, NULL,
@@ -1795,7 +1843,11 @@ get_function_name(expand_T *xp, int idx)
{
name = get_user_func_name(xp, idx);
if (name != NULL)
{
if (*name != '<' && STRNCMP("g:", xp->xp_pattern, 2) == 0)
return cat_prefix_varname('g', name);
return name;
}
}
if (++intidx < (int)(sizeof(global_functions) / sizeof(funcentry_T)))
{
@@ -1896,7 +1948,11 @@ internal_func_name(int idx)
* Return FAIL and gives an error message when a type is wrong.
*/
int
internal_func_check_arg_types(type_T **types, int idx, int argcount)
internal_func_check_arg_types(
type_T **types,
int idx,
int argcount,
cctx_T *cctx)
{
argcheck_T *argchecks = global_functions[idx].f_argcheck;
int i;
@@ -1907,6 +1963,7 @@ internal_func_check_arg_types(type_T **types, int idx, int argcount)
context.arg_count = argcount;
context.arg_types = types;
context.arg_cctx = cctx;
for (i = 0; i < argcount; ++i)
if (argchecks[i] != NULL)
{
@@ -2710,14 +2767,15 @@ set_cursorpos(typval_T *argvars, typval_T *rettv, int charcol)
}
else if ((argvars[0].v_type == VAR_NUMBER ||
argvars[0].v_type == VAR_STRING)
&& argvars[1].v_type == VAR_NUMBER)
&& (argvars[1].v_type == VAR_NUMBER ||
argvars[1].v_type == VAR_STRING))
{
line = tv_get_lnum(argvars);
if (line < 0)
semsg(_(e_invarg2), tv_get_string(&argvars[0]));
col = (long)tv_get_number_chk(&argvars[1], NULL);
if (charcol)
col = buf_charidx_to_byteidx(curbuf, line, col);
col = buf_charidx_to_byteidx(curbuf, line, col) + 1;
if (argvars[2].v_type != VAR_UNKNOWN)
coladd = (long)tv_get_number_chk(&argvars[2], NULL);
}
@@ -3980,8 +4038,8 @@ getpos_both(
if (fp != NULL && charcol)
{
pos = *fp;
pos.col = buf_byteidx_to_charidx(wp->w_buffer, pos.lnum,
pos.col) - 1;
pos.col =
buf_byteidx_to_charidx(wp->w_buffer, pos.lnum, pos.col);
fp = &pos;
}
}
+3 -3
View File
@@ -1954,7 +1954,7 @@ static int varnamebuflen = 0;
/*
* Function to concatenate a prefix and a variable name.
*/
static char_u *
char_u *
cat_prefix_varname(int prefix, char_u *name)
{
int len;
@@ -3155,7 +3155,7 @@ set_var_const(
// A Vim9 script-local variable is also present in sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
if (is_script_local && vim9script)
update_vim9_script_var(FALSE, di, tv, &type);
update_vim9_script_var(FALSE, di, flags, tv, &type);
}
// existing variable, need to clear the value
@@ -3245,7 +3245,7 @@ set_var_const(
// A Vim9 script-local variable is also added to sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
if (is_script_local && vim9script)
update_vim9_script_var(TRUE, di, tv, &type);
update_vim9_script_var(TRUE, di, flags, tv, &type);
}
if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
+4
View File
@@ -673,6 +673,10 @@ f_win_execute(typval_T *argvars, typval_T *rettv)
win_T *save_curwin;
tabpage_T *save_curtab;
// Return an empty string if something fails.
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
if (wp != NULL && tp != NULL)
{
pos_T curpos = wp->w_cursor;
+16 -1
View File
@@ -2742,6 +2742,8 @@ do_ecmd(
else
{
win_T *the_curwin = curwin;
int did_decrement;
buf_T *was_curbuf = curbuf;
// Set the w_closing flag to avoid that autocommands close the
// window. And set b_locked for the same reason.
@@ -2754,7 +2756,7 @@ do_ecmd(
// Close the link to the current buffer. This will set
// oldwin->w_buffer to NULL.
u_sync(FALSE);
close_buffer(oldwin, curbuf,
did_decrement = close_buffer(oldwin, curbuf,
(flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE, FALSE);
the_curwin->w_closing = FALSE;
@@ -2776,7 +2778,15 @@ do_ecmd(
goto theend;
}
if (buf == curbuf) // already in new buffer
{
// close_buffer() has decremented the window count,
// increment it again here and restore w_buffer.
if (did_decrement && buf_valid(was_curbuf))
++was_curbuf->b_nwindows;
if (win_valid_any_tab(oldwin) && oldwin->w_buffer == NULL)
oldwin->w_buffer = was_curbuf;
auto_buf = TRUE;
}
else
{
#ifdef FEAT_SYN_HL
@@ -4148,6 +4158,7 @@ ex_substitute(exarg_T *eap)
{
char_u *orig_line = NULL;
int len_change = 0;
int save_p_lz = p_lz;
#ifdef FEAT_FOLDING
int save_p_fen = curwin->w_p_fen;
@@ -4158,6 +4169,9 @@ ex_substitute(exarg_T *eap)
temp = RedrawingDisabled;
RedrawingDisabled = 0;
// avoid calling update_screen() in vgetorpeek()
p_lz = FALSE;
if (new_start != NULL)
{
// There already was a substitution, we would
@@ -4233,6 +4247,7 @@ ex_substitute(exarg_T *eap)
msg_didout = FALSE; // don't scroll up
msg_col = 0;
gotocmdline(TRUE);
p_lz = save_p_lz;
// restore the line
if (orig_line != NULL)
+1 -1
View File
@@ -1371,7 +1371,7 @@ EXCMD(CMD_silent, "silent", ex_wrongmodifier,
EX_NEEDARG|EX_EXTRA|EX_BANG|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
ADDR_NONE),
EXCMD(CMD_sleep, "sleep", ex_sleep,
EX_RANGE|EX_COUNT|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
EX_BANG|EX_RANGE|EX_COUNT|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
ADDR_OTHER),
EXCMD(CMD_slast, "slast", ex_last,
EX_EXTRA|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR,
+12 -5
View File
@@ -1274,7 +1274,7 @@ do_cmdline(
*/
if (did_throw)
{
void *p = NULL;
char *p = NULL;
msglist_T *messages = NULL, *next;
/*
@@ -1289,7 +1289,7 @@ do_cmdline(
vim_snprintf((char *)IObuff, IOSIZE,
_("E605: Exception not caught: %s"),
current_exception->value);
p = vim_strsave(IObuff);
p = (char *)vim_strsave(IObuff);
break;
case ET_ERROR:
messages = current_exception->messages;
@@ -7233,14 +7233,17 @@ ex_sleep(exarg_T *eap)
case NUL: len *= 1000L; break;
default: semsg(_(e_invarg2), eap->arg); return;
}
do_sleep(len);
// Hide the cursor if invoked with !
do_sleep(len, eap->forceit);
}
/*
* Sleep for "msec" milliseconds, but keep checking for a CTRL-C every second.
* Hide the cursor if "hide_cursor" is TRUE.
*/
void
do_sleep(long msec)
do_sleep(long msec, int hide_cursor)
{
long done = 0;
long wait_now;
@@ -7252,7 +7255,11 @@ do_sleep(long msec)
ELAPSED_INIT(start_tv);
# endif
cursor_on();
if (hide_cursor)
cursor_off();
else
cursor_on();
out_flush_cursor(FALSE, FALSE);
while (!got_int && done < msec)
{
+23 -4
View File
@@ -1640,11 +1640,11 @@ f_readdirex(typval_T *argvars, typval_T *rettv)
/*
* "readfile()" function
*/
void
f_readfile(typval_T *argvars, typval_T *rettv)
static void
read_file_or_blob(typval_T *argvars, typval_T *rettv, int always_blob)
{
int binary = FALSE;
int blob = FALSE;
int blob = always_blob;
int failed = FALSE;
char_u *fname;
FILE *fd;
@@ -1796,7 +1796,8 @@ f_readfile(typval_T *argvars, typval_T *rettv)
if (dest < buf)
{
adjust_prevlen = (int)(buf - dest); // must be 1 or 2
// must be 1 or 2
adjust_prevlen = (int)(buf - dest);
dest = buf;
}
if (readlen > p - buf + 1)
@@ -1866,6 +1867,24 @@ f_readfile(typval_T *argvars, typval_T *rettv)
fclose(fd);
}
/*
* "readblob()" function
*/
void
f_readblob(typval_T *argvars, typval_T *rettv)
{
read_file_or_blob(argvars, rettv, TRUE);
}
/*
* "readfile()" function
*/
void
f_readfile(typval_T *argvars, typval_T *rettv)
{
read_file_or_blob(argvars, rettv, FALSE);
}
/*
* "resolve()" function
*/
+1
View File
@@ -433,6 +433,7 @@ EXTERN type_T t_dict_empty INIT6(VAR_DICT, 0, 0, TTFLAG_STATIC, &t_unknown, NULL
EXTERN type_T t_list_bool INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_bool, NULL);
EXTERN type_T t_list_number INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_number, NULL);
EXTERN type_T t_list_string INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_string, NULL);
EXTERN type_T t_list_job INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_job, NULL);
EXTERN type_T t_list_dict_any INIT6(VAR_LIST, 0, 0, TTFLAG_STATIC, &t_dict_any, NULL);
EXTERN type_T t_dict_bool INIT6(VAR_DICT, 0, 0, TTFLAG_STATIC, &t_bool, NULL);
+108 -23
View File
@@ -905,14 +905,15 @@ list_slice(list_T *ol, long n1, long n2)
list_slice_or_index(
list_T *list,
int range,
long n1_arg,
long n2_arg,
varnumber_T n1_arg,
varnumber_T n2_arg,
int exclusive,
typval_T *rettv,
int verbose)
{
long len = list_len(list);
long n1 = n1_arg;
long n2 = n2_arg;
varnumber_T n1 = n1_arg;
varnumber_T n2 = n2_arg;
typval_T var1;
if (n1 < 0)
@@ -936,7 +937,9 @@ list_slice_or_index(
if (n2 < 0)
n2 = len + n2;
else if (n2 >= len)
n2 = len - 1;
n2 = len - (exclusive ? 0 : 1);
if (exclusive)
--n2;
if (n2 < 0 || n2 + 1 < n1)
n2 = -1;
l = list_slice(list, n1, n2);
@@ -1982,10 +1985,18 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
: N_("filter() argument"));
int save_did_emsg;
int idx = 0;
type_T *type = NULL;
garray_T type_list;
// map() and filter() return the first argument, also on failure.
if (filtermap != FILTERMAP_MAPNEW)
copy_tv(&argvars[0], rettv);
if (filtermap == FILTERMAP_MAP && in_vim9script())
{
// Check that map() does not change the type of the dict.
ga_init2(&type_list, sizeof(type_T *), 10);
type = typval2type(argvars, &type_list);
}
if (argvars[0].v_type == VAR_BLOB)
{
@@ -1995,7 +2006,7 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
rettv->vval.v_blob = NULL;
}
if ((b = argvars[0].vval.v_blob) == NULL)
return;
goto theend;
}
else if (argvars[0].v_type == VAR_LIST)
{
@@ -2007,7 +2018,7 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
if ((l = argvars[0].vval.v_list) == NULL
|| (filtermap == FILTERMAP_FILTER
&& value_check_lock(l->lv_lock, arg_errmsg, TRUE)))
return;
goto theend;
}
else if (argvars[0].v_type == VAR_DICT)
{
@@ -2019,12 +2030,12 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
if ((d = argvars[0].vval.v_dict) == NULL
|| (filtermap == FILTERMAP_FILTER
&& value_check_lock(d->dv_lock, arg_errmsg, TRUE)))
return;
goto theend;
}
else
{
semsg(_(e_listdictblobarg), ermsg);
return;
goto theend;
}
expr = &argvars[1];
@@ -2052,7 +2063,7 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
if (filtermap == FILTERMAP_MAPNEW)
{
if (rettv_dict_alloc(rettv) == FAIL)
return;
goto theend;
d_ret = rettv->vval.v_dict;
}
@@ -2087,6 +2098,12 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
}
if (filtermap == FILTERMAP_MAP)
{
if (type != NULL && check_typval_type(type->tt_member,
&newtv, 0) == FAIL)
{
clear_tv(&newtv);
break;
}
// map(): replace the dict item value
clear_tv(&di->di_tv);
newtv.v_lock = 0;
@@ -2123,7 +2140,7 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
if (filtermap == FILTERMAP_MAPNEW)
{
if (blob_copy(b, rettv) == FAIL)
return;
goto theend;
b_ret = rettv->vval.v_blob;
}
@@ -2172,7 +2189,7 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
if (filtermap == FILTERMAP_MAPNEW)
{
if (rettv_list_alloc(rettv) == FAIL)
return;
goto theend;
l_ret = rettv->vval.v_list;
}
// set_vim_var_nr() doesn't set the type
@@ -2215,6 +2232,13 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
}
if (filtermap != FILTERMAP_FILTER)
{
if (filtermap == FILTERMAP_MAP && type != NULL
&& check_typval_type(type->tt_member,
&newtv, 0) == FAIL)
{
clear_tv(&newtv);
break;
}
// map(), mapnew(): always append the new value to the
// list
if (list_append_tv_move(filtermap == FILTERMAP_MAP
@@ -2253,6 +2277,12 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
}
if (filtermap == FILTERMAP_MAP)
{
if (type != NULL && check_typval_type(type->tt_member,
&newtv, 0) == FAIL)
{
clear_tv(&newtv);
break;
}
// map(): replace the list item value
clear_tv(&li->li_tv);
newtv.v_lock = 0;
@@ -2278,6 +2308,10 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
did_emsg |= save_did_emsg;
}
theend:
if (type != NULL)
clear_type_list(&type_list);
}
/*
@@ -2454,14 +2488,11 @@ f_count(typval_T *argvars, typval_T *rettv)
}
/*
* "extend(list, list [, idx])" function
* "extend(dict, dict [, action])" function
* "extend()" or "extendnew()" function. "is_new" is TRUE for extendnew().
*/
void
f_extend(typval_T *argvars, typval_T *rettv)
static void
extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
{
char_u *arg_errmsg = (char_u *)N_("extend() argument");
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
{
list_T *l1, *l2;
@@ -2476,8 +2507,16 @@ f_extend(typval_T *argvars, typval_T *rettv)
return;
}
l2 = argvars[1].vval.v_list;
if (!value_check_lock(l1->lv_lock, arg_errmsg, TRUE) && l2 != NULL)
if ((is_new || !value_check_lock(l1->lv_lock, arg_errmsg, TRUE))
&& l2 != NULL)
{
if (is_new)
{
l1 = list_copy(l1, FALSE, get_copyID());
if (l1 == NULL)
return;
}
if (argvars[2].v_type != VAR_UNKNOWN)
{
before = (long)tv_get_number_chk(&argvars[2], &error);
@@ -2500,7 +2539,14 @@ f_extend(typval_T *argvars, typval_T *rettv)
item = NULL;
list_extend(l1, l2, item);
copy_tv(&argvars[0], rettv);
if (is_new)
{
rettv->v_type = VAR_LIST;
rettv->vval.v_list = l1;
rettv->v_lock = FALSE;
}
else
copy_tv(&argvars[0], rettv);
}
}
else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
@@ -2516,8 +2562,16 @@ f_extend(typval_T *argvars, typval_T *rettv)
return;
}
d2 = argvars[1].vval.v_dict;
if (!value_check_lock(d1->dv_lock, arg_errmsg, TRUE) && d2 != NULL)
if ((is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TRUE))
&& d2 != NULL)
{
if (is_new)
{
d1 = dict_copy(d1, FALSE, get_copyID());
if (d1 == NULL)
return;
}
// Check the third argument.
if (argvars[2].v_type != VAR_UNKNOWN)
{
@@ -2540,11 +2594,42 @@ f_extend(typval_T *argvars, typval_T *rettv)
dict_extend(d1, d2, action);
copy_tv(&argvars[0], rettv);
if (is_new)
{
rettv->v_type = VAR_DICT;
rettv->vval.v_dict = d1;
rettv->v_lock = FALSE;
}
else
copy_tv(&argvars[0], rettv);
}
}
else
semsg(_(e_listdictarg), "extend()");
semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()");
}
/*
* "extend(list, list [, idx])" function
* "extend(dict, dict [, action])" function
*/
void
f_extend(typval_T *argvars, typval_T *rettv)
{
char_u *errmsg = (char_u *)N_("extend() argument");
extend(argvars, rettv, errmsg, FALSE);
}
/*
* "extendnew(list, list [, idx])" function
* "extendnew(dict, dict [, action])" function
*/
void
f_extendnew(typval_T *argvars, typval_T *rettv)
{
char_u *errmsg = (char_u *)N_("extendnew() argument");
extend(argvars, rettv, errmsg, TRUE);
}
/*
+2 -2
View File
@@ -993,7 +993,7 @@ getcount:
// something different from CTRL-N. Can't be avoided.
while ((c = vpeekc()) <= 0 && towait > 0L)
{
do_sleep(towait > 50L ? 50L : towait);
do_sleep(towait > 50L ? 50L : towait, FALSE);
towait -= 50L;
}
if (c > 0)
@@ -6242,7 +6242,7 @@ nv_g_cmd(cmdarg_T *cap)
* "gs": Goto sleep.
*/
case 's':
do_sleep(cap->count1 * 1000L);
do_sleep(cap->count1 * 1000L, FALSE);
break;
/*
+2
View File
@@ -3076,6 +3076,8 @@ static struct vimoption options[] =
p_term("t_EC", T_CEC)
p_term("t_EI", T_CEI)
p_term("t_fs", T_FS)
p_term("t_fd", T_FD)
p_term("t_fe", T_FE)
p_term("t_GP", T_CGP)
p_term("t_IE", T_CIE)
p_term("t_IS", T_CIS)
+1 -1
View File
@@ -5,7 +5,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags);
void set_bufref(bufref_T *bufref, buf_T *buf);
int bufref_valid(bufref_T *bufref);
int buf_valid(buf_T *buf);
void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last, int ignore_abort);
int close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last, int ignore_abort);
void buf_clear_file(buf_T *buf);
void buf_freeall(buf_T *buf, int flags);
void free_wininfo(wininfo_T *wip);
+4 -2
View File
@@ -11,6 +11,7 @@ int eval_expr_to_bool(typval_T *expr, int *error);
char_u *eval_to_string_skip(char_u *arg, exarg_T *eap, int skip);
int skip_expr(char_u **pp, evalarg_T *evalarg);
int skip_expr_concatenate(char_u **arg, char_u **start, char_u **end, evalarg_T *evalarg);
char_u *typval2string(typval_T *tv, int convert);
char_u *eval_to_string_eap(char_u *arg, int convert, exarg_T *eap);
char_u *eval_to_string(char_u *arg, int convert);
char_u *eval_to_string_safe(char_u *arg, int use_sandbox);
@@ -41,7 +42,8 @@ void eval_addblob(typval_T *tv1, typval_T *tv2);
int eval_addlist(typval_T *tv1, typval_T *tv2);
int eval_leader(char_u **arg, int vim9);
int check_can_index(typval_T *rettv, int evaluate, int verbose);
int eval_index_inner(typval_T *rettv, int is_range, typval_T *var1, typval_T *var2, char_u *key, int keylen, int verbose);
void f_slice(typval_T *argvars, typval_T *rettv);
int eval_index_inner(typval_T *rettv, int is_range, typval_T *var1, typval_T *var2, int exclusive, char_u *key, int keylen, int verbose);
char_u *partial_name(partial_T *pt);
void partial_unref(partial_T *pt);
int get_copyID(void);
@@ -58,7 +60,7 @@ int string2float(char_u *text, float_T *value);
int buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx);
int buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx);
pos_T *var2fpos(typval_T *varp, int dollar_lnum, int *fnum, int charcol);
int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, int char_col);
int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, int charcol);
int get_env_len(char_u **arg);
int get_id_len(char_u **arg);
int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose);
+1 -1
View File
@@ -4,7 +4,7 @@ char_u *get_expr_name(expand_T *xp, int idx);
int find_internal_func(char_u *name);
int has_internal_func(char_u *name);
char *internal_func_name(int idx);
int internal_func_check_arg_types(type_T **types, int idx, int argcount);
int internal_func_check_arg_types(type_T **types, int idx, int argcount, cctx_T *cctx);
type_T *internal_func_ret_type(int idx, int argcount, type_T **argtypes);
int internal_func_is_map(int idx);
int check_internal_func(int idx, int argcount);
+1
View File
@@ -26,6 +26,7 @@ void ex_unletlock(exarg_T *eap, char_u *argstart, int deep, int glv_flags, int (
int do_unlet(char_u *name, int forceit);
void item_lock(typval_T *tv, int deep, int lock, int check_refcount);
void del_menutrans_vars(void);
char_u *cat_prefix_varname(int prefix, char_u *name);
char_u *get_user_var_name(expand_T *xp, int idx);
char *get_var_special_name(int nr);
dict_T *get_globvar_dict(void);
+1 -1
View File
@@ -43,7 +43,7 @@ void free_cd_dir(void);
void post_chdir(cdscope_T scope);
int changedir_func(char_u *new_dir, int forceit, cdscope_T scope);
void ex_cd(exarg_T *eap);
void do_sleep(long msec);
void do_sleep(long msec, int hide_cursor);
void ex_may_print(exarg_T *eap);
void ex_redraw(exarg_T *eap);
int vim_mkdir_emsg(char_u *name, int prot);
+2 -1
View File
@@ -1,5 +1,6 @@
/* filepath.c */
int modify_fname(char_u *src, int tilde_file, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen);
void shorten_dir(char_u *str);
void f_chdir(typval_T *argvars, typval_T *rettv);
void f_delete(typval_T *argvars, typval_T *rettv);
void f_executable(typval_T *argvars, typval_T *rettv);
@@ -21,10 +22,10 @@ void f_glob2regpat(typval_T *argvars, typval_T *rettv);
void f_globpath(typval_T *argvars, typval_T *rettv);
void f_isdirectory(typval_T *argvars, typval_T *rettv);
void f_mkdir(typval_T *argvars, typval_T *rettv);
void shorten_dir(char_u *str);
void f_pathshorten(typval_T *argvars, typval_T *rettv);
void f_readdir(typval_T *argvars, typval_T *rettv);
void f_readdirex(typval_T *argvars, typval_T *rettv);
void f_readblob(typval_T *argvars, typval_T *rettv);
void f_readfile(typval_T *argvars, typval_T *rettv);
void f_resolve(typval_T *argvars, typval_T *rettv);
void f_tempname(typval_T *argvars, typval_T *rettv);
+2 -1
View File
@@ -34,7 +34,7 @@ void f_flatten(typval_T *argvars, typval_T *rettv);
int list_extend(list_T *l1, list_T *l2, listitem_T *bef);
int list_concat(list_T *l1, list_T *l2, typval_T *tv);
list_T *list_slice(list_T *ol, long n1, long n2);
int list_slice_or_index(list_T *list, int range, long n1_arg, long n2_arg, typval_T *rettv, int verbose);
int list_slice_or_index(list_T *list, int range, varnumber_T n1_arg, varnumber_T n2_arg, int exclusive, typval_T *rettv, int verbose);
list_T *list_copy(list_T *orig, int deep, int copyID);
void vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2);
char_u *list2string(typval_T *tv, int copyID, int restore_copyID);
@@ -52,6 +52,7 @@ void f_mapnew(typval_T *argvars, typval_T *rettv);
void f_add(typval_T *argvars, typval_T *rettv);
void f_count(typval_T *argvars, typval_T *rettv);
void f_extend(typval_T *argvars, typval_T *rettv);
void f_extendnew(typval_T *argvars, typval_T *rettv);
void f_insert(typval_T *argvars, typval_T *rettv);
void f_remove(typval_T *argvars, typval_T *rettv);
void f_reverse(typval_T *argvars, typval_T *rettv);
+1
View File
@@ -2,6 +2,7 @@
int check_defined(char_u *p, size_t len, cctx_T *cctx);
int check_compare_types(exprtype_T type, typval_T *tv1, typval_T *tv2);
int use_typecheck(type_T *actual, type_T *expected);
int need_type(type_T *actual, type_T *expected, int offset, int arg_idx, cctx_T *cctx, int silent, int actual_is_const);
int get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx);
imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx);
imported_T *find_imported_in_script(char_u *name, size_t len, int sid);
+1 -1
View File
@@ -2,7 +2,7 @@
void to_string_error(vartype_T vartype);
void funcstack_check_refcount(funcstack_T *funcstack);
char_u *char_from_string(char_u *str, varnumber_T index);
char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last);
char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive);
int fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx);
int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, partial_T *partial, typval_T *rettv);
void ex_disassemble(exarg_T *eap);
+1 -1
View File
@@ -10,7 +10,7 @@ void ex_import(exarg_T *eap);
int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx);
char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, evalarg_T *evalarg, void *cctx);
char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg);
void update_vim9_script_var(int create, dictitem_T *di, typval_T *tv, type_T **type);
void update_vim9_script_var(int create, dictitem_T *di, int flags, typval_T *tv, type_T **type);
void hide_script_var(scriptitem_T *si, int idx, int func_defined);
void free_all_script_vars(scriptitem_T *si);
svar_T *find_typval_in_script(typval_T *dest);
+1 -1
View File
@@ -15,7 +15,6 @@ int check_typval_type(type_T *expected, typval_T *actual_tv, int argidx);
void type_mismatch(type_T *expected, type_T *actual);
void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
int check_type(type_T *expected, type_T *actual, int give_msg, int argidx);
int check_arg_type(type_T *expected, type_T *actual, int argidx);
int check_argument_types(type_T *type, typval_T *argvars, int argcount, char_u *name);
char_u *skip_type(char_u *start, int optional);
type_T *parse_type(char_u **arg, garray_T *type_gap, int give_error);
@@ -24,4 +23,5 @@ void common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap
type_T *get_member_type_from_stack(type_T **stack_top, int count, int skip, garray_T *type_gap);
char *vartype_name(vartype_T type);
char *type_name(type_T *type, char **tofree);
void f_typename(typval_T *argvars, typval_T *rettv);
/* vim: set ft=c : */
+16 -40
View File
@@ -1019,30 +1019,6 @@ ex_options(
/*
* ":source" and associated commands.
*/
/*
* Structure used to store info for each sourced file.
* It is shared between do_source() and getsourceline().
* This is required, because it needs to be handed to do_cmdline() and
* sourcing can be done recursively.
*/
struct source_cookie
{
FILE *fp; // opened file for sourcing
char_u *nextline; // if not NULL: line that was read ahead
linenr_T sourcing_lnum; // line number of the source file
int finished; // ":finish" used
#ifdef USE_CRNL
int fileformat; // EOL_UNKNOWN, EOL_UNIX or EOL_DOS
int error; // TRUE if LF found after CR-LF
#endif
#ifdef FEAT_EVAL
linenr_T breakpoint; // next line with breakpoint or zero
char_u *fname; // name of sourced file
int dbg_tick; // debug_tick when breakpoint was set
int level; // top nesting level of sourced file
#endif
vimconv_T conv; // type of conversion
};
#ifdef FEAT_EVAL
/*
@@ -1051,7 +1027,7 @@ struct source_cookie
linenr_T *
source_breakpoint(void *cookie)
{
return &((struct source_cookie *)cookie)->breakpoint;
return &((source_cookie_T *)cookie)->breakpoint;
}
/*
@@ -1060,7 +1036,7 @@ source_breakpoint(void *cookie)
int *
source_dbg_tick(void *cookie)
{
return &((struct source_cookie *)cookie)->dbg_tick;
return &((source_cookie_T *)cookie)->dbg_tick;
}
/*
@@ -1069,7 +1045,7 @@ source_dbg_tick(void *cookie)
int
source_level(void *cookie)
{
return ((struct source_cookie *)cookie)->level;
return ((source_cookie_T *)cookie)->level;
}
/*
@@ -1079,7 +1055,7 @@ source_level(void *cookie)
char_u *
source_nextline(void *cookie)
{
return ((struct source_cookie *)cookie)->nextline;
return ((source_cookie_T *)cookie)->nextline;
}
#endif
@@ -1130,7 +1106,7 @@ do_source(
int is_vimrc, // DOSO_ value
int *ret_sid UNUSED)
{
struct source_cookie cookie;
source_cookie_T cookie;
char_u *p;
char_u *fname_exp;
char_u *firstline = NULL;
@@ -1613,12 +1589,12 @@ get_sourced_lnum(
void *cookie)
{
return fgetline == getsourceline
? ((struct source_cookie *)cookie)->sourcing_lnum
? ((source_cookie_T *)cookie)->sourcing_lnum
: SOURCING_LNUM;
}
static char_u *
get_one_sourceline(struct source_cookie *sp)
get_one_sourceline(source_cookie_T *sp)
{
garray_T ga;
int len;
@@ -1736,7 +1712,7 @@ getsourceline(
int indent UNUSED,
getline_opt_T options)
{
struct source_cookie *sp = (struct source_cookie *)cookie;
source_cookie_T *sp = (source_cookie_T *)cookie;
char_u *line;
char_u *p;
int do_vim9_all = in_vim9script()
@@ -1761,8 +1737,8 @@ getsourceline(
SOURCING_LNUM = sp->sourcing_lnum + 1;
// Get current line. If there is a read-ahead line, use it, otherwise get
// one now.
if (sp->finished)
// one now. "fp" is NULL if actually using a string.
if (sp->finished || sp->fp == NULL)
line = NULL;
else if (sp->nextline == NULL)
line = get_one_sourceline(sp);
@@ -1880,8 +1856,8 @@ getsourceline(
void
ex_scriptencoding(exarg_T *eap)
{
struct source_cookie *sp;
char_u *name;
source_cookie_T *sp;
char_u *name;
if (!getline_equal(eap->getline, eap->cookie, getsourceline))
{
@@ -1899,7 +1875,7 @@ ex_scriptencoding(exarg_T *eap)
name = eap->arg;
// Setup for conversion from the specified encoding to 'encoding'.
sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie);
sp = (source_cookie_T *)getline_cookie(eap->getline, eap->cookie);
convert_setup(&sp->conv, name, p_enc);
if (name != eap->arg)
@@ -1963,7 +1939,7 @@ do_finish(exarg_T *eap, int reanimate)
int idx;
if (reanimate)
((struct source_cookie *)getline_cookie(eap->getline,
((source_cookie_T *)getline_cookie(eap->getline,
eap->cookie))->finished = FALSE;
// Cleanup (and inactivate) conditionals, but stop when a try conditional
@@ -1977,7 +1953,7 @@ do_finish(exarg_T *eap, int reanimate)
report_make_pending(CSTP_FINISH, NULL);
}
else
((struct source_cookie *)getline_cookie(eap->getline,
((source_cookie_T *)getline_cookie(eap->getline,
eap->cookie))->finished = TRUE;
}
@@ -1993,7 +1969,7 @@ source_finished(
void *cookie)
{
return (getline_equal(fgetline, cookie, getsourceline)
&& ((struct source_cookie *)getline_cookie(
&& ((source_cookie_T *)getline_cookie(
fgetline, cookie))->finished);
}
+27 -1
View File
@@ -1777,7 +1777,7 @@ struct svar_S {
char_u *sv_name; // points into "sn_all_vars" di_key
typval_T *sv_tv; // points into "sn_vars" or "sn_all_vars" di_tv
type_T *sv_type;
int sv_const;
int sv_const; // 0, ASSIGN_CONST or ASSIGN_FINAL
int sv_export; // "export let var = val"
};
@@ -4319,6 +4319,32 @@ typedef struct
int sa_wrapped; // search wrapped around
} searchit_arg_T;
/*
* Cookie used by getsourceline().
*/
/*
* Cookie used to store info for each sourced file.
* It is shared between do_source() and getsourceline().
* This is passed to do_cmdline().
*/
typedef struct {
FILE *fp; // opened file for sourcing
char_u *nextline; // if not NULL: line that was read ahead
linenr_T sourcing_lnum; // line number of the source file
int finished; // ":finish" used
#ifdef USE_CRNL
int fileformat; // EOL_UNKNOWN, EOL_UNIX or EOL_DOS
int error; // TRUE if LF found after CR-LF
#endif
#ifdef FEAT_EVAL
linenr_T breakpoint; // next line with breakpoint or zero
char_u *fname; // name of sourced file
int dbg_tick; // debug_tick when breakpoint was set
int level; // top nesting level of sourced file
#endif
vimconv_T conv; // type of conversion
} source_cookie_T;
#define WRITEBUFSIZE 8192 // size of normal write buffer
+86 -2
View File
@@ -196,6 +196,11 @@ static char_u *vim_tgetstr(char *s, char_u **pp);
static int detected_8bit = FALSE; // detected 8-bit terminal
#if (defined(UNIX) || defined(VMS))
static int focus_mode = FALSE; // xterm's "focus reporting" availability
static int focus_state = FALSE; // TRUE if the terminal window gains focus
#endif
#ifdef FEAT_TERMRESPONSE
// When the cursor shape was detected these values are used:
// 1: block, 2: underline, 3: vertical bar
@@ -908,6 +913,10 @@ static struct builtin_term builtin_termcaps[] =
{(int)KS_CRT, IF_EB("\033[23;2t", ESC_STR "[23;2t")},
{(int)KS_SSI, IF_EB("\033[22;1t", ESC_STR "[22;1t")},
{(int)KS_SRI, IF_EB("\033[23;1t", ESC_STR "[23;1t")},
# if (defined(UNIX) || defined(VMS))
{(int)KS_FD, IF_EB("\033[?1004l", ESC_STR "[?1004l")},
{(int)KS_FE, IF_EB("\033[?1004h", ESC_STR "[?1004h")},
# endif
{K_UP, IF_EB("\033O*A", ESC_STR "O*A")},
{K_DOWN, IF_EB("\033O*B", ESC_STR "O*B")},
@@ -2050,6 +2059,27 @@ set_termname(char_u *term)
set_mouse_termcode(KS_MOUSE, (char_u *)"\233M");
#endif
#ifdef FEAT_MOUSE_XTERM
// focus reporting is supported by xterm compatible terminals and tmux.
if (use_xterm_like_mouse(term))
{
char_u name[3];
// handle focus in event
name[0] = KS_EXTRA;
name[1] = KE_FOCUSGAINED;
name[2] = NUL;
add_termcode(name, (char_u *)"\033[I", FALSE);
// handle focus out event
name[1] = KE_FOCUSLOST;
add_termcode(name, (char_u *)"\033[O", FALSE);
focus_mode = TRUE;
focus_state = TRUE;
}
#endif
#ifdef USE_TERM_CONSOLE
// DEFAULT_TERM indicates that it is the machine console.
if (STRCMP(term, DEFAULT_TERM) != 0)
@@ -2525,7 +2555,12 @@ out_flush(void)
if (ch_log_output)
{
out_buf[len] = NUL;
ch_log(NULL, "raw terminal output: \"%s\"", out_buf);
ch_log(NULL, "raw %s output: \"%s\"",
# ifdef FEAT_GUI
(gui.in_use && !gui.dying && !gui.starting) ? "GUI" :
# endif
"terminal",
out_buf);
ch_log_output = FALSE;
}
#endif
@@ -2684,7 +2719,7 @@ out_str_cf(char_u *s)
else
{
++p;
do_sleep(duration);
do_sleep(duration, FALSE);
}
# else
// Rely on the terminal library to sleep.
@@ -3588,6 +3623,13 @@ starttermcap(void)
out_str(T_CTI); // start "raw" mode
out_str(T_KS); // start "keypad transmit" mode
out_str(T_BE); // enable bracketed paste mode
#if (defined(UNIX) || defined(VMS))
// enable xterm's focus reporting mode
if (focus_mode && *T_FE != NUL)
out_str(T_FE);
#endif
out_flush();
termcap_active = TRUE;
screen_start(); // don't know where cursor is now
@@ -3639,6 +3681,13 @@ stoptermcap(void)
#ifdef FEAT_JOB_CHANNEL
ch_log_output = TRUE;
#endif
#if (defined(UNIX) || defined(VMS))
// disable xterm's focus reporting mode
if (focus_mode && *T_FD != NUL)
out_str(T_FD);
#endif
out_str(T_BD); // disable bracketed paste mode
out_str(T_KE); // stop "keypad transmit" mode
out_flush();
@@ -5653,6 +5702,41 @@ check_termcode(
# endif // !USE_ON_FLY_SCROLL
#endif // FEAT_GUI
#if (defined(UNIX) || defined(VMS))
/*
* Handle FocusIn/FocusOut event sequences reported by XTerm.
* (CSI I/CSI O)
*/
if (focus_mode
# ifdef FEAT_GUI
&& !gui.in_use
# endif
&& key_name[0] == KS_EXTRA
)
{
if (key_name[1] == KE_FOCUSGAINED)
{
if (!focus_state)
{
ui_focus_change(TRUE);
did_cursorhold = TRUE;
focus_state = TRUE;
}
key_name[1] = (int)KE_IGNORE;
}
else if (key_name[1] == KE_FOCUSLOST)
{
if (focus_state)
{
ui_focus_change(FALSE);
did_cursorhold = TRUE;
focus_state = FALSE;
}
key_name[1] = (int)KE_IGNORE;
}
}
#endif
/*
* Change <xHome> to <Home>, <xUp> to <Up>, etc.
*/
+6 -2
View File
@@ -109,10 +109,12 @@ enum SpecialKey
KS_CST, // save window title
KS_CRT, // restore window title
KS_SSI, // save icon text
KS_SRI // restore icon text
KS_SRI, // restore icon text
KS_FD, // disable focus event tracking
KS_FE // enable focus event tracking
};
#define KS_LAST KS_SRI
#define KS_LAST KS_FE
/*
* the terminal capabilities are stored in this array
@@ -212,6 +214,8 @@ extern char_u *(term_strings[]); // current terminal strings
#define T_CRT (TERM_STR(KS_CRT)) // restore window title
#define T_SSI (TERM_STR(KS_SSI)) // save icon text
#define T_SRI (TERM_STR(KS_SRI)) // restore icon text
#define T_FD (TERM_STR(KS_FD)) // disable focus event tracking
#define T_FE (TERM_STR(KS_FE)) // enable focus event tracking
typedef enum {
TMODE_COOK, // terminal mode for external cmds and Ex mode
+2
View File
@@ -247,6 +247,7 @@ NEW_TESTS = \
test_shortpathname \
test_signals \
test_signs \
test_sleep \
test_smartindent \
test_sort \
test_sound \
@@ -474,6 +475,7 @@ NEW_TESTS_RES = \
test_shortpathname.res \
test_signals.res \
test_signs.res \
test_sleep.res \
test_smartindent.res \
test_sort.res \
test_sound.res \
+31 -3
View File
@@ -500,6 +500,34 @@ func Test_autocmd_bufwipe_in_SessLoadPost()
endfor
endfunc
" Using :blast and :ball for many events caused a crash, because b_nwindows was
" not incremented correctly.
func Test_autocmd_blast_badd()
" The system() here causes SetChangeMarks() to fail, when run in the GUI
" under Windows. No idea why. Happens with any external command, not
" related to the actual test.
" TODO: find the cause
if has('win32')
throw 'Skipped: calling system() causes problems'
endif
let content =<< trim [CODE]
au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* blast
edit foo1
au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* ball
edit foo2
call writefile(['OK'], 'Xerrors')
qall
[CODE]
call writefile(content, 'XblastBall')
call system(GetVimCommand() .. ' --clean -S XblastBall')
call assert_match('OK', readfile('Xerrors')->join())
call delete('XblastBall')
call delete('Xerrors')
endfunc
" SEGV occurs in older versions.
func Test_autocmd_bufwipe_in_SessLoadPost2()
tabnew
@@ -1619,14 +1647,14 @@ func Test_BufReadCmd()
endfunc
func SetChangeMarks(start, end)
exe a:start. 'mark ['
exe a:end. 'mark ]'
exe a:start .. 'mark ['
exe a:end .. 'mark ]'
endfunc
" Verify the effects of autocmds on '[ and ']
func Test_change_mark_in_autocmds()
edit! Xtest
call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u", 'xtn')
call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u\<Esc>", 'xtn')
call SetChangeMarks(2, 3)
write
+1
View File
@@ -87,6 +87,7 @@ func Test_client_server()
call writefile(['one', 'two'], 'Xclientfile')
call system(cmd)
call WaitForAssert({-> assert_equal('two', remote_expr(name, "getline(2)", "", 2))})
call delete('Xclientfile')
" Expression evaluated locally.
if v:servername == ''
+4
View File
@@ -619,6 +619,10 @@ func Test_cmdline_complete_user_func()
call assert_match('"func Test_cmdline_complete_user', @:)
call feedkeys(":func s:ScriptL\<Tab>\<Home>\"\<cr>", 'tx')
call assert_match('"func <SNR>\d\+_ScriptLocalFunction', @:)
" g: prefix also works
call feedkeys(":echo g:Test_cmdline_complete_user_f\<Tab>\<Home>\"\<cr>", 'tx')
call assert_match('"echo g:Test_cmdline_complete_user_func', @:)
endfunc
func Test_cmdline_complete_user_names()
+66 -4
View File
@@ -25,6 +25,9 @@ func Test_move_cursor()
" below last line goes to last line
eval [9, 1]->cursor()
call assert_equal([4, 1, 0, 1], getcurpos()[1:])
" pass string arguments
call cursor('3', '3')
call assert_equal([3, 3, 0, 3], getcurpos()[1:])
call setline(1, ["\<TAB>"])
call cursor(1, 1, 1)
@@ -123,11 +126,18 @@ func Test_screenpos_number()
bwipe!
endfunc
" Save the visual start character position
func SaveVisualStartCharPos()
call add(g:VisualStartPos, getcharpos('v'))
return ''
endfunc
" Save the current cursor character position in insert mode
func SaveInsertCurrentCharPos()
call add(g:InsertCurrentPos, getcharpos('.'))
return ''
endfunc
" Test for the getcharpos() function
func Test_getcharpos()
call assert_fails('call getcharpos({})', 'E731:')
@@ -156,16 +166,29 @@ func Test_getcharpos()
vnoremap <expr> <F3> SaveVisualStartCharPos()
let g:VisualStartPos = []
exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
call assert_equal([[0, 2, 7, 0], [0, 2, 9, 0], [0, 2, 5, 0]], g:VisualStartPos)
call assert_equal([[0, 2, 7, 0], [0, 2, 10, 0], [0, 2, 5, 0]], g:VisualStartPos)
call assert_equal([0, 2, 9, 0], getcharpos('v'))
let g:VisualStartPos = []
exe "normal 3Gv$\<F3>o\<F3>"
call assert_equal([[0, 3, 1, 0], [0, 3, 1, 0]], g:VisualStartPos)
call assert_equal([[0, 3, 1, 0], [0, 3, 2, 0]], g:VisualStartPos)
let g:VisualStartPos = []
exe "normal 1Gv$\<F3>o\<F3>"
call assert_equal([[0, 1, 1, 0], [0, 1, 1, 0]], g:VisualStartPos)
vunmap <F3>
" Test for getting the position in insert mode with the cursor after the
" last character in a line
inoremap <expr> <F3> SaveInsertCurrentCharPos()
let g:InsertCurrentPos = []
exe "normal 1GA\<F3>"
exe "normal 2GA\<F3>"
exe "normal 3GA\<F3>"
exe "normal 4GA\<F3>"
exe "normal 2G6li\<F3>"
call assert_equal([[0, 1, 1, 0], [0, 2, 10, 0], [0, 3, 2, 0], [0, 4, 10, 0],
\ [0, 2, 7, 0]], g:InsertCurrentPos)
iunmap <F3>
%bw!
endfunc
@@ -192,6 +215,10 @@ func Test_setcharpos()
call setcharpos("'m", [0, 2, 9, 0])
normal `m
call assert_equal([2, 11], [line('.'), col('.')])
" unload the buffer and try to set the mark
let bnr = bufnr()
enew!
call assert_equal(-1, setcharpos("'m", [bnr, 2, 2, 0]))
%bw!
call assert_equal(-1, setcharpos('.', [10, 3, 1, 0]))
@@ -202,6 +229,11 @@ func SaveVisualStartCharCol()
return ''
endfunc
func SaveInsertCurrentCharCol()
call add(g:InsertCurrentCol, charcol('.'))
return ''
endfunc
" Test for the charcol() function
func Test_charcol()
call assert_fails('call charcol({})', 'E731:')
@@ -239,19 +271,36 @@ func Test_charcol()
vnoremap <expr> <F3> SaveVisualStartCharCol()
let g:VisualStartCol = []
exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
call assert_equal([7, 9, 5], g:VisualStartCol)
call assert_equal([7, 10, 5], g:VisualStartCol)
call assert_equal(9, charcol('v'))
let g:VisualStartCol = []
exe "normal 3Gv$\<F3>o\<F3>"
call assert_equal([1, 1], g:VisualStartCol)
call assert_equal([1, 2], g:VisualStartCol)
let g:VisualStartCol = []
exe "normal 1Gv$\<F3>o\<F3>"
call assert_equal([1, 1], g:VisualStartCol)
vunmap <F3>
" Test for getting the column number in insert mode with the cursor after
" the last character in a line
inoremap <expr> <F3> SaveInsertCurrentCharCol()
let g:InsertCurrentCol = []
exe "normal 1GA\<F3>"
exe "normal 2GA\<F3>"
exe "normal 3GA\<F3>"
exe "normal 4GA\<F3>"
exe "normal 2G6li\<F3>"
call assert_equal([1, 10, 2, 10, 7], g:InsertCurrentCol)
iunmap <F3>
%bw!
endfunc
func SaveInsertCursorCharPos()
call add(g:InsertCursorPos, getcursorcharpos('.'))
return ''
endfunc
" Test for getcursorcharpos()
func Test_getcursorcharpos()
call assert_equal(getcursorcharpos(), getcursorcharpos(0))
@@ -269,6 +318,19 @@ func Test_getcursorcharpos()
normal 4G9l
call assert_equal([0, 4, 9, 0, 9], getcursorcharpos())
" Test for getting the cursor position in insert mode with the cursor after
" the last character in a line
inoremap <expr> <F3> SaveInsertCursorCharPos()
let g:InsertCursorPos = []
exe "normal 1GA\<F3>"
exe "normal 2GA\<F3>"
exe "normal 3GA\<F3>"
exe "normal 4GA\<F3>"
exe "normal 2G6li\<F3>"
call assert_equal([[0, 1, 1, 0, 1], [0, 2, 10, 0, 15], [0, 3, 2, 0, 2],
\ [0, 4, 10, 0, 10], [0, 2, 7, 0, 12]], g:InsertCursorPos)
iunmap <F3>
let winid = win_getid()
normal 2G5l
wincmd w
+2
View File
@@ -89,6 +89,8 @@ func Test_win_execute()
call win_gotoid(thiswin)
let line = win_execute(otherwin, 'echo getline(1)')
call assert_match('the new window', line)
let line = win_execute(134343, 'echo getline(1)')
call assert_equal('', line)
if has('popupwin')
let popupwin = popup_create('the popup win', {'line': 2, 'col': 3})
+32 -1
View File
@@ -348,7 +348,7 @@ let s:filename_checks = {
\ 'pamconf': ['/etc/pam.conf', '/etc/pam.d/file', 'any/etc/pam.conf', 'any/etc/pam.d/file'],
\ 'pamenv': ['/etc/security/pam_env.conf', '/home/user/.pam_environment', '.pam_environment', 'pam_env.conf'],
\ 'papp': ['file.papp', 'file.pxml', 'file.pxsl'],
\ 'pascal': ['file.pas', 'file.pp', 'file.dpr', 'file.lpr'],
\ 'pascal': ['file.pas', 'file.dpr', 'file.lpr'],
\ 'passwd': ['any/etc/passwd', 'any/etc/passwd-', 'any/etc/passwd.edit', 'any/etc/shadow', 'any/etc/shadow-', 'any/etc/shadow.edit', 'any/var/backups/passwd.bak', 'any/var/backups/shadow.bak', '/etc/passwd', '/etc/passwd-', '/etc/passwd.edit', '/etc/shadow', '/etc/shadow-', '/etc/shadow.edit', '/var/backups/passwd.bak', '/var/backups/shadow.bak'],
\ 'pbtxt': ['file.pbtxt'],
\ 'pccts': ['file.g'],
@@ -384,6 +384,7 @@ let s:filename_checks = {
\ 'proto': ['file.proto'],
\ 'protocols': ['/etc/protocols', 'any/etc/protocols'],
\ 'psf': ['file.psf'],
\ 'puppet': ['file.pp'],
\ 'pyrex': ['file.pyx', 'file.pxd'],
\ 'python': ['file.py', 'file.pyw', '.pythonstartup', '.pythonrc', 'file.ptl', 'file.pyi', 'SConstruct'],
\ 'quake': ['anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg', 'baseq2/file.cfg', 'id1/file.cfg', 'quake1/file.cfg', 'some-baseq2/file.cfg', 'some-id1/file.cfg', 'some-quake1/file.cfg'],
@@ -444,6 +445,7 @@ let s:filename_checks = {
\ 'smith': ['file.smt', 'file.smith'],
\ 'sml': ['file.sml'],
\ 'snobol4': ['file.sno', 'file.spt'],
\ 'sparql': ['file.rq', 'file.sparql'],
\ 'spec': ['file.spec'],
\ 'spice': ['file.sp', 'file.spice'],
\ 'spup': ['file.speedup', 'file.spdata', 'file.spd'],
@@ -636,6 +638,7 @@ let s:script_checks = {
\ 'cpp': [['// Standard iostream objects -*- C++ -*-'],
\ ['// -*- C++ -*-']],
\ 'yaml': [['%YAML 1.2']],
\ 'pascal': [['#!/path/instantfpc']],
\ }
" Various forms of "env" optional arguments.
@@ -730,5 +733,33 @@ func Test_ts_file()
filetype off
endfunc
func Test_pp_file()
filetype on
call writefile(['looks like puppet'], 'Xfile.pp')
split Xfile.pp
call assert_equal('puppet', &filetype)
bwipe!
let g:filetype_pp = 'pascal'
split Xfile.pp
call assert_equal('pascal', &filetype)
bwipe!
" Test dist#ft#FTpp()
call writefile(['{ pascal comment'], 'Xfile.pp')
split Xfile.pp
call assert_equal('pascal', &filetype)
bwipe!
call writefile(['procedure pascal'], 'Xfile.pp')
split Xfile.pp
call assert_equal('pascal', &filetype)
bwipe!
call delete('Xfile.pp')
filetype off
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+12
View File
@@ -864,6 +864,18 @@ func Test_listdict_extend()
call assert_fails("call extend(g:, {'-!' : 10})", 'E461:')
endfunc
func Test_listdict_extendnew()
" Test extendnew() with lists
let l = [1, 2, 3]
call assert_equal([1, 2, 3, 4, 5], extendnew(l, [4, 5]))
call assert_equal([1, 2, 3], l)
" Test extend() with dictionaries.
let d = {'a': {'b': 'B'}}
call assert_equal({'a': {'b': 'B'}, 'c': 'cc'}, extendnew(d, {'c': 'cc'}))
call assert_equal({'a': {'b': 'B'}}, d)
endfunc
func s:check_scope_dict(x, fixed)
func s:gen_cmd(cmd, x)
return substitute(a:cmd, '\<x\ze:', a:x, 'g')
+26
View File
@@ -0,0 +1,26 @@
" Test for sleep and sleep! commands
func! s:get_time_ms()
let timestr = reltimestr(reltime())
let dotidx = stridx(timestr, '.')
let sec = str2nr(timestr[:dotidx])
let msec = str2nr(timestr[dotidx + 1:])
return (sec * 1000) + (msec / 1000)
endfunc
func! s:assert_takes_longer(cmd, time_ms)
let start = s:get_time_ms()
execute a:cmd
let end = s:get_time_ms()
call assert_true(end - start >=# a:time_ms)
endfun
func! Test_sleep_bang()
call s:assert_takes_longer('sleep 50m', 50)
call s:assert_takes_longer('sleep! 50m', 50)
call s:assert_takes_longer('sl 50m', 50)
call s:assert_takes_longer('sl! 50m', 50)
call s:assert_takes_longer('1sleep', 1000)
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+76
View File
@@ -1004,4 +1004,80 @@ func Test_too_many_edit_args()
call assert_match('^Too many edit arguments: "-"', l[1])
endfunc
" Test starting vim with various names: vim, ex, view, evim, etc.
func Test_progname()
CheckUnix
call mkdir('Xprogname', 'p')
call writefile(['silent !date',
\ 'call writefile([mode(1), '
\ .. '&insertmode, &diff, &readonly, &updatecount, '
\ .. 'join(split(execute("message"), "\n")[1:])], "Xprogname_out")',
\ 'qall'], 'Xprogname_after')
" +---------------------------------------------- progname
" | +--------------------------------- mode(1)
" | | +--------------------------- &insertmode
" | | | +---------------------- &diff
" | | | | +----------------- &readonly
" | | | | | +-------- &updatecount
" | | | | | | +--- :messages
" | | | | | | |
let expectations = {
\ 'vim': ['n', '0', '0', '0', '200', ''],
\ 'gvim': ['n', '0', '0', '0', '200', ''],
\ 'ex': ['ce', '0', '0', '0', '200', ''],
\ 'exim': ['cv', '0', '0', '0', '200', ''],
\ 'view': ['n', '0', '0', '1', '10000', ''],
\ 'gview': ['n', '0', '0', '1', '10000', ''],
\ 'evim': ['n', '1', '0', '0', '200', ''],
\ 'eview': ['n', '1', '0', '1', '10000', ''],
\ 'rvim': ['n', '0', '0', '0', '200', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
\ 'rgvim': ['n', '0', '0', '0', '200', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
\ 'rview': ['n', '0', '0', '1', '10000', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
\ 'rgview': ['n', '0', '0', '1', '10000', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
\ 'vimdiff': ['n', '0', '1', '0', '200', ''],
\ 'gvimdiff': ['n', '0', '1', '0', '200', '']}
let prognames = ['vim', 'gvim', 'ex', 'exim', 'view', 'gview',
\ 'evim', 'eview', 'rvim', 'rgvim', 'rview', 'rgview',
\ 'vimdiff', 'gvimdiff']
for progname in prognames
if empty($DISPLAY)
if progname =~# 'g'
" Can't run gvim, gview (etc.) if $DISPLAY is not setup.
continue
endif
if has('gui') && (progname ==# 'evim' || progname ==# 'eview')
" evim or eview will start the GUI if there is gui support.
" So don't try to start them either if $DISPLAY is not setup.
continue
endif
endif
exe 'silent !ln -s -f ' ..exepath(GetVimProg()) .. ' Xprogname/' .. progname
let stdout_stderr = ''
if progname =~# 'g'
let stdout_stderr = system('Xprogname/'..progname..' -f --clean --not-a-term -S Xprogname_after')
else
exe 'sil !Xprogname/'..progname..' -f --clean --not-a-term -S Xprogname_after'
endif
if progname =~# 'g' && !has('gui')
call assert_equal("E25: GUI cannot be used: Not enabled at compile time\n", stdout_stderr, progname)
else
call assert_equal('', stdout_stderr, progname)
call assert_equal(expectations[progname], readfile('Xprogname_out'), progname)
endif
call delete('Xprogname/' .. progname)
call delete('Xprogname_out')
endfor
call delete('Xprogname_after')
call delete('Xprogname', 'd')
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+17 -1
View File
@@ -1225,6 +1225,12 @@ def Test_var_declaration()
g:dict_val = s:dict[key]
enddef
GetDictVal('a')
final adict: dict<string> = {}
def ChangeAdict()
adict.foo = 'foo'
enddef
ChangeAdict()
END
CheckScriptSuccess(lines)
assert_equal('', g:var_uninit)
@@ -1260,6 +1266,16 @@ def Test_var_declaration_fails()
CheckScriptFailure(lines, 'E741:')
unlet g:constvar
lines =<< trim END
vim9script
const cdict: dict<string> = {}
def Change()
cdict.foo = 'foo'
enddef
defcompile
END
CheckScriptFailure(lines, 'E46:')
lines =<< trim END
vim9script
final w:finalvar = [9]
@@ -1335,7 +1351,7 @@ def Test_var_list_dict_type()
var ll: list<number>
ll = [1, 2, 3]->map('"one"')
END
CheckDefExecFailure(lines, 'E1012: Type mismatch; expected list<number> but got list<string>')
CheckDefExecFailure(lines, 'E1012: Type mismatch; expected number but got string')
enddef
def Test_cannot_use_let()
+116 -21
View File
@@ -241,6 +241,19 @@ def Test_extend_arg_types()
CheckDefFailure(['extend({a: 1}, 42)'], 'E1013: Argument 2: type mismatch, expected dict<number> but got number')
CheckDefFailure(['extend({a: 1}, {b: "x"})'], 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>')
CheckDefFailure(['extend({a: 1}, {b: 2}, 1)'], 'E1013: Argument 3: type mismatch, expected string but got number')
CheckDefFailure(['extend([1], ["b"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>')
CheckDefExecFailure(['extend([1], ["b", 1])'], 'E1012: Type mismatch; expected list<number> but got list<any>')
enddef
def Test_extendnew()
assert_equal([1, 2, 'a'], extendnew([1, 2], ['a']))
assert_equal({one: 1, two: 'a'}, extendnew({one: 1}, {two: 'a'}))
CheckDefFailure(['extendnew({a: 1}, 42)'], 'E1013: Argument 2: type mismatch, expected dict<number> but got number')
CheckDefFailure(['extendnew({a: 1}, [42])'], 'E1013: Argument 2: type mismatch, expected dict<number> but got list<number>')
CheckDefFailure(['extendnew([1, 2], "x")'], 'E1013: Argument 2: type mismatch, expected list<number> but got string')
CheckDefFailure(['extendnew([1, 2], {x: 1})'], 'E1013: Argument 2: type mismatch, expected list<number> but got dict<number>')
enddef
def Test_extend_return_type()
@@ -304,31 +317,20 @@ def Test_extend_list_item_type()
CheckScriptFailure(['vim9script'] + lines, 'E1012:', 1)
enddef
def Test_job_info_return_type()
if has('job')
job_start(&shell)
var jobs = job_info()
assert_equal('list<job>', typename(jobs))
assert_equal('dict<any>', typename(job_info(jobs[0])))
job_stop(jobs[0])
endif
enddef
def Wrong_dict_key_type(items: list<number>): list<number>
return filter(items, (_, val) => get({[val]: 1}, 'x'))
enddef
def Test_map_function_arg()
var lines =<< trim END
def MapOne(i: number, v: string): string
return i .. ':' .. v
enddef
var l = ['a', 'b', 'c']
map(l, MapOne)
assert_equal(['0:a', '1:b', '2:c'], l)
END
CheckDefAndScriptSuccess(lines)
enddef
def Test_map_item_type()
var lines =<< trim END
var l = ['a', 'b', 'c']
map(l, (k, v) => k .. '/' .. v )
assert_equal(['0/a', '1/b', '2/c'], l)
END
CheckDefAndScriptSuccess(lines)
enddef
def Test_filereadable()
assert_false(filereadable(""))
assert_false(filereadable(test_null_string()))
@@ -561,6 +563,45 @@ def SID(): number
->str2nr()
enddef
def Test_map_function_arg()
var lines =<< trim END
def MapOne(i: number, v: string): string
return i .. ':' .. v
enddef
var l = ['a', 'b', 'c']
map(l, MapOne)
assert_equal(['0:a', '1:b', '2:c'], l)
END
CheckDefAndScriptSuccess(lines)
enddef
def Test_map_item_type()
var lines =<< trim END
var l = ['a', 'b', 'c']
map(l, (k, v) => k .. '/' .. v )
assert_equal(['0/a', '1/b', '2/c'], l)
END
CheckDefAndScriptSuccess(lines)
lines =<< trim END
var l: list<number> = [0]
echo map(l, (_, v) => [])
END
CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got list<unknown>', 2)
lines =<< trim END
var l: list<number> = range(2)
echo map(l, (_, v) => [])
END
CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got list<unknown>', 2)
lines =<< trim END
var d: dict<number> = {key: 0}
echo map(d, (_, v) => [])
END
CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got list<unknown>', 2)
enddef
def Test_maparg()
var lnum = str2nr(expand('<sflnum>'))
map foo bar
@@ -603,6 +644,32 @@ def Test_readdir()
eval expand('sautest')->readdirex((e) => e.name[0] !=# '.')
enddef
def Test_readblob()
var blob = 0z12341234
writefile(blob, 'Xreadblob')
var read: blob = readblob('Xreadblob')
assert_equal(blob, read)
var lines =<< trim END
var read: list<string> = readblob('Xreadblob')
END
CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected list<string> but got blob', 1)
delete('Xreadblob')
enddef
def Test_readfile()
var text = ['aaa', 'bbb', 'ccc']
writefile(text, 'Xreadfile')
var read: list<string> = readfile('Xreadfile')
assert_equal(text, read)
var lines =<< trim END
var read: dict<string> = readfile('Xreadfile')
END
CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected dict<string> but got list<string>', 1)
delete('Xreadfile')
enddef
def Test_remove_return_type()
var l = remove({one: [1, 2], two: [3, 4]}, 'one')
var res = 0
@@ -695,6 +762,29 @@ def Test_setreg()
getreginfo('a')->assert_equal(reginfo)
enddef
def Test_slice()
assert_equal('12345', slice('012345', 1))
assert_equal('123', slice('012345', 1, 4))
assert_equal('1234', slice('012345', 1, -1))
assert_equal('1', slice('012345', 1, -4))
assert_equal('', slice('012345', 1, -5))
assert_equal('', slice('012345', 1, -6))
assert_equal([1, 2, 3, 4, 5], slice(range(6), 1))
assert_equal([1, 2, 3], slice(range(6), 1, 4))
assert_equal([1, 2, 3, 4], slice(range(6), 1, -1))
assert_equal([1], slice(range(6), 1, -4))
assert_equal([], slice(range(6), 1, -5))
assert_equal([], slice(range(6), 1, -6))
assert_equal(0z1122334455, slice(0z001122334455, 1))
assert_equal(0z112233, slice(0z001122334455, 1, 4))
assert_equal(0z11223344, slice(0z001122334455, 1, -1))
assert_equal(0z11, slice(0z001122334455, 1, -4))
assert_equal(0z, slice(0z001122334455, 1, -5))
assert_equal(0z, slice(0z001122334455, 1, -6))
enddef
def Test_spellsuggest()
if !has('spell')
MissingFeature 'spell'
@@ -780,6 +870,11 @@ def Test_timer_paused()
timer_stop(id)
enddef
def Test_win_execute()
assert_equal("\n" .. winnr(), win_execute(win_getid(), 'echo winnr()'))
assert_equal('', win_execute(342343, 'echo winnr()'))
enddef
def Test_win_splitmove()
split
win_splitmove(1, 2, {vertical: true, rightbelow: true})
+10
View File
@@ -736,6 +736,9 @@ def Test_put_command()
assert_equal('above', getline(3))
assert_equal('below', getline(4))
:2put =['a', 'b', 'c']
assert_equal(['ppp', 'a', 'b', 'c', 'above'], getline(2, 6))
# compute range at runtime
setline(1, range(1, 8))
@a = 'aaa'
@@ -921,4 +924,11 @@ def Test_wincmd()
close
enddef
def Test_windo_missing_endif()
var lines =<< trim END
windo if 1
END
CheckDefExecFailure(lines, 'E171:', 1)
enddef
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
+15
View File
@@ -1842,4 +1842,19 @@ def Test_silent()
res)
enddef
def s:SilentReturn(): string
silent return "done"
enddef
def Test_silent_return()
var res = execute('disass s:SilentReturn')
assert_match('<SNR>\d*_SilentReturn\_s*' ..
'silent return "done"\_s*' ..
'\d CMDMOD silent\_s*' ..
'\d PUSHS "done"\_s*' ..
'\d CMDMOD_REV\_s*' ..
'\d RETURN',
res)
enddef
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
+20 -12
View File
@@ -2523,18 +2523,26 @@ enddef
def Test_expr7_parens()
# (expr)
assert_equal(4, (6 * 4) / 6)
assert_equal(0, 6 * ( 4 / 6 ))
assert_equal(6, +6)
assert_equal(-6, -6)
assert_equal(false, !-3)
assert_equal(true, !+0)
enddef
def Test_expr7_parens_vim9script()
var lines =<< trim END
vim9script
assert_equal(4, (6 * 4) / 6)
assert_equal(0, 6 * ( 4 / 6 ))
assert_equal(6, +6)
assert_equal(-6, -6)
assert_equal(false, !-3)
assert_equal(true, !+0)
assert_equal(7, 5 + (
2))
assert_equal(7, 5 + (
2
))
assert_equal(7, 5 + ( # comment
2))
assert_equal(7, 5 + ( # comment
# comment
2))
var s = (
'one'
..
@@ -2542,7 +2550,7 @@ def Test_expr7_parens_vim9script()
)
assert_equal('onetwo', s)
END
CheckScriptSuccess(lines)
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_negate_add()
+23
View File
@@ -197,6 +197,17 @@ def Test_return_nothing()
s:nothing->assert_equal(1)
enddef
def Test_return_invalid()
var lines =<< trim END
vim9script
def Func(): invalid
return xxx
enddef
defcompile
END
CheckScriptFailure(lines, 'E1010:', 2)
enddef
func Increment()
let g:counter += 1
endfunc
@@ -1800,6 +1811,18 @@ enddef
def Test_line_continuation_in_lambda()
Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A'])
var lines =<< trim END
vim9script
var res = [{n: 1, m: 2, s: 'xxx'}]
->mapnew((_, v: dict<any>): string => printf('%d:%d:%s',
v.n,
v.m,
substitute(v.s, '.*', 'yyy', '')
))
assert_equal(['1:2:yyy'], res)
END
CheckScriptSuccess(lines)
enddef
def Test_list_lambda()
+22 -3
View File
@@ -324,7 +324,7 @@ func g:NoSuchFunc()
echo 'none'
endfunc
def Test_try_catch()
def Test_try_catch_throw()
var l = []
try # comment
add(l, '1')
@@ -558,6 +558,25 @@ def Test_try_catch()
assert_equal(411, n)
enddef
def Test_throw_skipped()
if 0
throw dontgethere
endif
enddef
def Test_nocatch_throw_silenced()
var lines =<< trim END
vim9script
def Func()
throw 'error'
enddef
silent! Func()
END
writefile(lines, 'XthrowSilenced')
source XthrowSilenced
delete('XthrowSilenced')
enddef
def DeletedFunc(): list<any>
return ['delete me']
enddef
@@ -1238,7 +1257,7 @@ def Test_vim9script_reload_noclear()
assert_equal(3, g:loadCount)
assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values())
delete('Xreloaded')
delete('XReloaded')
delete('XExportReload')
delfunc g:Values
unlet g:loadCount
@@ -2966,7 +2985,7 @@ def Test_vim9_autoload_error()
invalid
endfu
try
invalid
alsoinvalid
catch /wontmatch/
endtry
END
+8
View File
@@ -6600,6 +6600,14 @@ func Test_type()
call ChangeYourMind()
endfunc
func Test_typename()
call assert_equal('number', typename(123))
call assert_equal('string', typename('x'))
call assert_equal('list<number>', typename([123]))
call assert_equal('dict<number>', typename(#{key: 123}))
call assert_equal('list<dict<number>>', typename([#{key: 123}]))
endfunc
"-------------------------------------------------------------------------------
" Test 92: skipping code {{{1
"-------------------------------------------------------------------------------
-2
View File
@@ -1124,7 +1124,6 @@ check_row(int row)
return row;
}
#if defined(FEAT_GUI) || defined(MSWIN) || defined(PROTO)
/*
* Called when focus changed. Used for the GUI or for systems where this can
* be done in the console (Win32).
@@ -1187,7 +1186,6 @@ ui_focus_change(
maketitle();
#endif
}
#endif
#if defined(HAVE_INPUT_METHOD) || defined(PROTO)
/*
+22 -6
View File
@@ -539,7 +539,8 @@ get_lambda_tv(
char_u *start, *end;
int *old_eval_lavars = eval_lavars_used;
int eval_lavars = FALSE;
char_u *tofree = NULL;
char_u *tofree1 = NULL;
char_u *tofree2 = NULL;
int equal_arrow = **arg == '(';
int white_error = FALSE;
@@ -582,6 +583,13 @@ get_lambda_tv(
}
*arg = s;
// Skipping over linebreaks may make "ret_type" invalid, make a copy.
if (ret_type != NULL)
{
ret_type = vim_strsave(ret_type);
tofree2 = ret_type;
}
// Set up a flag for checking local variables and arguments.
if (evaluate)
eval_lavars_used = &eval_lavars;
@@ -605,7 +613,7 @@ get_lambda_tv(
if (evalarg != NULL)
{
// avoid that the expression gets freed when another line break follows
tofree = evalarg->eval_tofree;
tofree1 = evalarg->eval_tofree;
evalarg->eval_tofree = NULL;
}
@@ -700,9 +708,10 @@ get_lambda_tv(
eval_lavars_used = old_eval_lavars;
if (evalarg != NULL && evalarg->eval_tofree == NULL)
evalarg->eval_tofree = tofree;
evalarg->eval_tofree = tofree1;
else
vim_free(tofree);
vim_free(tofree1);
vim_free(tofree2);
if (types_optional)
ga_clear_strings(&argtypes);
return OK;
@@ -715,9 +724,10 @@ errret:
vim_free(fp);
vim_free(pt);
if (evalarg != NULL && evalarg->eval_tofree == NULL)
evalarg->eval_tofree = tofree;
evalarg->eval_tofree = tofree1;
else
vim_free(tofree);
vim_free(tofree1);
vim_free(tofree2);
eval_lavars_used = old_eval_lavars;
return FAIL;
}
@@ -3886,6 +3896,12 @@ define_function(exarg_T *eap, char_u *name_arg)
{
p = ret_type;
fp->uf_ret_type = parse_type(&p, &fp->uf_type_list, TRUE);
if (fp->uf_ret_type == NULL)
{
fp->uf_ret_type = &t_void;
SOURCING_LNUM = lnum_save;
goto erret;
}
}
SOURCING_LNUM = lnum_save;
}
+78
View File
@@ -765,6 +765,84 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2366,
/**/
2365,
/**/
2364,
/**/
2363,
/**/
2362,
/**/
2361,
/**/
2360,
/**/
2359,
/**/
2358,
/**/
2357,
/**/
2356,
/**/
2355,
/**/
2354,
/**/
2353,
/**/
2352,
/**/
2351,
/**/
2350,
/**/
2349,
/**/
2348,
/**/
2347,
/**/
2346,
/**/
2345,
/**/
2344,
/**/
2343,
/**/
2342,
/**/
2341,
/**/
2340,
/**/
2339,
/**/
2338,
/**/
2337,
/**/
2336,
/**/
2335,
/**/
2334,
/**/
2333,
/**/
2332,
/**/
2331,
/**/
2330,
/**/
2329,
/**/
2328,
/**/
2327,
/**/
+71 -33
View File
@@ -474,8 +474,10 @@ may_generate_2STRING(int offset, cctx_T *cctx)
isn_T *isn;
isntype_T isntype = ISN_2STRING;
garray_T *stack = &cctx->ctx_type_stack;
type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
type_T **type;
RETURN_OK_IF_SKIP(cctx);
type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
switch ((*type)->tt_type)
{
// nothing to be done
@@ -876,11 +878,12 @@ use_typecheck(type_T *actual, type_T *expected)
* If "actual_is_const" is TRUE then the type won't change at runtime, do not
* generate a TYPECHECK.
*/
static int
int
need_type(
type_T *actual,
type_T *expected,
int offset,
int arg_idx,
cctx_T *cctx,
int silent,
int actual_is_const)
@@ -894,7 +897,7 @@ need_type(
return OK;
}
if (check_type(expected, actual, FALSE, 0) == OK)
if (check_type(expected, actual, FALSE, arg_idx) == OK)
return OK;
// If the actual type can be the expected type add a runtime check.
@@ -906,7 +909,7 @@ need_type(
}
if (!silent)
type_mismatch(expected, actual);
arg_type_mismatch(expected, actual, arg_idx);
return FAIL;
}
@@ -929,7 +932,7 @@ bool_on_stack(cctx_T *cctx)
// This requires a runtime type check.
return generate_COND2BOOL(cctx);
return need_type(type, &t_bool, -1, cctx, FALSE, FALSE);
return need_type(type, &t_bool, -1, 0, cctx, FALSE, FALSE);
}
/*
@@ -1611,7 +1614,8 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
{
// Check the types of the arguments.
argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
if (internal_func_check_arg_types(argtypes, func_idx, argcount) == FAIL)
if (internal_func_check_arg_types(argtypes, func_idx, argcount,
cctx) == FAIL)
return FAIL;
if (internal_func_is_map(func_idx))
maptype = *argtypes;
@@ -1654,7 +1658,7 @@ generate_LISTAPPEND(cctx_T *cctx)
list_type = ((type_T **)stack->ga_data)[stack->ga_len - 2];
item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
expected = list_type->tt_member;
if (need_type(item_type, expected, -1, cctx, FALSE, FALSE) == FAIL)
if (need_type(item_type, expected, -1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL;
if (generate_instr(cctx, ISN_LISTAPPEND) == NULL)
@@ -1676,7 +1680,7 @@ generate_BLOBAPPEND(cctx_T *cctx)
// Caller already checked that blob_type is a blob.
item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
if (need_type(item_type, &t_number, -1, cctx, FALSE, FALSE) == FAIL)
if (need_type(item_type, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL;
if (generate_instr(cctx, ISN_BLOBAPPEND) == NULL)
@@ -1731,7 +1735,7 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
else
expected = ufunc->uf_va_type->tt_member;
actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
if (need_type(actual, expected, -argcount + i, cctx,
if (need_type(actual, expected, -argcount + i, 0, cctx,
TRUE, FALSE) == FAIL)
{
arg_type_mismatch(expected, actual, i + 1);
@@ -1848,7 +1852,7 @@ generate_PCALL(
type->tt_argcount - 1]->tt_member;
else
expected = type->tt_args[i];
if (need_type(actual, expected, offset,
if (need_type(actual, expected, offset, 0,
cctx, TRUE, FALSE) == FAIL)
{
arg_type_mismatch(expected, actual, i + 1);
@@ -2053,6 +2057,7 @@ generate_undo_cmdmods(cctx_T *cctx)
{
if (cctx->ctx_has_cmdmod && generate_instr(cctx, ISN_CMDMOD_REV) == NULL)
return FAIL;
cctx->ctx_has_cmdmod = FALSE;
return OK;
}
@@ -2124,11 +2129,30 @@ free_locals(cctx_T *cctx)
ga_clear(&cctx->ctx_locals);
}
/*
* If "check_writable" is ASSIGN_CONST give an error if the variable was
* defined with :final or :const, if "check_writable" is ASSIGN_FINAL give an
* error if the variable was defined with :const.
*/
static int
check_item_writable(svar_T *sv, int check_writable, char_u *name)
{
if ((check_writable == ASSIGN_CONST && sv->sv_const != 0)
|| (check_writable == ASSIGN_FINAL
&& sv->sv_const == ASSIGN_CONST))
{
semsg(_(e_readonlyvar), name);
return FAIL;
}
return OK;
}
/*
* Find "name" in script-local items of script "sid".
* Pass "check_writable" to check_item_writable().
* Returns the index in "sn_var_vals" if found.
* If found but not in "sn_var_vals" returns -1.
* If not found returns -2.
* If not found or the variable is not writable returns -2.
*/
int
get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx)
@@ -2149,8 +2173,8 @@ get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx)
return -2;
idx = sav->sav_var_vals_idx;
sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
if (check_writable && sv->sv_const)
semsg(_(e_readonlyvar), name);
if (check_item_writable(sv, check_writable, name) == FAIL)
return -2;
return idx;
}
@@ -2166,8 +2190,8 @@ get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx)
sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
if (sv->sv_tv == &di->di_tv)
{
if (check_writable && sv->sv_const)
semsg(_(e_readonlyvar), name);
if (check_item_writable(sv, check_writable, name) == FAIL)
return -2;
return idx;
}
}
@@ -2464,7 +2488,7 @@ compile_load_scriptvar(
if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
return FAIL;
si = SCRIPT_ITEM(current_sctx.sc_sid);
idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE, cctx);
idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx);
if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
{
// variable is not in sn_var_vals: old style script.
@@ -3113,7 +3137,7 @@ compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
type_T *keytype = ((type_T **)stack->ga_data)
[stack->ga_len - 1];
if (need_type(keytype, &t_string, -1, cctx,
if (need_type(keytype, &t_string, -1, 0, cctx,
FALSE, FALSE) == FAIL)
return FAIL;
}
@@ -3532,8 +3556,10 @@ compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
int ret;
char_u *p = *arg + 1;
*arg = skipwhite(*arg + 1);
if (may_get_next_line_error(p, arg, cctx) == FAIL)
return FAIL;
if (ppconst->pp_used <= PPSIZE - 10)
{
ret = compile_expr1(arg, cctx, ppconst);
@@ -3784,13 +3810,13 @@ compile_subscript(
vtype = VAR_DICT;
if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB)
{
if (need_type(valtype, &t_number, -1, cctx,
if (need_type(valtype, &t_number, -1, 0, cctx,
FALSE, FALSE) == FAIL)
return FAIL;
if (is_slice)
{
valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2];
if (need_type(valtype, &t_number, -2, cctx,
if (need_type(valtype, &t_number, -2, 0, cctx,
FALSE, FALSE) == FAIL)
return FAIL;
}
@@ -3812,7 +3838,7 @@ compile_subscript(
}
else
{
if (need_type(*typep, &t_dict_any, -2, cctx,
if (need_type(*typep, &t_dict_any, -2, 0, cctx,
FALSE, FALSE) == FAIL)
return FAIL;
*typep = &t_any;
@@ -4211,7 +4237,7 @@ compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
if (check_type(want_type, actual, FALSE, 0) == FAIL)
{
if (need_type(actual, want_type, -1, cctx, FALSE, FALSE) == FAIL)
if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL;
}
}
@@ -4893,7 +4919,7 @@ compile_return(char_u *arg, int check_return_type, cctx_T *cctx)
return NULL;
}
if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
cctx, FALSE, FALSE) == FAIL)
0, cctx, FALSE, FALSE) == FAIL)
return NULL;
}
}
@@ -4912,6 +4938,10 @@ compile_return(char_u *arg, int check_return_type, cctx_T *cctx)
// No argument, return zero.
generate_PUSHNR(cctx, 0);
}
// Undo any command modifiers.
generate_undo_cmdmods(cctx);
if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
return NULL;
@@ -5473,6 +5503,11 @@ compile_lhs(
lhs->lhs_name = vim_strnsave(var_start, lhs->lhs_varlen);
if (lhs->lhs_name == NULL)
return FAIL;
if (lhs->lhs_dest_end > var_start + lhs->lhs_varlen)
// Something follows after the variable: "var[idx]" or "var.key".
lhs->lhs_has_index = TRUE;
if (heredoc)
lhs->lhs_type = &t_list_string;
else
@@ -5574,9 +5609,11 @@ compile_lhs(
lhs->lhs_scriptvar_sid = import->imp_sid;
if (SCRIPT_ID_VALID(lhs->lhs_scriptvar_sid))
{
// Check writable only when no index follows.
lhs->lhs_scriptvar_idx = get_script_item_idx(
lhs->lhs_scriptvar_sid,
rawname, TRUE, cctx);
lhs->lhs_scriptvar_sid, rawname,
lhs->lhs_has_index ? ASSIGN_FINAL : ASSIGN_CONST,
cctx);
if (lhs->lhs_scriptvar_idx >= 0)
{
scriptitem_T *si = SCRIPT_ITEM(
@@ -5663,7 +5700,7 @@ compile_lhs(
}
lhs->lhs_member_type = lhs->lhs_type;
if (lhs->lhs_dest_end > var_start + lhs->lhs_varlen)
if (lhs->lhs_has_index)
{
// Something follows after the variable: "var[idx]" or "var.key".
// TODO: should we also handle "->func()" here?
@@ -5698,7 +5735,6 @@ compile_lhs(
lhs->lhs_type = &t_any;
}
lhs->lhs_has_index = TRUE;
if (lhs->lhs_type->tt_member == NULL)
lhs->lhs_member_type = &t_any;
else
@@ -5797,7 +5833,7 @@ compile_assign_unlet(
: ((type_T **)stack->ga_data)[stack->ga_len - 1];
// now we can properly check the type
if (lhs->lhs_type->tt_member != NULL && rhs_type != &t_void
&& need_type(rhs_type, lhs->lhs_type->tt_member, -2, cctx,
&& need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx,
FALSE, FALSE) == FAIL)
return FAIL;
}
@@ -5942,7 +5978,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
emsg(_(e_cannot_use_void_value));
goto theend;
}
if (need_type(stacktype, &t_list_any, -1, cctx,
if (need_type(stacktype, &t_list_any, -1, 0, cctx,
FALSE, FALSE) == FAIL)
goto theend;
// TODO: check the length of a constant list here
@@ -6089,13 +6125,13 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
// without operator check type here, otherwise below
if (lhs.lhs_has_index)
use_type = lhs.lhs_member_type;
if (need_type(rhs_type, use_type, -1, cctx,
if (need_type(rhs_type, use_type, -1, 0, cctx,
FALSE, is_const) == FAIL)
goto theend;
}
}
else if (*p != '=' && need_type(rhs_type, lhs.lhs_member_type,
-1, cctx, FALSE, FALSE) == FAIL)
-1, 0, cctx, FALSE, FALSE) == FAIL)
goto theend;
}
else if (cmdidx == CMD_final)
@@ -6182,7 +6218,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
// If variable is float operation with number is OK.
!(expected == &t_float && stacktype == &t_number) &&
#endif
need_type(stacktype, expected, -1, cctx,
need_type(stacktype, expected, -1, 0, cctx,
FALSE, FALSE) == FAIL)
goto theend;
@@ -6891,7 +6927,7 @@ compile_for(char_u *arg_start, cctx_T *cctx)
// Now that we know the type of "var", check that it is a list, now or at
// runtime.
vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
if (need_type(vartype, &t_list_any, -1, cctx, FALSE, FALSE) == FAIL)
if (need_type(vartype, &t_list_any, -1, 0, cctx, FALSE, FALSE) == FAIL)
{
drop_scope(cctx);
return NULL;
@@ -7461,6 +7497,8 @@ compile_throw(char_u *arg, cctx_T *cctx UNUSED)
if (compile_expr0(&p, cctx) == FAIL)
return NULL;
if (cctx->ctx_skip == SKIP_YES)
return p;
if (may_generate_2STRING(-1, cctx) == FAIL)
return NULL;
if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
+34 -13
View File
@@ -754,7 +754,7 @@ call_partial(typval_T *tv, int argcount_arg, ectx_T *ectx)
int argcount = argcount_arg;
char_u *name = NULL;
int called_emsg_before = called_emsg;
int res;
int res = FAIL;
if (tv->v_type == VAR_PARTIAL)
{
@@ -800,7 +800,7 @@ call_partial(typval_T *tv, int argcount_arg, ectx_T *ectx)
vim_free(tofree);
}
if (name == NULL || res == FAIL)
if (res == FAIL)
{
if (called_emsg == called_emsg_before)
semsg(_(e_unknownfunc),
@@ -965,10 +965,11 @@ char_idx2byte(char_u *str, size_t str_len, varnumber_T idx)
/*
* Return the slice "str[first:last]" using character indexes.
* "exclusive" is TRUE for slice().
* Return NULL when the result is empty.
*/
char_u *
string_slice(char_u *str, varnumber_T first, varnumber_T last)
string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive)
{
long start_byte, end_byte;
size_t slen;
@@ -979,12 +980,12 @@ string_slice(char_u *str, varnumber_T first, varnumber_T last)
start_byte = char_idx2byte(str, slen, first);
if (start_byte < 0)
start_byte = 0; // first index very negative: use zero
if (last == -1)
if ((last == -1 && !exclusive) || last == VARNUM_MAX)
end_byte = (long)slen;
else
{
end_byte = char_idx2byte(str, slen, last);
if (end_byte >= 0 && end_byte < (long)slen)
if (!exclusive && end_byte >= 0 && end_byte < (long)slen)
// end index is inclusive
end_byte += MB_CPTR2LEN(str + end_byte);
}
@@ -1382,9 +1383,18 @@ call_def_function(
// execute Ex command line
case ISN_EXEC:
{
source_cookie_T cookie;
SOURCING_LNUM = iptr->isn_lnum;
do_cmdline_cmd(iptr->isn_arg.string);
if (did_emsg)
// Pass getsourceline to get an error for a missing ":end"
// command.
CLEAR_FIELD(cookie);
cookie.sourcing_lnum = iptr->isn_lnum - 1;
if (do_cmdline(iptr->isn_arg.string,
getsourceline, &cookie,
DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED)
== FAIL
|| did_emsg)
goto on_error;
}
break;
@@ -2595,6 +2605,17 @@ call_def_function(
break;
case ISN_THROW:
if (ectx.ec_trystack.ga_len == 0 && trylevel == 0
&& emsg_silent)
{
// throwing an exception while using "silent!" causes the
// function to abort but not display an error.
tv = STACK_TV_BOT(-1);
clear_tv(tv);
tv->v_type = VAR_NUMBER;
tv->vval.v_number = 0;
goto done;
}
--ectx.ec_stack.ga_len;
tv = STACK_TV_BOT(0);
if (tv->vval.v_string == NULL
@@ -2983,7 +3004,7 @@ call_def_function(
tv = STACK_TV_BOT(-1);
if (is_slice)
// Slice: Select the characters from the string
res = string_slice(tv->vval.v_string, n1, n2);
res = string_slice(tv->vval.v_string, n1, n2, FALSE);
else
// Index: The resulting variable is a string of a
// single character. If the index is too big or
@@ -3021,8 +3042,8 @@ call_def_function(
ectx.ec_stack.ga_len -= is_slice ? 2 : 1;
tv = STACK_TV_BOT(-1);
SOURCING_LNUM = iptr->isn_lnum;
if (list_slice_or_index(list, is_slice, n1, n2, tv, TRUE)
== FAIL)
if (list_slice_or_index(list, is_slice, n1, n2, FALSE,
tv, TRUE) == FAIL)
goto on_error;
}
break;
@@ -3043,8 +3064,8 @@ call_def_function(
goto on_error;
var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1);
var2 = is_slice ? STACK_TV_BOT(-1) : NULL;
res = eval_index_inner(tv, is_slice,
var1, var2, NULL, -1, TRUE);
res = eval_index_inner(tv, is_slice, var1, var2,
FALSE, NULL, -1, TRUE);
clear_tv(var1);
if (is_slice)
clear_tv(var2);
@@ -3336,7 +3357,7 @@ call_def_function(
expr = tv->vval.v_string;
else
{
expr = typval_tostring(tv); // allocates value
expr = typval2string(tv, TRUE); // allocates value
clear_tv(tv);
}
--ectx.ec_stack.ga_len;
+11 -4
View File
@@ -257,7 +257,7 @@ find_exported(
// find name in "script"
// TODO: also find script-local user function
idx = get_script_item_idx(sid, name, FALSE, cctx);
idx = get_script_item_idx(sid, name, 0, cctx);
if (idx >= 0)
{
sv = ((svar_T *)script->sn_var_vals.ga_data) + idx;
@@ -661,10 +661,16 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg)
* with a hashtable) and sn_var_vals (lookup by index).
* When "create" is TRUE this is a new variable, otherwise find and update an
* existing variable.
* "flags" can have ASSIGN_FINAL or ASSIGN_CONST.
* When "*type" is NULL use "tv" for the type and update "*type".
*/
void
update_vim9_script_var(int create, dictitem_T *di, typval_T *tv, type_T **type)
update_vim9_script_var(
int create,
dictitem_T *di,
int flags,
typval_T *tv,
type_T **type)
{
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
hashitem_T *hi;
@@ -686,7 +692,8 @@ update_vim9_script_var(int create, dictitem_T *di, typval_T *tv, type_T **type)
return;
sv->sv_tv = &di->di_tv;
sv->sv_const = (di->di_flags & DI_FLAGS_LOCK) ? ASSIGN_CONST : 0;
sv->sv_const = (flags & ASSIGN_FINAL) ? ASSIGN_FINAL
: (flags & ASSIGN_CONST) ? ASSIGN_CONST : 0;
sv->sv_export = is_export;
newsav->sav_var_vals_idx = si->sn_var_vals.ga_len;
++si->sn_var_vals.ga_len;
@@ -864,7 +871,7 @@ check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
if (sv != NULL)
{
if (sv->sv_const)
if (sv->sv_const != 0)
{
semsg(_(e_readonlyvar), name);
return FAIL;
+30 -15
View File
@@ -513,26 +513,16 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx)
return ret;
}
/*
* Like check_type() but also allow for a runtime type check. E.g. "any" can be
* used for "number".
*/
int
check_arg_type(type_T *expected, type_T *actual, int argidx)
{
if (check_type(expected, actual, FALSE, 0) == OK
|| use_typecheck(actual, expected))
return OK;
// TODO: should generate a TYPECHECK instruction.
return check_type(expected, actual, TRUE, argidx);
}
/*
* Check that the arguments of "type" match "argvars[argcount]".
* Return OK/FAIL.
*/
int
check_argument_types(type_T *type, typval_T *argvars, int argcount, char_u *name)
check_argument_types(
type_T *type,
typval_T *argvars,
int argcount,
char_u *name)
{
int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
int i;
@@ -1170,4 +1160,29 @@ type_name(type_T *type, char **tofree)
return name;
}
/*
* "typename(expr)" function
*/
void
f_typename(typval_T *argvars, typval_T *rettv)
{
garray_T type_list;
type_T *type;
char *tofree;
char *name;
rettv->v_type = VAR_STRING;
ga_init2(&type_list, sizeof(type_T *), 10);
type = typval2type(argvars, &type_list);
name = type_name(type, &tofree);
if (tofree != NULL)
rettv->vval.v_string = (char_u *)tofree;
else
{
rettv->vval.v_string = vim_strsave((char_u *)name);
vim_free(tofree);
}
clear_type_list(&type_list);
}
#endif // FEAT_EVAL