mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
Merge remote-tracking branch 'vim/master'
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
coverage:
|
||||
range: "80...100"
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 0.05%
|
||||
@@ -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
|
||||
|
||||
Vendored
+21
-2
@@ -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("$")
|
||||
|
||||
|
||||
@@ -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
@@ -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: >
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:*
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
...
|
||||
|
||||
@@ -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
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -227,4 +227,4 @@ endfunction
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim:sw=2
|
||||
" vim:sw=2
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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,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,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
@@ -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]*$'
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
Vendored
+4
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
/*
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 == ''
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
"-------------------------------------------------------------------------------
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user