Merge remote-tracking branch 'vim/master'

This commit is contained in:
ichizok
2021-03-18 09:07:25 +09:00
83 changed files with 1665 additions and 282 deletions
+2 -1
View File
@@ -13,7 +13,8 @@ SRC_ALL = \
.hgignore \
.lgtm.yml \
.travis.yml \
appveyor.yml \
.appveyor.yml \
.codecov.yml \
ci/appveyor.bat \
ci/build-snd-dummy.sh \
ci/config.mk*.sed \
+13 -5
View File
@@ -1,4 +1,4 @@
*change.txt* For Vim version 8.2. Last change: 2021 Jan 21
*change.txt* For Vim version 8.2. Last change: 2021 Mar 01
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -649,6 +649,8 @@ For other systems the tmpnam() library function is used.
The space between `:substitute` and the 'c', 'g',
'i', 'I' and 'r' flags isn't required, but in scripts
it's a good idea to keep it to avoid confusion.
Also see the two and three letter commands to repeat
:substitute below |:substitute-repeat|.
:[range]~[&][flags] [count] *:~*
Repeat last substitute with same substitute string
@@ -877,20 +879,26 @@ either the first or second pattern in parentheses did not match, so either
*:sge* *:sgi* *:sgI* *:sgl* *:sgn* *:sgp* *:sgr* *:sI* *:si*
*:sic* *:sIc* *:sie* *:sIe* *:sIg* *:sIl* *:sin* *:sIn* *:sIp*
*:sip* *:sIr* *:sir* *:sr* *:src* *:srg* *:sri* *:srI* *:srl*
*:srn* *:srp*
*:srn* *:srp* *:substitute-repeat*
2-letter and 3-letter :substitute commands ~
These commands repeat the previous `:substitute` command with the given flags.
The first letter is always "s", followed by one or two of the possible flag
characters. For example `:sce` works like `:s///ce`. The table lists the
possible combinations, not all flags are possible, because the command is
short for another command.
List of :substitute commands
| c e g i I n p l r
| c :sc :sce :scg :sci :scI :scn :scp :scl ---
| c :sc :sce :scg :sci :scI :scn :scp :scl
| e
| g :sgc :sge :sg :sgi :sgI :sgn :sgp :sgl :sgr
| i :sic :sie --- :si :siI :sin :sip --- :sir
| i :sic :sie :si :siI :sin :sip :sir
| I :sIc :sIe :sIg :sIi :sI :sIn :sIp :sIl :sIr
| n
| p
| l
| r :src --- :srg :sri :srI :srn :srp :srl :sr
| r :src :srg :sri :srI :srn :srp :srl :sr
Exceptions:
:scr is `:scriptnames`
+45 -16
View File
@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.2. Last change: 2021 Feb 10
*eval.txt* For Vim version 8.2. Last change: 2021 Mar 10
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1187,7 +1187,8 @@ byte under the cursor: >
In Vim9 script:
If expr8 is a String this results in a String that contains the expr1'th
single character from expr8. To use byte indexes use |strpart()|.
single character (including any composing characters) from expr8. To use byte
indexes use |strpart()|.
Index zero gives the first byte or character. Careful: text column numbers
start with one!
@@ -1217,8 +1218,9 @@ In legacy Vim script the indexes are byte indexes. This doesn't recognize
multibyte encodings, see |byteidx()| for computing the indexes. If expr8 is
a Number it is first converted to a String.
In Vim9 script the indexes are character indexes. To use byte indexes use
|strpart()|.
In Vim9 script the indexes are character indexes and include composing
characters. To use byte indexes use |strpart()|. To use character indexes
without including composing characters use |strcharpart()|.
The item at index expr1b is included, it is inclusive. For an exclusive index
use the |slice()| function.
@@ -2935,10 +2937,11 @@ str2list({expr} [, {utf8}]) List convert each character of {expr} to
ASCII/UTF8 value
str2nr({expr} [, {base} [, {quoted}]])
Number convert String to Number
strcharpart({str}, {start} [, {len}])
strcharlen({expr}) Number character length of the String {expr}
strcharpart({str}, {start} [, {len} [, {skipcc}]])
String {len} characters of {str} at
character {start}
strchars({expr} [, {skipcc}]) Number character length of the String {expr}
strchars({expr} [, {skipcc}]) Number character count of the String {expr}
strdisplaywidth({expr} [, {col}]) Number display length of the String {expr}
strftime({format} [, {time}]) String format time with a specified format
strgetchar({str}, {index}) Number get char {index} from {str}
@@ -5312,6 +5315,9 @@ getcharpos({expr})
Get the position for {expr}. Same as |getpos()| but the column
number in the returned List is a character index instead of
a byte index.
If |getpos()| returns a very large column number, such as
2147483647, then getcharpos() will return the character index
of the last character.
Example:
With the cursor on '세' in line 5 with text "여보세요": >
@@ -5791,6 +5797,8 @@ getpos({expr}) Get the position for {expr}. For possible values of {expr}
The column number in the returned List is the byte position
within the line. To get the character position in the line,
use |getcharpos()|
The column number can be very large, e.g. 2147483647, in which
case it means "after the end of the line".
This can be used to save and restore the position of a mark: >
let save_a_mark = getpos("'a")
...
@@ -7462,7 +7470,8 @@ matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]])
to be used when fast match additions and deletions are
required, for example to highlight matching parentheses.
The list {pos} can contain one of these items:
{pos} is a list of positions. Each position can be one of
these:
- A number. This whole line will be highlighted. The first
line has number 1.
- A list with one number, e.g., [23]. The whole line with this
@@ -7475,7 +7484,7 @@ matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]])
- A list with three numbers, e.g., [23, 11, 3]. As above, but
the third number gives the length of the highlight in bytes.
The maximum number of positions is 8.
The maximum number of positions in {pos} is 8.
Example: >
:highlight MyGroup ctermbg=green guibg=green
@@ -7484,8 +7493,7 @@ matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]])
:call matchdelete(m)
< Matches added by |matchaddpos()| are returned by
|getmatches()| with an entry "pos1", "pos2", etc., with the
value a list like the {pos} item.
|getmatches()|.
Can also be used as a |method|: >
GetGroup()->matchaddpos([23, 11])
@@ -9925,7 +9933,7 @@ 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|.
|vim9script|. Also, composing characters are not counted.
When {end} is omitted the slice continues to the last item.
When {end} is -1 the last item is omitted.
@@ -10283,23 +10291,44 @@ str2nr({expr} [, {base} [, {quoted}]]) *str2nr()*
Can also be used as a |method|: >
GetText()->str2nr()
strcharpart({src}, {start} [, {len}]) *strcharpart()*
strcharlen({expr}) *strcharlen()*
The result is a Number, which is the number of characters
in String {expr}. Composing characters are ignored.
|strchars()| can count the number of characters, counting
composing characters separately.
Also see |strlen()|, |strdisplaywidth()| and |strwidth()|.
Can also be used as a |method|: >
GetText()->strcharlen()
strcharpart({src}, {start} [, {len} [, {skipcc}]]) *strcharpart()*
Like |strpart()| but using character index and length instead
of byte index and length.
When {skipcc} is omitted or zero, composing characters are
counted separately.
When {skipcc} set to 1, Composing characters are ignored,
similar to |slice()|.
When a character index is used where a character does not
exist it is assumed to be one character. For example: >
exist it is omitted and counted as one character. For
example: >
strcharpart('abc', -1, 2)
< results in 'a'.
Can also be used as a |method|: >
GetText()->strcharpart(5)
strchars({expr} [, {skipcc}]) *strchars()*
The result is a Number, which is the number of characters
in String {expr}.
When {skipcc} is omitted or zero, composing characters are
counted separately.
When {skipcc} set to 1, Composing characters are ignored.
|strcharlen()| always does this.
Also see |strlen()|, |strdisplaywidth()| and |strwidth()|.
{skipcc} is only available after 7.4.755. For backward
@@ -13159,7 +13188,7 @@ text...
Cannot be followed by a comment.
Examples: >
:execute "buffer" nextbuf
:execute "normal" count . "w"
:execute "normal" count .. "w"
<
":execute" can be used to append a command to commands
that don't accept a '|'. Example: >
@@ -13175,8 +13204,8 @@ text...
file names. The |fnameescape()| function can be used
for Vim commands, |shellescape()| for |:!| commands.
Examples: >
:execute "e " . fnameescape(filename)
:execute "!ls " . shellescape(filename, 1)
:execute "e " .. fnameescape(filename)
:execute "!ls " .. shellescape(filename, 1)
<
Note: The executed string may be any command-line, but
starting or ending "if", "while" and "for" does not
+8 -1
View File
@@ -1,4 +1,4 @@
*filetype.txt* For Vim version 8.2. Last change: 2021 Jan 21
*filetype.txt* For Vim version 8.2. Last change: 2021 Mar 11
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -628,6 +628,13 @@ For fish, add to the config file
set -x MANPAGER "vim -M +MANPAGER -"
MARKDOWN *ft-markdown-plugin*
To enable folding use this: >
let g:markdown_folding = 1
<
PDF *ft-pdf-plugin*
Two maps, <C-]> and <C-T>, are provided to simulate a tag stack for navigating
+14
View File
@@ -263,6 +263,20 @@ input. Example: >
endfunc
nnoremap <expr> <F3> <Sid>OpenPopup()
Also, keep in mind that the expression may be evaluated when looking for
typeahead, before the previous command has been executed. For example: >
func StoreColumn()
let g:column = col('.')
return 'x'
endfunc
nnoremap <expr> x StoreColumn()
nmap ! f!x
You will notice that g:column has the value from before executing "fx",
because "z" is evaluated before "fx" is executed.
This can be solved by inserting <Ignore> before the character that is
expression-mapped: >
nmap ! f!<Ignore>x
Be very careful about side effects! The expression is evaluated while
obtaining characters, you may very well make the command dysfunctional.
For this reason the following is blocked:
+3 -3
View File
@@ -677,9 +677,9 @@ Your directory layout would be like this:
opt/fooextra/doc/tags " help tags
This allows for the user to do: >
mkdir ~/.vim/pack/myfoobar
cd ~/.vim/pack/myfoobar
git clone https://github.com/you/foobar.git
mkdir ~/.vim/pack
cd ~/.vim/pack
git clone https://github.com/you/foobar.git myfoobar
Here "myfoobar" is a name that the user can choose, the only condition is that
it differs from other packages.
+18 -2
View File
@@ -1,4 +1,4 @@
*sign.txt* For Vim version 8.2. Last change: 2020 Oct 28
*sign.txt* For Vim version 8.2. Last change: 2021 Mar 07
VIM REFERENCE MANUAL by Gordon Prieur
@@ -146,6 +146,9 @@ See |sign_define()| for the equivalent Vim script function.
texthl={group}
Highlighting group used for the text item.
Example: >
:sign define MySign text=>> texthl=Search linehl=DiffText
<
DELETING A SIGN *:sign-undefine* *E155*
@@ -155,7 +158,9 @@ See |sign_undefine()| for the equivalent Vim script function.
Deletes a previously defined sign. If signs with this {name}
are still placed this will cause trouble.
Example: >
:sign undefine MySign
<
LISTING SIGNS *:sign-list* *E156*
@@ -209,6 +214,10 @@ See |sign_place()| for the equivalent Vim script function.
Same, but use buffer {nr}. If the buffer argument is not
given, place the sign in the current buffer.
Example: >
:sign place 10 line=99 name=sign3
:sign place 10 line=99 name=sign3 buffer=3
<
*E885*
:sign place {id} name={name} file={fname}
Change the placed sign {id} in file {fname} to use the defined
@@ -221,10 +230,17 @@ See |sign_place()| for the equivalent Vim script function.
"priority={prio}" attribute can be used to change the priority
of an existing sign.
Example: >
:sign place 23 name=sign1 file=/path/to/edit.py
<
:sign place {id} name={name} [buffer={nr}]
Same, but use buffer {nr}. If the buffer argument is not
given, use the current buffer.
Example: >
:sign place 23 name=sign1
:sign place 23 name=sign1 buffer=7
<
REMOVING SIGNS *:sign-unplace* *E159*
+4 -4
View File
@@ -1,4 +1,4 @@
*syntax.txt* For Vim version 8.2. Last change: 2021 Jan 21
*syntax.txt* For Vim version 8.2. Last change: 2021 Mar 06
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1741,8 +1741,8 @@ The coloring scheme for tags in the HTML file works as follows.
The <> of opening tags are colored differently than the </> of a closing tag.
This is on purpose! For opening tags the 'Function' color is used, while for
closing tags the 'Type' color is used (See syntax.vim to check how those are
defined for you)
closing tags the 'Identifier' color is used (See syntax.vim to check how those
are defined for you)
Known tag names are colored the same way as statements in C. Unknown tag
names are colored with the same color as the <> or </> respectively which
@@ -4676,7 +4676,7 @@ matches, nextgroup, etc. But there are a few differences:
- A line continuation pattern can be given. It is used to decide which group
of lines need to be searched like they were one line. This means that the
search for a match with the specified items starts in the first of the
consecutive that contain the continuation pattern.
consecutive lines that contain the continuation pattern.
- When using "nextgroup" or "contains", this only works within one line (or
group of continued lines).
- When using a region, it must start and end in the same line (or group of
+2
View File
@@ -3218,6 +3218,7 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX*
:stselect tagsrch.txt /*:stselect*
:su change.txt /*:su*
:substitute change.txt /*:substitute*
:substitute-repeat change.txt /*:substitute-repeat*
:sun windows.txt /*:sun*
:sunhide windows.txt /*:sunhide*
:sunm map.txt /*:sunm*
@@ -6667,6 +6668,7 @@ ft-mail.vim syntax.txt /*ft-mail.vim*
ft-make-syntax syntax.txt /*ft-make-syntax*
ft-man-plugin filetype.txt /*ft-man-plugin*
ft-maple-syntax syntax.txt /*ft-maple-syntax*
ft-markdown-plugin filetype.txt /*ft-markdown-plugin*
ft-masm-syntax syntax.txt /*ft-masm-syntax*
ft-mathematica-syntax syntax.txt /*ft-mathematica-syntax*
ft-matlab-indent indent.txt /*ft-matlab-indent*
+2 -1
View File
@@ -1,4 +1,4 @@
*testing.txt* For Vim version 8.2. Last change: 2020 Dec 12
*testing.txt* For Vim version 8.2. Last change: 2021 Mar 10
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -168,6 +168,7 @@ test_override({name}, {val}) *test_override()*
wait time of up to 3 seconds for messages
term_props reset all terminal properties when the version
string is detected
uptime overrules sysinfo.uptime
ALL clear all overrides ({val} is not used)
"starting" is to be used when a test should behave like
+40 -15
View File
@@ -1,4 +1,4 @@
*todo.txt* For Vim version 8.2. Last change: 2021 Feb 20
*todo.txt* For Vim version 8.2. Last change: 2021 Mar 11
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -39,13 +39,25 @@ browser use: https://github.com/vim/vim/issues/1234
-------------------- Known bugs and current work -----------------------
Vim9 - Make everything work:
- Implement "export {one, two three}".
- Does this work now: Implement using imported items at script level from
"import * as X" in
- import of item that isn't exported: error should mention missing "export"?
- no error for using :import in legacy script?
- Disallow :open ?
- Check: what if 'cpo' is intentionally changed in Vim9 script, does it get
restored at the end?
- 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:
var p = function('NoSuchFunc')
- When indexing a string, should we include composing characters? #6563
string[0] - first character including its composing characters.
string[0 : 0] - same
If you don't want that use strcharpart().
Also, add optional arg to strcharpart() to include composing chars, to
make it consistent with strchars().
Add strcharlen(), like strchars() but like skipcc is always set
- 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
@@ -74,13 +86,11 @@ Vim9 - Make everything work:
- make 0 == 'string' fail on the script level, like inside :def.
- Check that when using a user function name without prefix, it does not find
a global function. Prefixing g: is required.
- Need the equivalent of get_lval() and set_var_lval() to implement assignment
to nested list and dict members.
- Assignment to dict doesn't work:
var ret: dict<string> = #{}
ret[i] = string(i)
- Appending to dict item doesn't work:
var d[i] ..= value
- Appending to dict item doesn't work in a :def function:
var d: dict<string> = {a: 'x'}
d['a'] ..= 'y'
d.a ..= 'y'
Test to be extended: Test_assign_dict_with_op()
- Using ".." at script level doesn't convert arguments to a string.
- Compile replacement of :s command: s/pat/\=expr/
- Compile redir to local variable: var_redir_start().
@@ -89,8 +99,6 @@ Vim9 - Make everything work:
islocked()
- When evaluating constants for script variables, some functions could work:
has('asdf'), len('string')
- 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.
- Make "++nr" work. "++g:count" doesn't work, thinks it is a range.
- Reload: How to make sure type of script function hasn't changed?
@@ -102,6 +110,11 @@ Vim9 - Make everything work:
- give an error for "echo Func()" if Func() does not return anything.
- Using "windo echo expr" does not accept a line break inside "expr" (in a
:def function and at script level in a not executed block). #7681
- "assert_fails()" cannot access local variables. Perhaps add this:
assertfails
... cmd ...
endassertfails /E99:.*cmd/
Similar to try/catch/endtry but without the boilerplate.
Once Vim9 is stable:
- Change the help to prefer Vim9 syntax where appropriate
@@ -184,6 +197,7 @@ Text properties:
- Popup attached to text property stays visible when text is deleted with
"cc". (#7737) "C" works OK. "dd" also files in a buffer with a single
line.
- Auto-indenting may cause highlighting to shift. (#7719)
- "cc" does not call inserted_bytes(). (Axel Forsman, #5763)
- Combining text property with 'cursorline' does not always work (Billie
Cleek, #5533)
@@ -263,7 +277,9 @@ Terminal emulator window:
- When 'encoding' is not utf-8, or the job is using another encoding, setup
conversions.
Valgrind reports memory leaks in test_options
Include patch #6290: recognize shell directory change.
Valgrind reports memory leaks in test_options.
test_arglist func Test_all_not_allowed_from_cmdwin() hangs on MS-Windows.
@@ -277,6 +293,8 @@ Was originally written by Felipe Morales.
Adding "10" to 'spellsuggest' causes spell suggestions to become very slow.
(#4087) Did patch 8.2.2379 help?
Also, z= in German on a long word can take a very long time, but CTRL-C to
interrupt does not work. Where to add ui_breakcheck()?
Remove SPACE_IN_FILENAME ? It is only used for completion.
@@ -288,6 +306,8 @@ with 'termguicolors'. #1740
Patch for blockwise paste reporting changes: #6660.
Patch to make fillchars global-local. (#5206)
Missing filetype test for bashrc, PKGBUILD, etc.
Add an option to not fetch terminal codes in xterm, to avoid flicker when t_Co
@@ -306,6 +326,10 @@ 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)
MS-Windows: when writing undo file the infostreams are copied in
mch_copy_file_attribute(), that seems unnecessary. (#7925)
Add a flag to only copy attributes?
Changing a capturing group to non-capturing changes the result: #7607
:echo matchstr('aaa bbb', '\(.\{-1,}\>\)\|.*')
aaa
@@ -382,6 +406,10 @@ manager. Problem with Motif?
Patch to add :argdedupe. (Nir Lichtman, #6235)
When editing a file with ":edit" the output of :swapname is relative, while
editing it with "vim file" it is absolute. (#355)
Which one should it be?
:map output does not clear the reset of the command line.
(#5623, also see #5962)
@@ -1156,9 +1184,6 @@ timer expires.
Rule to use "^" for statusline does not work if a space is defined with
highlighting for both stl and stlnc. Patch by Ken Hamada (itchyny, 2016 Dec 11)
8 "stl" and "stlnc" in 'fillchars' don't work for multibyte characters.
Patch by Christian Wellenbrock, 2013 Jul 5.
Using CTRL-G_U in InsertCharPre causes trouble for redo. (Israel Chauca
Fuentes, 2017 Feb 12, #1470)
+2 -1
View File
@@ -611,7 +611,8 @@ String manipulation: *string-functions*
stridx() first index of a short string in a long string
strridx() last index of a short string in a long string
strlen() length of a string in bytes
strchars() length of a string in characters
strcharlen() length of a string in characters
strchars() number of characters in a string
strwidth() size of string when displayed
strdisplaywidth() size of string when displayed, deals with tabs
setcellwidths() set character cell width overrides
+2 -2
View File
@@ -1,4 +1,4 @@
*various.txt* For Vim version 8.2. Last change: 2021 Jan 26
*various.txt* For Vim version 8.2. Last change: 2021 Mar 02
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -575,7 +575,7 @@ N *+X11* Unix only: can restore window title |X11|
it in / any non-ID character (see |'isident'|) can be
used, so long as it does not appear in {pat}. Without
the enclosing character the pattern cannot include the
bar character.
bar character. 'ignorecase' is not used.
The pattern is matched against the relevant part of
the output, not necessarily the whole line. Only some
+16 -8
View File
@@ -1,4 +1,4 @@
*vim9.txt* For Vim version 8.2. Last change: 2021 Feb 23
*vim9.txt* For Vim version 8.2. Last change: 2021 Mar 03
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -96,8 +96,8 @@ script and `:def` functions; details are below:
def CallMe(count: number, message: string): bool
- Call functions without `:call`: >
writefile(['done'], 'file.txt')
- You cannot use `:xit`, `:t`, `:k`, `:append`, `:change`, `:insert` or
curly-braces names.
- You cannot use `:xit`, `:t`, `:k`, `:append`, `:change`, `:insert`, `:open`
or curly-braces names.
- A range before a command must be prefixed with a colon: >
:%s/this/that
- Unless mentioned specifically, the highest |scriptversion| is used.
@@ -341,7 +341,8 @@ Functions can be called without `:call`: >
Using `:call` is still possible, but this is discouraged.
A method call without `eval` is possible, so long as the start is an
identifier or can't be an Ex command. Examples: >
identifier or can't be an Ex command. For a function either "(" or "->" must
be following, without a line break. Examples: >
myList->add(123)
g:myList->add(123)
[1, 2, 3]->Process()
@@ -696,8 +697,9 @@ for v:null. When converting a boolean to a string "false" and "true" are
used, not "v:false" and "v:true" like in legacy script. "v:none" is not
changed, it is only used in JSON and has no equivalent in other languages.
Indexing a string with [idx] or [idx : idx] uses character indexes instead of
byte indexes. Example: >
Indexing a string with [idx] or taking a slice with [idx : idx] uses character
indexes instead of byte indexes. Composing characters are included.
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 'á'.
@@ -800,6 +802,8 @@ Patterns are used like 'magic' is set, unless explicitly overruled.
The 'edcompatible' option value is not used.
The 'gdefault' option value is not used.
You may also find this wiki useful. It was written by an early adoptor of
Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
==============================================================================
@@ -843,6 +847,8 @@ THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE
:enddef End of a function defined with `:def`. It should be on
a line by its own.
You may also find this wiki useful. It was written by an early adoptor of
Vim9 script: https://github.com/lacygoill/wiki/blob/master/vim/vim9.md
If the script the function is defined in is Vim9 script, then script-local
variables can be accessed without the "s:" prefix. They must be defined
@@ -1076,7 +1082,9 @@ A side effect of `:vim9script` is that the 'cpoptions' option is set to the
Vim default value, like with: >
:set cpo&vim
One of the effects is that |line-continuation| is always enabled.
The original value of 'cpoptions' is restored at the end of the script.
The original value of 'cpoptions' is restored at the end of the script, while
flags added or removed in the script are also added to or removed from the
original value to get the same effect. The order of flags may change.
*vim9-mix*
There is one way to use both legacy and Vim9 syntax in one script file: >
@@ -1111,7 +1119,7 @@ Exporting an item can be written as: >
export class MyClass ...
As this suggests, only constants, variables, `:def` functions and classes can
be exported. {classes are not implemented yet}
be exported. {not implemented yet: export class}
*E1042*
`:export` can only be used in Vim9 script, at the script level.
+4 -1
View File
@@ -1,7 +1,7 @@
" Vim support file to detect file types
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2021 Jan 21
" Last Change: 2021 Mar 12
" Listen very carefully, I will say this only once
if exists("did_load_filetypes")
@@ -1334,6 +1334,9 @@ au BufNewFile,BufRead *.pml setf promela
au BufNewFile,BufRead *.proto setf proto
au BufNewFile,BufRead *.pbtxt setf pbtxt
" Poke
au BufNewFile,BufRead *.pk setf poke
" Protocols
au BufNewFile,BufRead */etc/protocols setf protocols
+32
View File
@@ -0,0 +1,32 @@
" Vim filetype plugin file
" Language: GNU Poke
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Last Change: 2021 March 11
if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1
let s:cpo_save = &cpo
set cpo&vim
setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
setlocal commentstring=//\ %s
setlocal formatoptions-=t formatoptions+=croql
setlocal include=load
setlocal suffixesadd=.pk
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "Poke Files (*.pk)\t*.pk\n" .
\ "All Files (*.*)\t*.*\n"
endif
let b:undo_ftplugin = "setl fo< com< cms< inc< sua<" .
\ " | unlet! b:browsefilter"
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: nowrap sw=2 sts=2 ts=8
+25 -44
View File
@@ -3,8 +3,9 @@
" Previous Maintainer: Jorge Maldonado Ventura <jorgesumle@freakspot.net>
" Previous Maintainer: Claudio Fleiner <claudio@fleiner.com>
" Repository: https://notabug.org/jorgesumle/vim-html-syntax
" Last Change: 2021 Feb 25
" Last Change: 2021 Mar 02
" Included patch #7900 to fix comments
" Included patch #7916 to fix a few more things
"
" Please check :help html.vim for some comments and a description of the options
@@ -79,26 +80,16 @@ syn keyword htmlArg contained usemap ismap valign value vlink vspace width wrap
syn match htmlArg contained "\<\(http-equiv\|href\|title\)="me=e-1
" aria attributes
syn match htmlArg contained "\<\(aria-activedescendant\|aria-atomic\)\>"
syn match htmlArg contained "\<\(aria-autocomplete\|aria-busy\|aria-checked\)\>"
syn match htmlArg contained "\<\(aria-colcount\|aria-colindex\|aria-colspan\)\>"
syn match htmlArg contained "\<\(aria-controls\|aria-current\)\>"
syn match htmlArg contained "\<\(aria-describedby\|aria-details\)\>"
syn match htmlArg contained "\<\(aria-disabled\|aria-dropeffect\)\>"
syn match htmlArg contained "\<\(aria-errormessage\|aria-expanded\)\>"
syn match htmlArg contained "\<\(aria-flowto\|aria-grabbed\|aria-haspopup\)\>"
syn match htmlArg contained "\<\(aria-hidden\|aria-invalid\)\>"
syn match htmlArg contained "\<\(aria-keyshortcuts\|aria-label\)\>"
syn match htmlArg contained "\<\(aria-labelledby\|aria-level\|aria-live\)\>"
syn match htmlArg contained "\<\(aria-modal\|aria-multiline\)\>"
syn match htmlArg contained "\<\(aria-multiselectable\|aria-orientation\)\>"
syn match htmlArg contained "\<\(aria-owns\|aria-placeholder\|aria-posinset\)\>"
syn match htmlArg contained "\<\(aria-pressed\|aria-readonly\|aria-relevant\)\>"
syn match htmlArg contained "\<\(aria-required\|aria-roledescription\)\>"
syn match htmlArg contained "\<\(aria-rowcount\|aria-rowindex\|aria-rowspan\)\>"
syn match htmlArg contained "\<\(aria-selected\|aria-setsize\|aria-sort\)\>"
syn match htmlArg contained "\<\(aria-valuemax\|aria-valuemin\)\>"
syn match htmlArg contained "\<\(aria-valuenow\|aria-valuetext\)\>"
exe 'syn match htmlArg contained "\<aria-\%(' . join([
\ 'activedescendant', 'atomic', 'autocomplete', 'busy', 'checked', 'colcount',
\ 'colindex', 'colspan', 'controls', 'current', 'describedby', 'details',
\ 'disabled', 'dropeffect', 'errormessage', 'expanded', 'flowto', 'grabbed',
\ 'haspopup', 'hidden', 'invalid', 'keyshortcuts', 'label', 'labelledby', 'level',
\ 'live', 'modal', 'multiline', 'multiselectable', 'orientation', 'owns',
\ 'placeholder', 'posinset', 'pressed', 'readonly', 'relevant', 'required',
\ 'roledescription', 'rowcount', 'rowindex', 'rowspan', 'selected', 'setsize',
\ 'sort', 'valuemax', 'valuemin', 'valuenow', 'valuetext'
\ ], '\|') . '\)\>"'
syn keyword htmlArg contained role
" Netscape extensions
@@ -139,25 +130,19 @@ syn match htmlSpecialChar "&#\=[0-9A-Za-z]\{1,8};"
" Comments (the real ones or the old netscape ones)
if exists("html_wrong_comments")
syn region htmlComment start=+<!--+ end=+--\s*>+ contains=@Spell
syn region htmlComment start=+<!--+ end=+--\s*>+ contains=@Spell
else
" The HTML 5.2 syntax 8.2.4.41-42: bogus comment is parser error; browser skips until next &gt;
" Note: must stand first to get lesser :syn-priority
syn region htmlComment start=+<!+ end=+>+ contains=htmlCommentError
" Normal comment opening <!-- ...>
syn region htmlComment start=+<!--+ end=+>+ contains=htmlCommentPart,@Spell
" Idem 8.2.4.43-44: <!--> and <!---> are parser errors; browser treats as comments
syn match htmlComment "<!---\?>" contains=htmlCommentError
" Idem 8.2.4.51: any number of consecutive dashes within comment is okay; --> closes comment
" Idem 8.2.4.52: closing comment by dash-dash-bang (--!>) is error ignored by parser(!); closes comment
syn region htmlCommentPart contained start=+--+ end=+--!\?>+me=e-1 contains=htmlCommentNested,@htmlPreProc,@Spell
" Idem 8.2.4.49: opening nested comment <!-- is parser error, ignored by browser, except <!--> is all right
syn match htmlCommentNested contained "<!--[^>]"me=e-1
syn match htmlCommentNested contained "<!--->"me=e-3
syn match htmlCommentNested contained "<!---\?!>"me=e-4
syn match htmlCommentError contained "[^><!]"
" The HTML 5.2 syntax 8.2.4.41: bogus comment is parser error; browser skips until next &gt
syn region htmlComment start=+<!+ end=+>+ contains=htmlCommentError keepend
" Idem 8.2.4.42,51: Comment starts with <!-- and ends with -->
" Idem 8.2.4.43,44: Except <!--> and <!---> are parser errors
" Idem 8.2.4.52: dash-dash-bang (--!>) is error ignored by parser, also closes comment
syn region htmlComment matchgroup=htmlComment start=+<!--\%(-\?>\)\@!+ end=+--!\?>+ contains=htmlCommentNested,@htmlPreProc,@Spell keepend
" Idem 8.2.4.49: nested comment is parser error, except <!--> is all right
syn match htmlCommentNested contained "<!-->\@!"
syn match htmlCommentError contained "[^><!]"
endif
syn region htmlComment start=+<!DOCTYPE+ keepend end=+>+
syn region htmlComment start=+<!DOCTYPE+ end=+>+ keepend
" server-parsed commands
syn region htmlPreProc start=+<!--#+ end=+-->+ contains=htmlPreStmt,htmlPreError,htmlPreAttr
@@ -278,7 +263,7 @@ hi def link htmlEndTag Identifier
hi def link htmlArg Type
hi def link htmlTagName htmlStatement
hi def link htmlSpecialTagName Exception
hi def link htmlValue String
hi def link htmlValue String
hi def link htmlSpecialChar Special
if !exists("html_no_rendering")
@@ -322,14 +307,10 @@ hi def link htmlPreProc PreProc
hi def link htmlPreAttr String
hi def link htmlPreProcAttrName PreProc
hi def link htmlPreProcAttrError Error
hi def link htmlSpecial Special
hi def link htmlSpecialChar Special
hi def link htmlString String
hi def link htmlStatement Statement
hi def link htmlComment Comment
hi def link htmlCommentPart Comment
hi def link htmlValue String
hi def link htmlCommentNested htmlCommentError
hi def link htmlCommentNested htmlError
hi def link htmlCommentError htmlError
hi def link htmlTagError htmlError
hi def link htmlEvent javaScript
+151
View File
@@ -0,0 +1,151 @@
" Copyright (C) 2021 Matthew T. Ihlenfield.
"
" This program is free software: you can redistribute it and/or modify
" it under the terms of the GNU General Public License as published by
" the Free Software Foundation, either version 3 of the License, or
" (at your option) any later version.
"
" This program is distributed in the hope that it will be useful,
" but WITHOUT ANY WARRANTY; without even the implied warranty of
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
" GNU General Public License for more details.
"
" You should have received a copy of the GNU General Public License
" along with this program. If not, see <http://www.gnu.org/licenses/>.
"
" Vim syntax file
" Language: Poke
" Maintainer: Matt Ihlenfield <mtihlenfield@protonmail.com>
" Filenames: *.pk
" Latest Revision: 10 March 2021
if exists('b:current_syntax')
finish
endif
" Poke statement
syn keyword pokeStatement assert break continue return
syn keyword pokeStatement type unit fun method nextgroup=pokeFunction skipwhite
syn keyword pokeStatement var nextgroup=pokeVar skipWhite
" Identifiers
syn match pokeVar '\h\w*' display contained
" User defined functions
syn match pokeFunction '\h\w*' display contained
" Poke operators
syn keyword pokeOperator in sizeof as isa unmap
" Conditionals
syn keyword pokeConditional if else where
" Structures, unions, etc...
syn keyword pokeStructure struct union pinned
" Loops
syn keyword pokeRepeat while for
" Imports
syn keyword pokeLoad load
" Exceptions
syn keyword pokeException try catch until raise
" Exception types
syn keyword pokeExceptionType Exception E_generic E_out_of_bounds
syn keyword pokeExceptionType E_eof E_elem E_constraint
syn keyword pokeExceptionType E_conv E_map_bounds E_map
syn keyword pokeExceptionType E_div_by_zero E_no_ios E_no_return
syn keyword pokeExceptionType E_io E_io_flags E_assert E_overflow
" Exception codes
syn keyword pokeExceptionCode EC_generic EC_out_of_bounds
syn keyword pokeExceptionCode EC_eof EC_elem EC_constraint
syn keyword pokeExceptionCode EC_conv EC_map_bounds EC_map
syn keyword pokeExceptionCode EC_div_by_zero EC_no_ios EC_no_return
syn keyword pokeExceptionCode EC_io EC_io_flags EC_assert EC_overflow
" Poke builtin types
syn keyword pokeBuiltinType string void int uint bit nibble
syn keyword pokeBuiltinType byte char ushort short ulong long
syn keyword pokeBuiltinType uint8 uint16 uint32 uint64
syn keyword pokeBuiltinType off64 uoff64 offset
syn keyword pokeBuiltinType Comparator POSIX_Time32 POSIX_Time64
syn keyword pokeBuiltinType big little any
" Poke constants
syn keyword pokeConstant ENDIAN_LITTLE ENDIAN_BIG
syn keyword pokeConstant IOS_F_READ IOS_F_WRITE IOS_F_TRUNCATE IOS_F_CREATE
syn keyword pokeConstant IOS_M_RDONLY IOS_M_WRONLY IOS_M_RDWR
syn keyword pokeConstant load_path NULL OFFSET
" Poke std lib
syn keyword pokeBuiltinFunction print printf catos stoca atoi ltos reverse
syn keyword pokeBuiltinFunction ltrim rtrim strchr qsort crc32 alignto
syn keyword pokeBuiltinFunction open close flush get_ios set_ios iosize
syn keyword pokeBuiltinFunction rand get_endian set_endian strace exit
syn keyword pokeBuiltinFunction getenv
" Formats
" Special chars
syn match pokeSpecial "\\\([nt\\]\|\o\{1,3}\)" display contained
" Chars
syn match pokeChar "'[^']*'" contains=pokeSpecial
" Attributes
syn match pokeAttribute "\h\w*'\h\w"
" Strings
syn region pokeString skip=+\\\\\|\\"+ start=+"+ end=+"+ contains=pokeSpecial
" Integer literals
syn match pokeInteger "\<\d\+_*\d*\([LlHhBbNn]\=[Uu]\=\|[Uu]\=[LlHhBbNn]\=\)\>"
syn match pokeInteger "\<0[Xx]\x\+_*\x*\([LlHhBbNn]\=[Uu]\=\|[Uu]\=[LlHhBbNn]\=\)\>"
syn match pokeInteger "\<0[Oo]\o\+_*\o*\([LlHhBbNn]\=[Uu]\=\|[Uu]\=[LlHhBbNn]\=\)\>"
syn match pokeInteger "\<0[Bb][01]\+_*[01]*\([LlHhBbNn]\=[Uu]\=\|[Uu]\=[LlHhBbNn]\=\)\>"
" Units
syn keyword pokeBuiltinUnit b M B
syn keyword pokeBuiltinUnit Kb KB Mb MB Gb GB
syn keyword pokeBuiltinUnit Kib KiB Mib MiB Gib GiB
" Offsets
syn match pokeOffset "#\h\w*" contains=pokeBuiltinUnit
" Comments
syn keyword pokeCommentTodo TODO FIXME XXX TBD contained
syn match pokeLineComment "\/\/.*" contains=pokeCommentTodo,@Spell extend
syn region pokeComment start="/\*" end="\*/" contains=pokeCommentTodo,@Spell fold extend
" Allow folding of blocks
syn region pokeBlock start="{" end="}" transparent fold
" Highlight groups
hi def link pokeBuiltinFunction Function
hi def link pokeBuiltinType Type
hi def link pokeBuiltinUnit Keyword
hi def link pokeChar Character
hi def link pokeComment Comment
hi def link pokeCommentTodo Todo
hi def link pokeConditional Conditional
hi def link pokeConstant Constant
hi def link pokeException Exception
hi def link pokeExceptionCode Constant
hi def link pokeExceptionType Type
hi def link pokeFunction Function
hi def link pokeInteger Number
hi def link pokeLineComment Comment
hi def link pokeLoad Include
hi def link pokeOffset StorageClass
hi def link pokeOperator Operator
hi def link pokeSpecial SpecialChar
hi def link pokeStatement Statement
hi def link pokeString String
hi def link pokeStructure Structure
hi def link pokeRepeat Repeat
hi def link pokeVar Identifier
let b:current_syntax = 'poke'
+7 -3
View File
@@ -60,8 +60,8 @@ To built Vim on Ubuntu from scratch on a clean system using git:
% sudo apt install libxt-dev
% make reconfig
Add GUI support (ignore compiler warnings):
% sudo apt install libgtk2.0-dev
Add GUI support:
% sudo apt install libgtk-3-dev
% make reconfig
Add Python 3 support:
@@ -134,8 +134,12 @@ These configure arguments can be used to select which GUI to use:
--disable-motif-check
--disable-athena-check
This configure argument can be used to disable the GUI, even when the necessary
files are found:
--disable-gui
--enable-gui defaults to "auto", so it will automatically look for a GUI (in
the order of GTK, Motif, then Athena). If one is found, then is uses it and
the order of GTK, Motif, then Athena). If one is found, then it is used and
does not proceed to check any of the remaining ones. Otherwise, it moves on
to the next one.
+29
View File
@@ -14148,6 +14148,35 @@ $as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysinfo.uptime" >&5
$as_echo_n "checking for sysinfo.uptime... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/sysinfo.h>
int
main ()
{
struct sysinfo sinfo;
long ut;
(void)sysinfo(&sinfo);
ut = sinfo.uptime;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }; $as_echo "#define HAVE_SYSINFO_UPTIME 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysconf" >&5
$as_echo_n "checking for sysconf... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+16 -4
View File
@@ -1337,7 +1337,7 @@ do_doautocmd(
void
ex_doautoall(exarg_T *eap)
{
int retval;
int retval = OK;
aco_save_T aco;
buf_T *buf;
bufref_T bufref;
@@ -1354,7 +1354,8 @@ ex_doautoall(exarg_T *eap)
*/
FOR_ALL_BUFFERS(buf)
{
if (buf->b_ml.ml_mfp != NULL)
// Only do loaded buffers and skip the current buffer, it's done last.
if (buf->b_ml.ml_mfp != NULL && buf != curbuf)
{
// find a window for this buffer and save some values
aucmd_prepbuf(&aco, buf);
@@ -1364,22 +1365,31 @@ ex_doautoall(exarg_T *eap)
retval = do_doautocmd(arg, FALSE, &did_aucmd);
if (call_do_modelines && did_aucmd)
{
// Execute the modeline settings, but don't set window-local
// options if we are using the current window for another
// buffer.
do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
}
// restore the current window
aucmd_restbuf(&aco);
// stop if there is some error or buffer was deleted
if (retval == FAIL || !bufref_valid(&bufref))
{
retval = FAIL;
break;
}
}
}
// Execute autocommands for the current buffer last.
if (retval == OK)
{
do_doautocmd(arg, FALSE, &did_aucmd);
if (call_do_modelines && did_aucmd)
do_modelines(0);
}
check_cursor(); // just in case lines got deleted
}
@@ -2167,12 +2177,14 @@ apply_autocmds_group(
while (au_pending_free_buf != NULL)
{
buf_T *b = au_pending_free_buf->b_next;
vim_free(au_pending_free_buf);
au_pending_free_buf = b;
}
while (au_pending_free_win != NULL)
{
win_T *w = au_pending_free_win->w_next;
vim_free(au_pending_free_win);
au_pending_free_win = w;
}
+1
View File
@@ -213,6 +213,7 @@
#undef HAVE_SYSCTL
#undef HAVE_SYSINFO
#undef HAVE_SYSINFO_MEM_UNIT
#undef HAVE_SYSINFO_UPTIME
#undef HAVE_TGETENT
#undef HAVE_TOWLOWER
#undef HAVE_TOWUPPER
+14
View File
@@ -4280,6 +4280,20 @@ AC_TRY_COMPILE(
AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSINFO_MEM_UNIT),
AC_MSG_RESULT(no))
dnl struct sysinfo may have the uptime field or not
AC_MSG_CHECKING(for sysinfo.uptime)
AC_TRY_COMPILE(
[#include <sys/types.h>
#include <sys/sysinfo.h>],
[ struct sysinfo sinfo;
long ut;
(void)sysinfo(&sinfo);
ut = sinfo.uptime;
],
AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSINFO_UPTIME),
AC_MSG_RESULT(no))
dnl sysconf() may exist but not support what we want to use
AC_MSG_CHECKING(for sysconf)
AC_TRY_COMPILE(
+1 -1
View File
@@ -1034,7 +1034,7 @@ win_line(
p_extra_free = alloc(MAX_MCO * fdc + 1);
if (p_extra_free != NULL)
{
n_extra = fill_foldcolumn(p_extra_free, wp,
n_extra = (int)fill_foldcolumn(p_extra_free, wp,
FALSE, lnum);
p_extra_free[n_extra] = NUL;
p_extra = p_extra_free;
+2
View File
@@ -373,3 +373,5 @@ EXTERN char e_argument_name_shadows_existing_variable_str[]
INIT(= N_("E1167: Argument name shadows existing variable: %s"));
EXTERN char e_argument_already_declared_in_script_str[]
INIT(= N_("E1168: Argument already declared in the script: %s"));
EXTERN char e_import_as_name_not_supported_here[]
INIT(= N_("E1169: 'import * as {name}' not supported here"));
+60 -2
View File
@@ -1370,7 +1370,7 @@ set_var_lval(
// handle +=, -=, *=, /=, %= and .=
di = NULL;
if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name),
&tv, &di, TRUE, FALSE) == OK)
&tv, &di, EVAL_VAR_VERBOSE) == OK)
{
if ((di == NULL
|| (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
@@ -3500,7 +3500,8 @@ eval7(
ret = OK;
}
else
ret = eval_variable(s, len, rettv, NULL, TRUE, FALSE);
ret = eval_variable(s, len, rettv, NULL,
EVAL_VAR_VERBOSE + EVAL_VAR_IMPORT);
}
else
{
@@ -5760,6 +5761,63 @@ handle_subscript(
check_white = FALSE;
}
if (rettv->v_type == VAR_ANY)
{
char_u *exp_name;
int cc;
int idx;
ufunc_T *ufunc;
type_T *type;
// Found script from "import * as {name}", script item name must
// follow.
if (**arg != '.')
{
if (verbose)
semsg(_(e_expected_str_but_got_str), "'.'", *arg);
ret = FAIL;
break;
}
++*arg;
if (IS_WHITE_OR_NUL(**arg))
{
if (verbose)
emsg(_(e_no_white_space_allowed_after_dot));
ret = FAIL;
break;
}
// isolate the name
exp_name = *arg;
while (eval_isnamec(**arg))
++*arg;
cc = **arg;
**arg = NUL;
idx = find_exported(rettv->vval.v_number, exp_name, &ufunc, &type,
evalarg->eval_cctx, verbose);
**arg = cc;
*arg = skipwhite(*arg);
if (idx < 0 && ufunc == NULL)
{
ret = FAIL;
break;
}
if (idx >= 0)
{
scriptitem_T *si = SCRIPT_ITEM(rettv->vval.v_number);
svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
copy_tv(sv->sv_tv, rettv);
}
else
{
rettv->v_type = VAR_FUNC;
rettv->vval.v_string = vim_strsave(ufunc->uf_name);
}
}
if ((**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
|| rettv->v_type == VAR_PARTIAL))
&& (!check_white || !VIM_ISWHITE(*(*arg - 1))))
+53 -16
View File
@@ -223,6 +223,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv);
#endif
static void f_str2list(typval_T *argvars, typval_T *rettv);
static void f_str2nr(typval_T *argvars, typval_T *rettv);
static void f_strcharlen(typval_T *argvars, typval_T *rettv);
static void f_strchars(typval_T *argvars, typval_T *rettv);
static void f_strgetchar(typval_T *argvars, typval_T *rettv);
static void f_stridx(typval_T *argvars, typval_T *rettv);
@@ -1021,7 +1022,7 @@ static funcentry_T global_functions[] =
{"getcwd", 0, 2, FEARG_1, NULL,
ret_string, f_getcwd},
{"getenv", 1, 1, FEARG_1, NULL,
ret_string, f_getenv},
ret_any, f_getenv},
{"getfontname", 0, 1, 0, NULL,
ret_string, f_getfontname},
{"getfperm", 1, 1, FEARG_1, NULL,
@@ -1572,7 +1573,9 @@ static funcentry_T global_functions[] =
ret_list_number, f_str2list},
{"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool,
ret_number, f_str2nr},
{"strcharpart", 2, 3, FEARG_1, NULL,
{"strcharlen", 1, 1, FEARG_1, NULL,
ret_number, f_strcharlen},
{"strcharpart", 2, 4, FEARG_1, NULL,
ret_string, f_strcharpart},
{"strchars", 1, 2, FEARG_1, NULL,
ret_number, f_strchars},
@@ -9271,31 +9274,45 @@ f_strlen(typval_T *argvars, typval_T *rettv)
tv_get_string(&argvars[0])));
}
static void
strchar_common(typval_T *argvars, typval_T *rettv, int skipcc)
{
char_u *s = tv_get_string(&argvars[0]);
varnumber_T len = 0;
int (*func_mb_ptr2char_adv)(char_u **pp);
func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
while (*s != NUL)
{
func_mb_ptr2char_adv(&s);
++len;
}
rettv->vval.v_number = len;
}
/*
* "strcharlen()" function
*/
static void
f_strcharlen(typval_T *argvars, typval_T *rettv)
{
strchar_common(argvars, rettv, TRUE);
}
/*
* "strchars()" function
*/
static void
f_strchars(typval_T *argvars, typval_T *rettv)
{
char_u *s = tv_get_string(&argvars[0]);
varnumber_T skipcc = FALSE;
varnumber_T len = 0;
int (*func_mb_ptr2char_adv)(char_u **pp);
if (argvars[1].v_type != VAR_UNKNOWN)
skipcc = tv_get_bool(&argvars[1]);
if (skipcc < 0 || skipcc > 1)
semsg(_(e_using_number_as_bool_nr), skipcc);
else
{
func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
while (*s != NUL)
{
func_mb_ptr2char_adv(&s);
++len;
}
rettv->vval.v_number = len;
}
strchar_common(argvars, rettv, skipcc);
}
/*
@@ -9334,6 +9351,7 @@ f_strcharpart(typval_T *argvars, typval_T *rettv)
int nchar;
int nbyte = 0;
int charlen;
int skipcc = FALSE;
int len = 0;
int slen;
int error = FALSE;
@@ -9344,10 +9362,24 @@ f_strcharpart(typval_T *argvars, typval_T *rettv)
nchar = (int)tv_get_number_chk(&argvars[1], &error);
if (!error)
{
if (argvars[2].v_type != VAR_UNKNOWN
&& argvars[3].v_type != VAR_UNKNOWN)
{
skipcc = tv_get_bool(&argvars[3]);
if (skipcc < 0 || skipcc > 1)
{
semsg(_(e_using_number_as_bool_nr), skipcc);
return;
}
}
if (nchar > 0)
while (nchar > 0 && nbyte < slen)
{
nbyte += MB_CPTR2LEN(p + nbyte);
if (skipcc)
nbyte += mb_ptr2len(p + nbyte);
else
nbyte += MB_CPTR2LEN(p + nbyte);
--nchar;
}
else
@@ -9362,7 +9394,12 @@ f_strcharpart(typval_T *argvars, typval_T *rettv)
if (off < 0)
len += 1;
else
len += MB_CPTR2LEN(p + off);
{
if (skipcc)
len += mb_ptr2len(p + off);
else
len += MB_CPTR2LEN(p + off);
}
--charlen;
}
}
+50 -23
View File
@@ -321,7 +321,8 @@ garbage_collect_scriptvars(int copyID)
{
svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
abort = abort || set_ref_in_item(sv->sv_tv, copyID, NULL, NULL);
if (sv->sv_name != NULL)
abort = abort || set_ref_in_item(sv->sv_tv, copyID, NULL, NULL);
}
}
@@ -1220,7 +1221,8 @@ list_arg_vars(exarg_T *eap, char_u *arg, int *first)
arg = skipwhite(arg);
if (tofree != NULL)
name = tofree;
if (eval_variable(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
if (eval_variable(name, len, &tv, NULL,
EVAL_VAR_VERBOSE) == FAIL)
error = TRUE;
else
{
@@ -2540,6 +2542,8 @@ set_cmdarg(exarg_T *eap, char_u *oldarg)
/*
* Get the value of internal variable "name".
* If "flags" has EVAL_VAR_IMPORT may return a VAR_ANY with v_number set to the
* imported script ID.
* Return OK or FAIL. If OK is returned "rettv" must be cleared.
*/
int
@@ -2548,12 +2552,11 @@ eval_variable(
int len, // length of "name"
typval_T *rettv, // NULL when only checking existence
dictitem_T **dip, // non-NULL when typval's dict item is needed
int verbose, // may give error message
int no_autoload) // do not use script autoloading
int flags) // EVAL_VAR_ flags
{
int ret = OK;
typval_T *tv = NULL;
int foundFunc = FALSE;
int found = FALSE;
dictitem_T *v;
int cc;
@@ -2562,7 +2565,7 @@ eval_variable(
name[len] = NUL;
// Check for user-defined variables.
v = find_var(name, NULL, no_autoload);
v = find_var(name, NULL, flags & EVAL_VAR_NOAUTOLOAD);
if (v != NULL)
{
tv = &v->di_tv;
@@ -2582,7 +2585,7 @@ eval_variable(
{
if (import->imp_funcname != NULL)
{
foundFunc = TRUE;
found = TRUE;
if (rettv != NULL)
{
rettv->v_type = VAR_FUNC;
@@ -2591,8 +2594,21 @@ eval_variable(
}
else if (import->imp_flags & IMP_FLAGS_STAR)
{
emsg("Sorry, 'import * as X' not implemented yet");
ret = FAIL;
if ((flags & EVAL_VAR_IMPORT) == 0)
{
if (flags & EVAL_VAR_VERBOSE)
emsg(_(e_import_as_name_not_supported_here));
ret = FAIL;
}
else
{
if (rettv != NULL)
{
rettv->v_type = VAR_ANY;
rettv->vval.v_number = import->imp_sid;
}
found = TRUE;
}
}
else
{
@@ -2608,7 +2624,7 @@ eval_variable(
if (ufunc != NULL)
{
foundFunc = TRUE;
found = TRUE;
if (rettv != NULL)
{
rettv->v_type = VAR_FUNC;
@@ -2618,11 +2634,11 @@ eval_variable(
}
}
if (!foundFunc)
if (!found)
{
if (tv == NULL)
{
if (rettv != NULL && verbose)
if (rettv != NULL && (flags & EVAL_VAR_VERBOSE))
semsg(_(e_undefined_variable_str), name);
ret = FAIL;
}
@@ -2791,12 +2807,15 @@ get_script_local_ht(void)
/*
* Look for "name[len]" in script-local variables and functions.
* When "cmd" is TRUE it must look like a command, a function must be followed
* by "(" or "->".
* Return OK when found, FAIL when not found.
*/
int
lookup_scriptitem(
char_u *name,
size_t len,
int cmd,
cctx_T *dummy UNUSED)
{
hashtab_T *ht = get_script_local_ht();
@@ -2831,19 +2850,26 @@ lookup_scriptitem(
if (p != buffer)
vim_free(p);
// Find a function, so that a following "->" works.
// When used as a command require "(" or "->" to follow, "Cmd" is a user
// command while "Cmd()" is a function call.
if (res != OK)
{
// Find a function, so that a following "->" works. Skip "g:" before a
// function name.
// Do not check for an internal function, since it might also be a
// valid command, such as ":split" versuse "split()".
if (name[0] == 'g' && name[1] == ':')
p = skipwhite(name + len);
if (!cmd || name[len] == '(' || (p[0] == '-' && p[1] == '>'))
{
is_global = TRUE;
fname = name + 2;
// Do not check for an internal function, since it might also be a
// valid command, such as ":split" versus "split()".
// Skip "g:" before a function name.
if (name[0] == 'g' && name[1] == ':')
{
is_global = TRUE;
fname = name + 2;
}
if (find_func(fname, is_global, NULL) != NULL)
res = OK;
}
if (find_func(fname, is_global, NULL) != NULL)
res = OK;
}
return res;
@@ -3274,7 +3300,7 @@ set_var_const(
{
// Item not found, check if a function already exists.
if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
&& lookup_scriptitem(name, STRLEN(name), NULL) == OK)
&& lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == OK)
{
semsg(_(e_redefining_script_item_str), name);
goto failed;
@@ -3696,7 +3722,8 @@ var_exists(char_u *var)
{
if (tofree != NULL)
name = tofree;
n = (eval_variable(name, len, &tv, NULL, FALSE, TRUE) == OK);
n = (eval_variable(name, len, &tv, NULL,
EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT) == OK);
if (n)
{
// handle d.key, l[idx], f(expr)
+7 -3
View File
@@ -3317,7 +3317,7 @@ skip_option_env_lead(char_u *start)
find_ex_command(
exarg_T *eap,
int *full UNUSED,
int (*lookup)(char_u *, size_t, cctx_T *) UNUSED,
int (*lookup)(char_u *, size_t, int cmd, cctx_T *) UNUSED,
cctx_T *cctx UNUSED)
{
int len;
@@ -3436,7 +3436,7 @@ find_ex_command(
|| *eap->cmd == '&'
|| *eap->cmd == '$'
|| *eap->cmd == '@'
|| lookup(eap->cmd, p - eap->cmd, cctx) == OK)
|| lookup(eap->cmd, p - eap->cmd, TRUE, cctx) == OK)
{
eap->cmdidx = CMD_var;
return eap->cmd;
@@ -3455,7 +3455,7 @@ find_ex_command(
// If it is an ID it might be a variable with an operator on the next
// line, if the variable exists it can't be an Ex command.
if (p > eap->cmd && ends_excmd(*skipwhite(p))
&& (lookup(eap->cmd, p - eap->cmd, cctx) == OK
&& (lookup(eap->cmd, p - eap->cmd, TRUE, cctx) == OK
|| (ASCII_ISALPHA(eap->cmd[0]) && eap->cmd[1] == ':')))
{
eap->cmdidx = CMD_eval;
@@ -6615,6 +6615,10 @@ ex_open(exarg_T *eap)
regmatch_T regmatch;
char_u *p;
#ifdef FEAT_EVAL
if (not_in_vim9(eap) == FAIL)
return;
#endif
curwin->w_cursor.lnum = eap->line2;
beginline(BL_SOL | BL_FIX);
if (*eap->arg == '/')
+1
View File
@@ -1865,6 +1865,7 @@ EXTERN int nfa_fail_for_testing INIT(= FALSE);
EXTERN int no_query_mouse_for_testing INIT(= FALSE);
EXTERN int ui_delay_for_testing INIT(= 0);
EXTERN int reset_term_props_on_termresponse INIT(= FALSE);
EXTERN long override_sysinfo_uptime INIT(= -1);
EXTERN int in_free_unref_items INIT(= FALSE);
#endif
+5
View File
@@ -568,6 +568,11 @@ luaV_pushtypval(lua_State *L, typval_T *tv)
case VAR_FUNC:
luaV_pushfuncref(L, tv->vval.v_string);
break;
case VAR_PARTIAL:
// TODO: handle partial arguments
luaV_pushfuncref(L, partial_name(tv->vval.v_partial));
break;
case VAR_BLOB:
luaV_pushblob(L, tv->vval.v_blob);
break;
+3
View File
@@ -3627,8 +3627,11 @@ usage(void)
#endif // FEAT_GUI_X11
#ifdef FEAT_GUI_GTK
mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n"));
main_msg(_("-background <color>\tUse <color> for the background (also: -bg)"));
main_msg(_("-foreground <color>\tUse <color> for normal text (also: -fg)"));
main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
main_msg(_("-iconic\t\tStart Vim iconified"));
main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
main_msg(_("-display <display>\tRun Vim on <display> (also: --display)"));
main_msg(_("--role <role>\tSet a unique role to identify the main window"));
+32 -7
View File
@@ -1080,6 +1080,35 @@ add_b0_fenc(
}
}
#if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO_UPTIME)
# include <sys/sysinfo.h>
#endif
/*
* Return TRUE if the process with number "b0p->b0_pid" is still running.
* "swap_fname" is the name of the swap file, if it's from before a reboot then
* the result is FALSE;
*/
static int
swapfile_process_running(ZERO_BL *b0p, char_u *swap_fname UNUSED)
{
#ifdef HAVE_SYSINFO_UPTIME
stat_T st;
struct sysinfo sinfo;
// If the system rebooted after when the swap file was written then the
// process can't be running now.
if (mch_stat((char *)swap_fname, &st) != -1
&& sysinfo(&sinfo) == 0
&& st.st_mtime < time(NULL) - (
# ifdef FEAT_EVAL
override_sysinfo_uptime >= 0 ? override_sysinfo_uptime :
# endif
sinfo.uptime))
return FALSE;
#endif
return mch_process_running(char_to_long(b0p->b0_pid));
}
/*
* Try to recover curbuf from the .swp file.
@@ -1692,7 +1721,7 @@ ml_recover(int checkext)
msg(_("Recovery completed. Buffer contents equals file contents."));
msg_puts(_("\nYou may want to delete the .swp file now."));
#if defined(UNIX) || defined(MSWIN)
if (mch_process_running(char_to_long(b0p->b0_pid)))
if (swapfile_process_running(b0p, fname_used))
{
// Warn there could be an active Vim on the same file, the user may
// want to kill it.
@@ -2170,7 +2199,7 @@ swapfile_info(char_u *fname)
msg_puts(_("\n process ID: "));
msg_outnum(char_to_long(b0.b0_pid));
#if defined(UNIX) || defined(MSWIN)
if (mch_process_running(char_to_long(b0.b0_pid)))
if (swapfile_process_running(&b0, fname))
{
msg_puts(_(" (STILL RUNNING)"));
# ifdef HAVE_PROCESS_STILL_RUNNING
@@ -2213,9 +2242,6 @@ swapfile_unchanged(char_u *fname)
int fd;
struct block0 b0;
int ret = TRUE;
#if defined(UNIX) || defined(MSWIN)
long pid;
#endif
// must be able to stat the swap file
if (mch_stat((char *)fname, &st) == -1)
@@ -2258,8 +2284,7 @@ swapfile_unchanged(char_u *fname)
}
// process must be known and not be running
pid = char_to_long(b0.b0_pid);
if (pid == 0L || mch_process_running(pid))
if (char_to_long(b0.b0_pid) == 0L || swapfile_process_running(&b0, fname))
ret = FALSE;
#endif
+7 -4
View File
@@ -3247,7 +3247,9 @@ set_bool_option(
if (curwin->w_curswant != MAXCOL
&& (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
curwin->w_set_curswant = TRUE;
check_redraw(options[opt_idx].flags);
if ((opt_flags & OPT_NO_REDRAW) == 0)
check_redraw(options[opt_idx].flags);
return NULL;
}
@@ -3263,8 +3265,8 @@ set_num_option(
long value, // new value
char *errbuf, // buffer for error messages
size_t errbuflen, // length of "errbuf"
int opt_flags) // OPT_LOCAL, OPT_GLOBAL and
// OPT_MODELINE
int opt_flags) // OPT_LOCAL, OPT_GLOBAL,
// OPT_MODELINE, etc.
{
char *errmsg = NULL;
long old_value = *(long *)varp;
@@ -3842,7 +3844,8 @@ set_num_option(
if (curwin->w_curswant != MAXCOL
&& (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
curwin->w_set_curswant = TRUE;
check_redraw(options[opt_idx].flags);
if ((opt_flags & OPT_NO_REDRAW) == 0)
check_redraw(options[opt_idx].flags);
return errmsg;
}
+6 -3
View File
@@ -2480,11 +2480,14 @@ ambw_end:
&& (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0)
curwin->w_set_curswant = TRUE;
if ((opt_flags & OPT_NO_REDRAW) == 0)
{
#ifdef FEAT_GUI
// check redraw when it's not a GUI option or the GUI is active.
if (!redraw_gui_only || gui.in_use)
// check redraw when it's not a GUI option or the GUI is active.
if (!redraw_gui_only || gui.in_use)
#endif
check_redraw(get_option_flags(opt_idx));
check_redraw(get_option_flags(opt_idx));
}
#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
if (did_swaptcap)
+2 -2
View File
@@ -56,12 +56,12 @@ void set_reg_var(int c);
char_u *v_exception(char_u *oldval);
char_u *v_throwpoint(char_u *oldval);
char_u *set_cmdarg(exarg_T *eap, char_u *oldarg);
int eval_variable(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload);
int eval_variable(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int flags);
void check_vars(char_u *name, int len);
dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload);
dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload);
hashtab_T *get_script_local_ht(void);
int lookup_scriptitem(char_u *name, size_t len, cctx_T *dummy);
int lookup_scriptitem(char_u *name, size_t len, int cmd, cctx_T *dummy);
hashtab_T *find_var_ht(char_u *name, char_u **varname);
char_u *get_var_value(char_u *name);
void new_script_vars(scid_T id);
+1 -1
View File
@@ -13,7 +13,7 @@ void undo_cmdmod(cmdmod_T *cmod);
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
int checkforcmd(char_u **pp, char *cmd, int len);
char_u *skip_option_env_lead(char_u *start);
char_u *find_ex_command(exarg_T *eap, int *full, int (*lookup)(char_u *, size_t, cctx_T *), cctx_T *cctx);
char_u *find_ex_command(exarg_T *eap, int *full, int (*lookup)(char_u *, size_t, int cmd, cctx_T *), cctx_T *cctx);
int modifier_len(char_u *cmd);
int cmd_exists(char_u *name);
void f_fullcommand(typval_T *argvars, typval_T *rettv);
+1 -1
View File
@@ -7,7 +7,7 @@ void ex_export(exarg_T *eap);
void free_imports_and_script_vars(int sid);
void mark_imports_for_reload(int sid);
void ex_import(exarg_T *eap);
int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx);
int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx, int verbose);
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, int flags, typval_T *tv, type_T **type);
+28 -1
View File
@@ -1459,7 +1459,34 @@ almosttheend:
si = SCRIPT_ITEM(current_sctx.sc_sid);
if (si->sn_save_cpo != NULL)
{
set_option_value((char_u *)"cpo", 0L, si->sn_save_cpo, 0);
if (STRCMP(p_cpo, CPO_VIM) != 0)
{
char_u *f;
char_u *t;
// 'cpo' was changed in the script. Apply the same change to the
// saved value, if possible.
for (f = (char_u *)CPO_VIM; *f != NUL; ++f)
if (vim_strchr(p_cpo, *f) == NULL
&& (t = vim_strchr(si->sn_save_cpo, *f)) != NULL)
// flag was removed, also remove it from the saved 'cpo'
mch_memmove(t, t + 1, STRLEN(t));
for (f = p_cpo; *f != NUL; ++f)
if (vim_strchr((char_u *)CPO_VIM, *f) == NULL
&& vim_strchr(si->sn_save_cpo, *f) == NULL)
{
// flag was added, also add it to the saved 'cpo'
t = alloc(STRLEN(si->sn_save_cpo) + 2);
if (t != NULL)
{
*t = *f;
STRCPY(t + 1, si->sn_save_cpo);
vim_free(si->sn_save_cpo);
si->sn_save_cpo = t;
}
}
}
set_option_value((char_u *)"cpo", 0L, si->sn_save_cpo, OPT_NO_REDRAW);
VIM_CLEAR(si->sn_save_cpo);
}
+2 -1
View File
@@ -401,11 +401,12 @@ put_view(
{
buf_T *alt = buflist_findnr(wp->w_alt_fnum);
// Set the alternate file.
// Set the alternate file if the buffer is listed.
if ((flagp == &ssop_flags)
&& alt != NULL
&& alt->b_fname != NULL
&& *alt->b_fname != NUL
&& alt->b_p_bl
&& (fputs("balt ", fd) < 0
|| ses_fname(fd, alt, flagp, TRUE) == FAIL))
return FAIL;
+1
View File
@@ -461,6 +461,7 @@ NEW_TESTS_RES = \
test_quickfix.res \
test_quotestar.res \
test_random.res \
test_recover.res \
test_regex_char_classes.res \
test_registers.res \
test_rename.res \
+34 -1
View File
@@ -84,8 +84,16 @@ func CheckUnix()
endif
endfunc
" Command to check for running on Linix
command CheckLinux call CheckLinux()
func CheckLinux()
if !has('linux')
throw 'Skipped: only works on Linux'
endif
endfunc
" Command to check for not running on a BSD system.
" TODO: using this checks should not be needed
" TODO: using this check should not be needed
command CheckNotBSD call CheckNotBSD()
func CheckNotBSD()
if has('bsd')
@@ -191,4 +199,29 @@ func CheckNotAsan()
endif
endfunc
" Command to check for satisfying any of the conditions.
" e.g. CheckAnyOf Feature:bsd Feature:sun Linux
command -nargs=+ CheckAnyOf call CheckAnyOf(<f-args>)
func CheckAnyOf(...)
let excp = []
for arg in a:000
try
exe 'Check' .. substitute(arg, ':', ' ', '')
return
catch /^Skipped:/
let excp += [substitute(v:exception, '^Skipped:\s*', '', '')]
endtry
endfor
throw 'Skipped: ' .. join(excp, '; ')
endfunc
" Command to check for satisfying all of the conditions.
" e.g. CheckAllOf Unix Gui Option:ballooneval
command -nargs=+ CheckAllOf call CheckAllOf(<f-args>)
func CheckAllOf(...)
for arg in a:000
exe 'Check' .. substitute(arg, ':', ' ', '')
endfor
endfunc
" vim: shiftwidth=2 sts=2 expandtab
@@ -0,0 +1,6 @@
|s+0&#ffffff0|o+0&#e0e0e08|m|e| |t|e|x|t| | +0&#ffffff0@64
|~+0#4040ff13&| @73
|~| @73
|~| @73
|~| @73
|:+0#0000000&|'|<|,|'|>> @68
+5
View File
@@ -196,7 +196,12 @@ func RunTheTest(test)
if a:test =~ 'Test_nocatch_'
" Function handles errors itself. This avoids skipping commands after the
" error.
let g:skipped_reason = ''
exe 'call ' . a:test
if g:skipped_reason != ''
call add(s:messages, ' Skipped')
call add(s:skipped, 'SKIPPED ' . a:test . ': ' . g:skipped_reason)
endif
else
try
au VimLeavePre * call EarlyExit(g:testfunc)
-1
View File
@@ -21,7 +21,6 @@ source test_jumps.vim
source test_lispwords.vim
source test_move.vim
source test_put.vim
source test_recover.vim
source test_reltime.vim
source test_scroll_opt.vim
source test_searchpos.vim
+9 -1
View File
@@ -2670,6 +2670,9 @@ func Test_autocmd_window()
%bw!
edit one.txt
tabnew two.txt
vnew three.txt
tabnew four.txt
tabprevious
let g:blist = []
augroup aucmd_win_test1
au!
@@ -2678,7 +2681,12 @@ func Test_autocmd_window()
augroup END
doautoall BufEnter
call assert_equal([['one.txt', 'autocmd'], ['two.txt', '']], g:blist)
call assert_equal([
\ ['one.txt', 'autocmd'],
\ ['two.txt', ''],
\ ['four.txt', 'autocmd'],
\ ['three.txt', ''],
\ ], g:blist)
augroup aucmd_win_test1
au!
+8
View File
@@ -31,6 +31,14 @@ func Test_strcharpart()
call assert_equal('a', strcharpart('àxb', 0, 1))
call assert_equal('̀', strcharpart('àxb', 1, 1))
call assert_equal('x', strcharpart('àxb', 2, 1))
call assert_equal('a', strcharpart('àxb', 0, 1, 0))
call assert_equal('à', strcharpart('àxb', 0, 1, 1))
call assert_equal('x', strcharpart('àxb', 1, 1, 1))
call assert_fails("let v = strcharpart('abc', 0, 0, [])", 'E745:')
call assert_fails("let v = strcharpart('abc', 0, 0, 2)", 'E1023:')
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+9
View File
@@ -33,6 +33,15 @@ func Test_fileformat_autocommand()
bw!
endfunc
func Test_fileformat_nomodifiable()
new
setlocal nomodifiable
call assert_fails('set fileformat=latin1', 'E21:')
bw
endfunc
" Convert the contents of a file into a literal string
func s:file2str(fname)
let b = readfile(a:fname, 'B')
+1
View File
@@ -374,6 +374,7 @@ let s:filename_checks = {
\ 'po': ['file.po', 'file.pot'],
\ 'pod': ['file.pod'],
\ 'pod6': ['file.pod6'],
\ 'poke': ['file.pk'],
\ 'postscr': ['file.ps', 'file.pfa', 'file.afm', 'file.eps', 'file.epsf', 'file.epsi', 'file.ai'],
\ 'pov': ['file.pov'],
\ 'povini': ['.povrayrc'],
+8
View File
@@ -1430,6 +1430,14 @@ func Test_input_func()
delfunc Tcomplete
call assert_equal('item1 item2 item3', c)
" Test for using special characters as default input
call feedkeys(":let c = input('name? ', \"x\<BS>y\")\<CR>\<CR>", 'xt')
call assert_equal('y', c)
" Test for using <CR> as default input
call feedkeys(":let c = input('name? ', \"\\<CR>\")\<CR>x\<CR>", 'xt')
call assert_equal(' x', c)
call assert_fails("call input('F:', '', 'invalid')", 'E180:')
call assert_fails("call input('F:', '', [])", 'E730:')
endfunc
+9
View File
@@ -121,6 +121,15 @@ func Test_lua_eval()
lua v = nil
endfunc
" Test luaeval() with lambda
func Test_luaeval_with_lambda()
lua function hello_luaeval_lambda(a, cb) return a .. cb() end
call assert_equal('helloworld',
\ luaeval('hello_luaeval_lambda(_A[1], _A[2])',
\ ['hello', {->'world'}]))
lua hello_luaeval_lambda = nil
endfunc
" Test vim.window()
func Test_lua_window()
e Xfoo2
+24
View File
@@ -485,6 +485,30 @@ func Test_list_mappings()
nmapclear
endfunc
func Test_expr_map_gets_cursor()
new
call setline(1, ['one', 'some w!rd'])
func StoreColumn()
let g:exprLine = line('.')
let g:exprCol = col('.')
return 'x'
endfunc
nnoremap <expr> x StoreColumn()
2
nmap ! f!<Ignore>x
call feedkeys("!", 'xt')
call assert_equal('some wrd', getline(2))
call assert_equal(2, g:exprLine)
call assert_equal(7, g:exprCol)
bwipe!
unlet g:exprLine
unlet g:exprCol
delfunc StoreColumn
nunmap x
nunmap !
endfunc
func Test_expr_map_restore_cursor()
CheckScreendump
+2 -2
View File
@@ -147,9 +147,9 @@ func Test_memory_func_capture_lvars()
" The usage may be a bit less than the last value, use 80%.
" Allow for 20% tolerance at the upper limit. That's very permissive, but
" otherwise the test fails sometimes. On Cirrus CI with FreeBSD we need to
" be even more permissive.
" be even much more permissive.
if has('bsd')
let multiplier = 15
let multiplier = 19
else
let multiplier = 12
endif
+11
View File
@@ -259,6 +259,17 @@ func Test_message_more()
call term_sendkeys(buf, 'q')
call WaitForAssert({-> assert_equal('100', term_getline(buf, 5))})
" Execute a : command from the more prompt
call term_sendkeys(buf, ":%p#\n")
call term_wait(buf)
call WaitForAssert({-> assert_equal('-- More --', term_getline(buf, 6))})
call term_sendkeys(buf, ":")
call term_wait(buf)
call WaitForAssert({-> assert_equal(':', term_getline(buf, 6))})
call term_sendkeys(buf, "echo 'Hello'\n")
call term_wait(buf)
call WaitForAssert({-> assert_equal('Hello ', term_getline(buf, 5))})
call StopVimInTerminal(buf)
endfunc
+14
View File
@@ -544,6 +544,20 @@ func Test_mkview_no_balt()
%bwipe
endfunc
func Test_mksession_no_balt()
edit Xtestfile1
edit Xtestfile2
bdelete Xtestfile1
mksession! Xtestview
source Xtestview
call assert_equal(0, buflisted('Xtestfile1'))
call delete('Xtestview')
%bwipe
endfunc
" Test :mkview with a file argument.
func Test_mkview_file()
" Create a view with line number and a fold.
+7
View File
@@ -3207,6 +3207,13 @@ func Test_normal_delete_cmd()
" delete to a readonly register
call setline(1, ['abcd'])
call assert_beeps('normal ":d2l')
" D and d with 'nomodifiable'
call setline(1, ['abcd'])
setlocal nomodifiable
call assert_fails('normal D', 'E21:')
call assert_fails('normal d$', 'E21:')
close!
endfunc
+21
View File
@@ -1038,6 +1038,27 @@ func Test_opt_winminheight_term()
call delete('Xwinminheight')
endfunc
func Test_opt_winminheight_term_tabs()
CheckRunVimInTerminal
" The tabline should be taken into account.
let lines =<< trim END
set wmh=0 stal=2
split
split
split
split
tabnew
END
call writefile(lines, 'Xwinminheight')
let buf = RunVimInTerminal('-S Xwinminheight', #{rows: 11})
call term_sendkeys(buf, ":set wmh=1\n")
call WaitForAssert({-> assert_match('E36: Not enough room', term_getline(buf, 11))})
call StopVimInTerminal(buf)
call delete('Xwinminheight')
endfunc
" Test for the 'winminwidth' option
func Test_opt_winminwidth()
only!
+14
View File
@@ -149,4 +149,18 @@ func Test_xrestore()
bwipe!
endfunc
" Test for 'pastetoggle'
func Test_pastetoggle()
new
set pastetoggle=<F4>
set nopaste
call feedkeys("iHello\<F4>", 'xt')
call assert_true(&paste)
call feedkeys("i\<F4>", 'xt')
call assert_false(&paste)
call assert_equal('Hello', getline(1))
set pastetoggle&
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+75 -9
View File
@@ -1,5 +1,7 @@
" Test :recover
source check.vim
func Test_recover_root_dir()
" This used to access invalid memory.
split Xtest
@@ -21,6 +23,21 @@ func Test_recover_root_dir()
set dir&
endfunc
" Make a copy of the current swap file to "Xswap".
" Return the name of the swap file.
func CopySwapfile()
preserve
" get the name of the swap file
let swname = split(execute("swapname"))[0]
let swname = substitute(swname, '[[:blank:][:cntrl:]]*\(.\{-}\)[[:blank:][:cntrl:]]*$', '\1', '')
" make a copy of the swap file in Xswap
set binary
exe 'sp ' . swname
w! Xswap
set nobinary
return swname
endfunc
" Inserts 10000 lines with text to fill the swap file with two levels of pointer
" blocks. Then recovers from the swap file and checks all text is restored.
"
@@ -37,15 +54,9 @@ func Test_swap_file()
let i += 1
endwhile
$delete
preserve
" get the name of the swap file
let swname = split(execute("swapname"))[0]
let swname = substitute(swname, '[[:blank:][:cntrl:]]*\(.\{-}\)[[:blank:][:cntrl:]]*$', '\1', '')
" make a copy of the swap file in Xswap
set binary
exe 'sp ' . swname
w! Xswap
set nobinary
let swname = CopySwapfile()
new
only!
bwipe! Xtest
@@ -67,4 +78,59 @@ func Test_swap_file()
enew! | only
endfunc
func Test_nocatch_process_still_running()
" sysinfo.uptime probably only works on Linux
if !has('linux')
let g:skipped_reason = 'only works on Linux'
return
endif
" the GUI dialog can't be handled
if has('gui_running')
let g:skipped_reason = 'only works in the terminal'
return
endif
" don't intercept existing swap file here
au! SwapExists
" Edit a file and grab its swapfile.
edit Xswaptest
call setline(1, ['a', 'b', 'c'])
let swname = CopySwapfile()
" Forget we edited this file
new
only!
bwipe! Xswaptest
call rename('Xswap', swname)
call feedkeys('e', 'tL')
redir => editOutput
edit Xswaptest
redir END
call assert_match('E325: ATTENTION', editOutput)
call assert_match('file name: .*Xswaptest', editOutput)
call assert_match('process ID: \d* (STILL RUNNING)', editOutput)
" Forget we edited this file
new
only!
bwipe! Xswaptest
" pretend we rebooted
call test_override("uptime", 0)
sleep 1
call rename('Xswap', swname)
call feedkeys('e', 'tL')
redir => editOutput
edit Xswaptest
redir END
call assert_match('E325: ATTENTION', editOutput)
call assert_notmatch('(STILL RUNNING)', editOutput)
call test_override("ALL", 0)
call delete(swname)
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+10
View File
@@ -709,4 +709,14 @@ func Test_insert_small_delete()
bwipe!
endfunc
" Record in insert mode using CTRL-O
func Test_record_in_insert_mode()
new
let @r = ''
call setline(1, ['foo'])
call feedkeys("i\<C-O>qrbaz\<C-O>q", 'xt')
call assert_equal('baz', @r)
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+4 -1
View File
@@ -165,7 +165,10 @@ func Test_term_mouse_multiple_clicks_to_select_mode()
let save_term = &term
let save_ttymouse = &ttymouse
call test_override('no_query_mouse', 1)
set mouse=a term=xterm mousetime=200
" 'mousetime' must be sufficiently large, or else the test is flaky when
" using a ssh connection with X forwarding; i.e. ssh -X.
set mouse=a term=xterm mousetime=1000
set selectmode=mouse
new
+1
View File
@@ -21,6 +21,7 @@ func! Test_sleep_bang()
call s:assert_takes_longer('sl 50m', 50)
call s:assert_takes_longer('sl! 50m', 50)
call s:assert_takes_longer('1sleep', 1000)
call s:assert_takes_longer('normal 1gs', 1000)
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+145 -14
View File
@@ -109,9 +109,9 @@ func Test_pack_in_rtp_when_plugins_run()
endfunc
func Test_help_arg()
if !has('unix') && has('gui_running')
throw 'Skipped: does not work with gvim on MS-Windows'
endif
" This does not work with a GUI-only binary, such as on MS-Windows.
CheckAnyOf Unix NotGui
if RunVim([], [], '--help >Xtestout')
let lines = readfile('Xtestout')
call assert_true(len(lines) > 20)
@@ -408,6 +408,134 @@ func Test_A_F_H_arg()
call delete('Xtestout')
endfunc
" Test the --echo-wid argument (for GTK GUI only).
func Test_echo_wid()
CheckCanRunGui
CheckFeature gui_gtk
if RunVim([], [], '-g --echo-wid -cq >Xtest_echo_wid')
let lines = readfile('Xtest_echo_wid')
call assert_equal(1, len(lines))
call assert_match('^WID: \d\+$', lines[0])
endif
call delete('Xtest_echo_wid')
endfunction
" Test the -reverse and +reverse arguments (for GUI only).
func Test_reverse()
CheckCanRunGui
CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena
let after =<< trim [CODE]
call writefile([&background], "Xtest_reverse")
qall
[CODE]
if RunVim([], after, '-f -g -reverse')
let lines = readfile('Xtest_reverse')
call assert_equal(['dark'], lines)
endif
if RunVim([], after, '-f -g +reverse')
let lines = readfile('Xtest_reverse')
call assert_equal(['light'], lines)
endif
call delete('Xtest_reverse')
endfunc
" Test the -background and -foreground arguments (for GUI only).
func Test_background_foreground()
CheckCanRunGui
CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena
" Is there a better way to check the effect of -background & -foreground
" other than merely looking at &background (dark or light)?
let after =<< trim [CODE]
call writefile([&background], "Xtest_fg_bg")
qall
[CODE]
if RunVim([], after, '-f -g -background darkred -foreground yellow')
let lines = readfile('Xtest_fg_bg')
call assert_equal(['dark'], lines)
endif
if RunVim([], after, '-f -g -background ivory -foreground darkgreen')
let lines = readfile('Xtest_fg_bg')
call assert_equal(['light'], lines)
endif
call delete('Xtest_fg_bg')
endfunc
" Test the -font argument (for GUI only).
func Test_font()
CheckCanRunGui
CheckNotMSWindows
if has('gui_gtk')
let font = 'Courier 14'
elseif has('gui_motif') || has('gui_athena')
let font = '-misc-fixed-bold-*'
else
throw 'Skipped: test does not set a valid font for this GUI'
endif
let after =<< trim [CODE]
call writefile([&guifont], "Xtest_font")
qall
[CODE]
if RunVim([], after, '--nofork -g -font "' .. font .. '"')
let lines = readfile('Xtest_font')
call assert_equal([font], lines)
endif
call delete('Xtest_font')
endfunc
" Test the -geometry argument (for GUI only).
func Test_geometry()
CheckCanRunGui
CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena
if has('gui_motif') || has('gui_athena')
" FIXME: With GUI Athena or Motif, the value of getwinposx(),
" getwinposy() and getwinpos() do not match exactly the
" value given in -geometry. Why?
" So only check &columns and &lines for those GUIs.
let after =<< trim [CODE]
call writefile([&columns, &lines], "Xtest_geometry")
qall
[CODE]
if RunVim([], after, '-f -g -geometry 31x13+41+43')
let lines = readfile('Xtest_geometry')
call assert_equal(['31', '13'], lines)
endif
else
let after =<< trim [CODE]
call writefile([&columns, &lines, getwinposx(), getwinposy(), string(getwinpos())], "Xtest_geometry")
qall
[CODE]
if RunVim([], after, '-f -g -geometry 31x13+41+43')
let lines = readfile('Xtest_geometry')
call assert_equal(['31', '13', '41', '43', '[41, 43]'], lines)
endif
endif
call delete('Xtest_geometry')
endfunc
" Test the -iconic argument (for GUI only).
func Test_iconic()
CheckCanRunGui
CheckAnyOf Feature:gui_gtk Feature:gui_motif Feature:gui_athena
call RunVim([], [], '-f -g -iconic -cq')
" TODO: currently only start vim iconified, but does not
" check that vim is iconified. How could this be checked?
endfunc
func Test_invalid_args()
" must be able to get the output of Vim.
CheckUnix
@@ -1044,16 +1172,11 @@ func Test_progname()
\ '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
let run_with_gui = (progname =~# 'g') || (has('gui') && (progname ==# 'evim' || progname ==# 'eview'))
if empty($DISPLAY) && run_with_gui
" Can't run gvim, gview (etc.) if $DISPLAY is not setup.
continue
endif
exe 'silent !ln -s -f ' ..exepath(GetVimProg()) .. ' Xprogname/' .. progname
@@ -1068,7 +1191,15 @@ func Test_progname()
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)
" GUI motif can output some warnings like this:
" Warning:
" Name: subMenu
" Class: XmCascadeButton
" Illegal mnemonic character; Could not convert X KEYSYM to a keycode
" So don't check that stderr is empty with GUI Motif.
if run_with_gui && !has('gui_motif')
call assert_equal('', stdout_stderr, progname)
endif
call assert_equal(expectations[progname], readfile('Xprogname_out'), progname)
endif
+15
View File
@@ -858,6 +858,21 @@ func Test_mps_latin1()
close!
endfunc
func Test_mps_error()
let encoding_save = &encoding
for e in ['utf-8', 'latin1']
exe 'set encoding=' .. e
call assert_fails('set mps=<:', 'E474:', e)
call assert_fails('set mps=:>', 'E474:', e)
call assert_fails('set mps=<>', 'E474:', e)
call assert_fails('set mps=<:>_', 'E474:', e)
endfor
let &encoding = encoding_save
endfunc
" Test for ra on multi-byte characters
func Test_ra_multibyte()
new
+14
View File
@@ -733,4 +733,18 @@ func Test_undofile_cryptmethod_blowfish2()
set undofile& undolevels& cryptmethod&
endfunc
" Test for redoing with incrementing numbered registers
func Test_redo_repeat_numbered_register()
new
for [i, v] in [[1, 'one'], [2, 'two'], [3, 'three'],
\ [4, 'four'], [5, 'five'], [6, 'six'],
\ [7, 'seven'], [8, 'eight'], [9, 'nine']]
exe 'let @' .. i .. '="' .. v .. '\n"'
endfor
call feedkeys('"1p.........', 'xt')
call assert_equal(['', 'one', 'two', 'three', 'four', 'five', 'six',
\ 'seven', 'eight', 'nine', 'nine'], getline(1, '$'))
bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+8 -1
View File
@@ -11,7 +11,7 @@ func Test_visual_block_insert()
bwipeout!
endfunc
" Test for built-in function strchars()
" Test for built-in functions strchars() and strcharlen()
func Test_strchars()
let inp = ["a", "あいa", "A\u20dd", "A\u20dd\u20dd", "\u20dd"]
let exp = [[1, 1, 1], [3, 3, 3], [2, 2, 1], [3, 3, 1], [1, 1, 1]]
@@ -20,6 +20,13 @@ func Test_strchars()
call assert_equal(exp[i][1], inp[i]->strchars(0))
call assert_equal(exp[i][2], strchars(inp[i], 1))
endfor
let exp = [1, 3, 1, 1, 1]
for i in range(len(inp))
call assert_equal(exp[i], inp[i]->strcharlen())
call assert_equal(exp[i], strcharlen(inp[i]))
endfor
call assert_fails("let v=strchars('abc', [])", 'E745:')
call assert_fails("let v=strchars('abc', 2)", 'E1023:')
endfunc
+7
View File
@@ -72,6 +72,13 @@ def Test_assignment()
CheckDefFailure(['var lambda = () => "lambda"'], 'E704:')
CheckScriptFailure(['var x = "x"'], 'E1124:')
# lower case name is OK for a list
var lambdaLines =<< trim END
var lambdaList: list<func> = [Test_syntax]
lambdaList[0] = () => "lambda"
END
CheckDefAndScriptSuccess(lambdaLines)
var nr: number = 1234
CheckDefFailure(['var nr: number = "asdf"'], 'E1012:')
+33
View File
@@ -340,6 +340,26 @@ def Test_extend_list_item_type()
CheckScriptFailure(['vim9script'] + lines, 'E1012:', 1)
enddef
def Test_extend_with_error_function()
var lines =<< trim END
vim9script
def F()
{
var m = 10
}
echo m
enddef
def Test()
var d: dict<any> = {}
d->extend({A: 10, Func: function('F', [])})
enddef
Test()
END
CheckScriptFailure(lines, 'E1001: Variable not found: m')
enddef
def Test_job_info_return_type()
if has('job')
job_start(&shell)
@@ -472,6 +492,19 @@ def Test_getchar()
getchar(true)->assert_equal(0)
enddef
def Test_getenv()
if getenv('does-not_exist') == ''
assert_report('getenv() should return null')
endif
if getenv('does-not_exist') == null
else
assert_report('getenv() should return null')
endif
$SOMEENVVAR = 'some'
assert_equal('some', getenv('SOMEENVVAR'))
unlet $SOMEENVVAR
enddef
def Test_getcompletion()
set wildignore=*.vim,*~
var l = getcompletion('run', 'file', true)
+30 -5
View File
@@ -364,9 +364,8 @@ def Test_method_call_linebreak()
return F()
enddef
def Test()
Foo
->Bar()
->setline(1)
Foo ->Bar()
->setline(1)
enddef
Test()
assert_equal('the text', getline(1))
@@ -401,8 +400,7 @@ def Test_method_call_linebreak()
return F()
enddef
Foo
->Bar()
Foo->Bar()
->setline(1)
END
CheckScriptSuccess(lines)
@@ -424,6 +422,33 @@ def Test_method_call_whitespace()
CheckDefAndScriptSuccess(lines)
enddef
def Test_method_and_user_command()
var lines =<< trim END
vim9script
def Cmd()
g:didFunc = 1
enddef
command Cmd g:didCmd = 1
Cmd
assert_equal(1, g:didCmd)
Cmd()
assert_equal(1, g:didFunc)
unlet g:didFunc
unlet g:didCmd
def InDefFunc()
Cmd
assert_equal(1, g:didCmd)
Cmd()
assert_equal(1, g:didFunc)
unlet g:didFunc
unlet g:didCmd
enddef
InDefFunc()
END
CheckScriptSuccess(lines)
enddef
def Test_skipped_expr_linebreak()
if 0
var x = []
+2 -2
View File
@@ -947,7 +947,7 @@ def NestedOuter()
enddef
enddef
def Test_nested_func()
def Test_disassemble_nested_func()
var instr = execute('disassemble NestedOuter')
assert_match('NestedOuter\_s*' ..
'def g:Inner()\_s*' ..
@@ -965,7 +965,7 @@ def NestedDefList()
def /Info/
enddef
def Test_nested_def_list()
def Test_disassemble_nested_def_list()
var instr = execute('disassemble NestedDefList')
assert_match('NestedDefList\_s*' ..
'def\_s*' ..
+32
View File
@@ -1370,6 +1370,9 @@ def Test_expr5_list_add()
dany[i] = i
endfor
assert_equal({a: 'a', 12: 12}, dany)
# result of glob() is "any", runtime type check
var sl: list<string> = glob('*.txt', false, true) + ['']
enddef
" test multiply, divide, modulo
@@ -2364,6 +2367,35 @@ def Test_expr7_any_index_slice()
assert_equal('abcd', g:teststring[: -3])
assert_equal('', g:teststring[: -9])
# composing characters are included
g:teststring = 'àéû'
assert_equal('à', g:teststring[0])
assert_equal('é', g:teststring[1])
assert_equal('û', g:teststring[2])
assert_equal('', g:teststring[3])
assert_equal('', g:teststring[4])
assert_equal('û', g:teststring[-1])
assert_equal('é', g:teststring[-2])
assert_equal('à', g:teststring[-3])
assert_equal('', g:teststring[-4])
assert_equal('', g:teststring[-5])
assert_equal('à', g:teststring[0 : 0])
assert_equal('é', g:teststring[1 : 1])
assert_equal('àé', g:teststring[0 : 1])
assert_equal('àéû', g:teststring[0 : -1])
assert_equal('àé', g:teststring[0 : -2])
assert_equal('à', g:teststring[0 : -3])
assert_equal('', g:teststring[0 : -4])
assert_equal('', g:teststring[0 : -5])
assert_equal('àéû', g:teststring[ : ])
assert_equal('àéû', g:teststring[0 : ])
assert_equal('éû', g:teststring[1 : ])
assert_equal('û', g:teststring[2 : ])
assert_equal('', g:teststring[3 : ])
assert_equal('', g:teststring[4 : ])
# blob index cannot be out of range
g:testblob = 0z01ab
assert_equal(0x01, g:testblob[0])
+42 -1
View File
@@ -311,6 +311,14 @@ def Test_call_default_args()
delfunc g:Func
CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: Argument 1: type mismatch, expected number but got string')
delfunc g:Func
var lines =<< trim END
vim9script
def Func(a = b == 0 ? 1 : 2, b = 0)
enddef
defcompile
END
CheckScriptFailure(lines, 'E1001: Variable not found: b')
enddef
def FuncWithComment( # comment
@@ -385,7 +393,6 @@ def Test_nested_function()
CheckDefFailure(lines, 'E1117:')
# nested function inside conditional
# TODO: should it work when "thecount" is inside the "if"?
lines =<< trim END
vim9script
var thecount = 0
@@ -403,6 +410,25 @@ def Test_nested_function()
assert_equal(2, Test())
END
CheckScriptSuccess(lines)
# also works when "thecount" is inside the "if" block
lines =<< trim END
vim9script
if true
var thecount = 0
def Test(): number
def TheFunc(): number
thecount += 1
return thecount
enddef
return TheFunc()
enddef
endif
defcompile
assert_equal(1, Test())
assert_equal(2, Test())
END
CheckScriptSuccess(lines)
enddef
def Test_not_nested_function()
@@ -726,11 +752,26 @@ def Test_call_lambda_args()
CheckDefFailure(lines, 'E1167:')
enddef
def FilterWithCond(x: string, Cond: func(string): bool): bool
return Cond(x)
enddef
def Test_lambda_return_type()
var lines =<< trim END
var Ref = (): => 123
END
CheckDefAndScriptFailure(lines, 'E1157:', 1)
# this works
for x in ['foo', 'boo']
echo FilterWithCond(x, (v) => v =~ '^b')
endfor
# this fails
lines =<< trim END
echo FilterWithCond('foo', (v) => v .. '^b')
END
CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected func(string): bool but got func(any): string', 1)
enddef
def Test_lambda_uses_assigned_var()
+126 -5
View File
@@ -5,6 +5,7 @@ source term_util.vim
source view_util.vim
source vim9.vim
source shared.vim
source screendump.vim
def Test_range_only()
new
@@ -591,6 +592,31 @@ def Test_try_catch_throw()
assert_equal(4, ReturnInFinally())
enddef
" :while at the very start of a function that :continue jumps to
def TryContinueFunc()
while g:Count < 2
g:sequence ..= 't'
try
echoerr 'Test'
catch
g:Count += 1
g:sequence ..= 'c'
continue
endtry
g:sequence ..= 'e'
g:Count += 1
endwhile
enddef
def Test_continue_in_try_in_while()
g:Count = 0
g:sequence = ''
TryContinueFunc()
assert_equal('tctc', g:sequence)
unlet g:Count
unlet g:sequence
enddef
def Test_nocatch_return_in_try()
# return in try block returns normally
def ReturnInTry(): string
@@ -1030,13 +1056,17 @@ def Test_vim9_import_export()
vim9script
import * as Export from './Xexport.vim'
def UseExport()
g:imported = Export.exported
g:imported_def = Export.exported
enddef
g:imported_script = Export.exported
assert_equal(1, exists('Export.exported'))
assert_equal(0, exists('Export.notexported'))
UseExport()
END
writefile(import_star_as_lines, 'Ximport.vim')
source Ximport.vim
assert_equal(9883, g:imported)
assert_equal(9883, g:imported_def)
assert_equal(9883, g:imported_script)
var import_star_as_lines_no_dot =<< trim END
vim9script
@@ -1071,6 +1101,22 @@ def Test_vim9_import_export()
writefile(import_star_as_duplicated, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim')
var import_star_as_lines_script_no_dot =<< trim END
vim9script
import * as Export from './Xexport.vim'
g:imported_script = Export exported
END
writefile(import_star_as_lines_script_no_dot, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1029:')
var import_star_as_lines_script_space_after_dot =<< trim END
vim9script
import * as Export from './Xexport.vim'
g:imported_script = Export. exported
END
writefile(import_star_as_lines_script_space_after_dot, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1074:')
var import_star_as_lines_missing_name =<< trim END
vim9script
import * as Export from './Xexport.vim'
@@ -1204,17 +1250,23 @@ def Test_vim9_import_export()
delete('Xexport.vim')
# Check that in a Vim9 script 'cpo' is set to the Vim default.
set cpo&vi
var cpo_before = &cpo
# Flags added or removed are also applied to the restored value.
set cpo=abcd
var lines =<< trim END
vim9script
g:cpo_in_vim9script = &cpo
set cpo+=f
set cpo-=c
g:cpo_after_vim9script = &cpo
END
writefile(lines, 'Xvim9_script')
source Xvim9_script
assert_equal(cpo_before, &cpo)
assert_equal('fabd', &cpo)
set cpo&vim
assert_equal(&cpo, g:cpo_in_vim9script)
var newcpo = substitute(&cpo, 'c', '', '') .. 'f'
assert_equal(newcpo, g:cpo_after_vim9script)
delete('Xvim9_script')
enddef
@@ -1515,6 +1567,35 @@ def Test_script_reload_change_type()
delete('Xreload.vim')
enddef
" Define CallFunc so that the test can be compiled
command CallFunc echo 'nop'
def Test_script_reload_from_function()
var lines =<< trim END
vim9script
if exists('g:loaded')
finish
endif
g:loaded = 1
delcommand CallFunc
command CallFunc Func()
def Func()
so XreloadFunc.vim
g:didTheFunc = 1
enddef
END
writefile(lines, 'XreloadFunc.vim')
source XreloadFunc.vim
CallFunc
assert_equal(1, g:didTheFunc)
delete('XreloadFunc.vim')
delcommand CallFunc
unlet g:loaded
unlet g:didTheFunc
enddef
def Test_script_var_shadows_function()
var lines =<< trim END
vim9script
@@ -1859,6 +1940,8 @@ def Test_no_insert_xit()
CheckScriptFailure(['vim9script', 'c'], 'E1100:')
CheckScriptFailure(['vim9script', 'i = 1'], 'E488:')
CheckScriptFailure(['vim9script', 'i'], 'E1100:')
CheckScriptFailure(['vim9script', 'o = 1'], 'E1100:')
CheckScriptFailure(['vim9script', 'o'], 'E1100:')
CheckScriptFailure(['vim9script', 't'], 'E1100:')
CheckScriptFailure(['vim9script', 't = 1'], 'E1100:')
CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:')
@@ -3154,6 +3237,10 @@ def Test_vim9_autoload()
return 'test'
enddef
g:some#name = 'name'
def some#varargs(a1: string, ...l: list<string>): string
return a1 .. l[0] .. l[1]
enddef
END
mkdir('Xdir/autoload', 'p')
@@ -3166,6 +3253,8 @@ def Test_vim9_autoload()
g:some#other = 'other'
assert_equal('other', g:some#other)
assert_equal('abc', some#varargs('a', 'b', 'c'))
# upper case script name works
lines =<< trim END
vim9script
@@ -3332,6 +3421,38 @@ def Test_restoring_cpo()
set cpo&vim
enddef
" Use :function so we can use Check commands
func Test_no_redraw_when_restoring_cpo()
CheckScreendump
CheckFeature timers
let lines =<< trim END
vim9script
def script#func()
enddef
END
call mkdir('Xdir/autoload', 'p')
call writefile(lines, 'Xdir/autoload/script.vim')
let lines =<< trim END
vim9script
set cpo+=M
exe 'set rtp^=' .. getcwd() .. '/Xdir'
au CmdlineEnter : ++once timer_start(0, () => script#func())
setline(1, 'some text')
END
call writefile(lines, 'XTest_redraw_cpo')
let buf = RunVimInTerminal('-S XTest_redraw_cpo', {'rows': 6})
call term_sendkeys(buf, "V:")
call VerifyScreenDump(buf, 'Test_vim9_no_redraw', {})
" clean up
call term_sendkeys(buf, "\<Esc>u")
call StopVimInTerminal(buf)
call delete('XTest_redraw_cpo')
call delete('Xdir', 'rf')
endfunc
def Test_unset_any_variable()
var lines =<< trim END
+4
View File
@@ -906,6 +906,10 @@ func Test_viminfo_oldfiles_newfile()
call delete('Xviminfofile')
call delete('Xviminfotest')
call delete('Xnew-file.txt')
let v:oldfiles = test_null_list()
call assert_equal("\nNo old files", execute('oldfiles'))
let &viminfo = save_viminfo
let &viminfofile = save_viminfofile
endfunc
+3
View File
@@ -970,6 +970,8 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
ui_delay_for_testing = val;
else if (STRCMP(name, (char_u *)"term_props") == 0)
reset_term_props_on_termresponse = val;
else if (STRCMP(name, (char_u *)"uptime") == 0)
override_sysinfo_uptime = val;
else if (STRCMP(name, (char_u *)"ALL") == 0)
{
disable_char_avail_for_testing = FALSE;
@@ -979,6 +981,7 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
no_query_mouse_for_testing = FALSE;
ui_delay_for_testing = 0;
reset_term_props_on_termresponse = FALSE;
override_sysinfo_uptime = -1;
if (save_starting >= 0)
{
starting = save_starting;
+22 -8
View File
@@ -1359,9 +1359,12 @@ func_remove(ufunc_T *fp)
// function, so we can find the index when defining the function again.
// Do remove it when it's a copy.
if (fp->uf_def_status == UF_COMPILED && (fp->uf_flags & FC_COPY) == 0)
{
fp->uf_flags |= FC_DEAD;
else
hash_remove(&func_hashtab, hi);
return FALSE;
}
hash_remove(&func_hashtab, hi);
fp->uf_flags |= FC_DELETED;
return TRUE;
}
return FALSE;
@@ -2134,11 +2137,23 @@ delete_script_functions(int sid)
int changed = func_hashtab.ht_changed;
fp->uf_flags |= FC_DEAD;
func_clear(fp, TRUE);
// When clearing a function another function can be cleared
// as a side effect. When that happens start over.
if (changed != func_hashtab.ht_changed)
break;
if (fp->uf_calls > 0)
{
// Function is executing, don't free it but do remove
// it from the hashtable.
if (func_remove(fp))
fp->uf_refcount--;
}
else
{
func_clear(fp, TRUE);
// When clearing a function another function can be
// cleared as a side effect. When that happens start
// over.
if (changed != func_hashtab.ht_changed)
break;
}
}
--todo;
}
@@ -4251,7 +4266,6 @@ ex_delfunction(exarg_T *eap)
// do remove it from the hashtable.
if (func_remove(fp))
fp->uf_refcount--;
fp->uf_flags |= FC_DELETED;
}
else
func_clear_free(fp, FALSE);
+86
View File
@@ -765,6 +765,92 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2619,
/**/
2618,
/**/
2617,
/**/
2616,
/**/
2615,
/**/
2614,
/**/
2613,
/**/
2612,
/**/
2611,
/**/
2610,
/**/
2609,
/**/
2608,
/**/
2607,
/**/
2606,
/**/
2605,
/**/
2604,
/**/
2603,
/**/
2602,
/**/
2601,
/**/
2600,
/**/
2599,
/**/
2598,
/**/
2597,
/**/
2596,
/**/
2595,
/**/
2594,
/**/
2593,
/**/
2592,
/**/
2591,
/**/
2590,
/**/
2589,
/**/
2588,
/**/
2587,
/**/
2586,
/**/
2585,
/**/
2584,
/**/
2583,
/**/
2582,
/**/
2581,
/**/
2580,
/**/
2579,
/**/
2578,
/**/
2577,
/**/
2576,
/**/
+6
View File
@@ -1208,6 +1208,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define OPT_WINONLY 0x10 // only set window-local options
#define OPT_NOWIN 0x20 // don't set window-local options
#define OPT_ONECOLUMN 0x40 // list options one per line
#define OPT_NO_REDRAW 0x80 // ignore redraw flags on option
// Magic chars used in confirm dialog strings
#define DLG_BUTTON_SEP '\n'
@@ -2712,4 +2713,9 @@ long elapsed(DWORD start_tick);
#define MCH_DELAY_IGNOREINPUT 1
#define MCH_DELAY_SETTMODE 2
// Flags for eval_variable().
#define EVAL_VAR_VERBOSE 1 // may give error message
#define EVAL_VAR_NOAUTOLOAD 2 // do not use script autoloading
#define EVAL_VAR_IMPORT 4 // may return special variable for import
#endif // VIM__H
+54 -28
View File
@@ -391,19 +391,29 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
* imported or function.
*/
static int
item_exists(char_u *name, size_t len, cctx_T *cctx)
item_exists(char_u *name, size_t len, int cmd UNUSED, cctx_T *cctx)
{
int is_global;
char_u *p;
if (variable_exists(name, len, cctx))
return TRUE;
// Find a function, so that a following "->" works. Skip "g:" before a
// function name.
// Do not check for an internal function, since it might also be a
// valid command, such as ":split" versuse "split()".
is_global = (name[0] == 'g' && name[1] == ':');
return find_func(is_global ? name + 2 : name, is_global, cctx) != NULL;
// This is similar to what is in lookup_scriptitem():
// Find a function, so that a following "->" works.
// Require "(" or "->" to follow, "Cmd" is a user command while "Cmd()" is
// a function call.
p = skipwhite(name + len);
if (name[len] == '(' || (p[0] == '-' && p[1] == '>'))
{
// Do not check for an internal function, since it might also be a
// valid command, such as ":split" versuse "split()".
// Skip "g:" before a function name.
is_global = (name[0] == 'g' && name[1] == ':');
return find_func(is_global ? name + 2 : name, is_global, cctx) != NULL;
}
return FALSE;
}
/*
@@ -2645,7 +2655,8 @@ compile_load_scriptvar(
cc = *p;
*p = NUL;
idx = find_exported(import->imp_sid, exp_name, &ufunc, &type, cctx);
idx = find_exported(import->imp_sid, exp_name, &ufunc, &type,
cctx, TRUE);
*p = cc;
p = skipwhite(p);
@@ -4184,7 +4195,7 @@ compile_expr7(
* "null" constant
*/
case 'n': if (STRNCMP(*arg, "null", 4) == 0
&& !eval_isnamec((*arg)[5]))
&& !eval_isnamec((*arg)[4]))
{
*arg += 4;
rettv->v_type = VAR_SPECIAL;
@@ -4450,7 +4461,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
}
/*
* + number addition
* + number addition or list/blobl concatenation
* - number subtraction
* .. string concatenation
*/
@@ -4532,6 +4543,7 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
else
{
generate_ppconst(cctx, ppconst);
ppconst->pp_is_const = FALSE;
if (*op == '.')
{
if (may_generate_2STRING(-2, cctx) == FAIL
@@ -5171,6 +5183,21 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
r = eap->skip ? OK : FAIL;
goto theend;
}
// copy over the block scope IDs before compiling
if (!is_global && cctx->ctx_ufunc->uf_block_depth > 0)
{
int block_depth = cctx->ctx_ufunc->uf_block_depth;
ufunc->uf_block_ids = ALLOC_MULT(int, block_depth);
if (ufunc->uf_block_ids != NULL)
{
mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids,
sizeof(int) * block_depth);
ufunc->uf_block_depth = block_depth;
}
}
if (func_needs_compiling(ufunc, PROFILING(ufunc))
&& compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx)
== FAIL)
@@ -5197,25 +5224,12 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
// Define a local variable for the function reference.
lvar_T *lvar = reserve_local(cctx, name_start, name_end - name_start,
TRUE, ufunc->uf_func_type);
int block_depth = cctx->ctx_ufunc->uf_block_depth;
if (lvar == NULL)
goto theend;
if (generate_FUNCREF(cctx, ufunc) == FAIL)
goto theend;
r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
// copy over the block scope IDs
if (block_depth > 0)
{
ufunc->uf_block_ids = ALLOC_MULT(int, block_depth);
if (ufunc->uf_block_ids != NULL)
{
mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids,
sizeof(int) * block_depth);
ufunc->uf_block_depth = block_depth;
}
}
}
// TODO: warning for trailing text?
@@ -5818,11 +5832,13 @@ compile_lhs(
return FAIL;
}
// new local variable
// Check the name is valid for a funcref.
if ((lhs->lhs_type->tt_type == VAR_FUNC
|| lhs->lhs_type->tt_type == VAR_PARTIAL)
&& var_wrong_func_name(lhs->lhs_name, TRUE))
&& var_wrong_func_name(lhs->lhs_name, TRUE))
return FAIL;
// New local variable.
lhs->lhs_lvar = reserve_local(cctx, var_start, lhs->lhs_varlen,
cmdidx == CMD_final || cmdidx == CMD_const, lhs->lhs_type);
if (lhs->lhs_lvar == NULL)
@@ -6261,6 +6277,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
{
if ((rhs_type->tt_type == VAR_FUNC
|| rhs_type->tt_type == VAR_PARTIAL)
&& !lhs.lhs_has_index
&& var_wrong_func_name(lhs.lhs_name, TRUE))
goto theend;
@@ -8198,6 +8215,7 @@ compile_def_function(
{
int count = ufunc->uf_def_args.ga_len;
int first_def_arg = ufunc->uf_args.ga_len - count;
int uf_args_len = ufunc->uf_args.ga_len;
int i;
char_u *arg;
int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
@@ -8210,16 +8228,24 @@ compile_def_function(
ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
if (ufunc->uf_def_arg_idx == NULL)
goto erret;
SOURCING_LNUM = 0; // line number unknown
for (i = 0; i < count; ++i)
{
garray_T *stack = &cctx.ctx_type_stack;
type_T *val_type;
int arg_idx = first_def_arg + i;
where_T where;
int r;
// Make sure later arguments are not found.
ufunc->uf_args.ga_len = i;
ufunc->uf_def_arg_idx[i] = instr->ga_len;
arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
if (compile_expr0(&arg, &cctx) == FAIL)
r = compile_expr0(&arg, &cctx);
ufunc->uf_args.ga_len = uf_args_len;
if (r == FAIL)
goto erret;
// If no type specified use the type of the default value.
@@ -8418,8 +8444,8 @@ compile_def_function(
}
}
}
p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
: (int (*)(char_u *, size_t, cctx_T *))item_exists, &cctx);
p = find_ex_command(&ea, NULL, starts_with_colon
? NULL : item_exists, &cctx);
if (p == NULL)
{
+37 -18
View File
@@ -30,7 +30,7 @@ typedef struct {
int tcd_finally_idx; // instruction of the :finally block or zero
int tcd_endtry_idx; // instruction of the :endtry
int tcd_caught; // catch block entered
int tcd_cont; // :continue encountered, jump here
int tcd_cont; // :continue encountered, jump here (minus one)
int tcd_return; // when TRUE return from end of :finally
} trycmd_T;
@@ -323,6 +323,8 @@ call_dfunc(int cdf_idx, partial_T *pt, int argcount_arg, ectx_T *ectx)
else
ectx->ec_outer = NULL;
++ufunc->uf_calls;
// Set execution state to the start of the called function.
ectx->ec_dfunc_idx = cdf_idx;
ectx->ec_instr = INSTRUCTIONS(dfunc);
@@ -556,6 +558,9 @@ func_return(ectx_T *ectx)
}
}
#endif
// TODO: when is it safe to delete the function when it is no longer used?
--dfunc->df_ufunc->uf_calls;
// execution context goes one level up
entry = estack_pop();
if (entry != NULL)
@@ -807,9 +812,12 @@ call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
// types are correct.
for (i = 0; i < argcount; ++i)
{
type_T *type = i < ufunc->uf_args.ga_len
? ufunc->uf_arg_types[i] : ufunc->uf_va_type;
type_T *type = NULL;
if (i < ufunc->uf_args.ga_len)
type = ufunc->uf_arg_types[i];
else if (ufunc->uf_va_type != NULL)
type = ufunc->uf_va_type->tt_member;
if (type != NULL && check_typval_arg_type(type,
&argv[i], i + 1) == FAIL)
return FAIL;
@@ -982,8 +990,9 @@ allocate_if_null(typval_T *tv)
}
/*
* Return the character "str[index]" where "index" is the character index. If
* "index" is out of range NULL is returned.
* Return the character "str[index]" where "index" is the character index,
* including composing characters.
* If "index" is out of range NULL is returned.
*/
char_u *
char_from_string(char_u *str, varnumber_T index)
@@ -1002,7 +1011,7 @@ char_from_string(char_u *str, varnumber_T index)
int clen = 0;
for (nbyte = 0; nbyte < slen; ++clen)
nbyte += MB_CPTR2LEN(str + nbyte);
nbyte += mb_ptr2len(str + nbyte);
nchar = clen + index;
if (nchar < 0)
// unlike list: index out of range results in empty string
@@ -1010,15 +1019,15 @@ char_from_string(char_u *str, varnumber_T index)
}
for (nbyte = 0; nchar > 0 && nbyte < slen; --nchar)
nbyte += MB_CPTR2LEN(str + nbyte);
nbyte += mb_ptr2len(str + nbyte);
if (nbyte >= slen)
return NULL;
return vim_strnsave(str + nbyte, MB_CPTR2LEN(str + nbyte));
return vim_strnsave(str + nbyte, mb_ptr2len(str + nbyte));
}
/*
* Get the byte index for character index "idx" in string "str" with length
* "str_len".
* "str_len". Composing characters are included.
* If going over the end return "str_len".
* If "idx" is negative count from the end, -1 is the last character.
* When going over the start return -1.
@@ -1033,7 +1042,7 @@ char_idx2byte(char_u *str, size_t str_len, varnumber_T idx)
{
while (nchar > 0 && nbyte < str_len)
{
nbyte += MB_CPTR2LEN(str + nbyte);
nbyte += mb_ptr2len(str + nbyte);
--nchar;
}
}
@@ -1053,7 +1062,8 @@ char_idx2byte(char_u *str, size_t str_len, varnumber_T idx)
}
/*
* Return the slice "str[first:last]" using character indexes.
* Return the slice "str[first : last]" using character indexes. Composing
* characters are included.
* "exclusive" is TRUE for slice().
* Return NULL when the result is empty.
*/
@@ -1076,7 +1086,7 @@ string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive)
end_byte = char_idx2byte(str, slen, last);
if (!exclusive && end_byte >= 0 && end_byte < (long)slen)
// end index is inclusive
end_byte += MB_CPTR2LEN(str + end_byte);
end_byte += mb_ptr2len(str + end_byte);
}
if (start_byte >= (long)slen || end_byte <= start_byte)
@@ -1329,7 +1339,7 @@ call_def_function(
++ectx.ec_stack.ga_len;
}
if (ufunc->uf_va_name != NULL)
++ectx.ec_stack.ga_len;
++ectx.ec_stack.ga_len;
// Frame pointer points to just after arguments.
ectx.ec_frame_idx = ectx.ec_stack.ga_len;
@@ -1402,6 +1412,9 @@ call_def_function(
// Do turn errors into exceptions.
suppress_errthrow = FALSE;
// Do not delete the function while executing it.
++ufunc->uf_calls;
// When ":silent!" was used before calling then we still abort the
// function. If ":silent!" is used in the function then we don't.
emsg_silent_def = emsg_silent;
@@ -1762,7 +1775,7 @@ call_def_function(
goto failed;
SOURCING_LNUM = iptr->isn_lnum;
if (eval_variable(name, (int)STRLEN(name),
STACK_TV_BOT(0), NULL, TRUE, FALSE) == FAIL)
STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL)
goto on_error;
++ectx.ec_stack.ga_len;
}
@@ -2754,7 +2767,9 @@ call_def_function(
{
trycmd = ((trycmd_T *)trystack->ga_data)
+ trystack->ga_len - i;
trycmd->tcd_cont = iidx;
// Add one to tcd_cont to be able to jump to
// instruction with index zero.
trycmd->tcd_cont = iidx + 1;
iidx = trycmd->tcd_finally_idx == 0
? trycmd->tcd_endtry_idx : trycmd->tcd_finally_idx;
}
@@ -2808,7 +2823,7 @@ call_def_function(
if (trycmd->tcd_cont != 0)
// handling :continue: jump to outer try block or
// start of the loop
ectx.ec_iidx = trycmd->tcd_cont;
ectx.ec_iidx = trycmd->tcd_cont - 1;
}
}
break;
@@ -3244,8 +3259,9 @@ call_def_function(
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
// negative the result is empty.
// single character (including composing characters).
// If the index is too big or negative the result is
// empty.
res = char_from_string(tv->vval.v_string, n2);
vim_free(tv->vval.v_string);
tv->vval.v_string = res;
@@ -3830,6 +3846,9 @@ failed:
estack_pop();
current_sctx = save_current_sctx;
// TODO: when is it safe to delete the function if it is no longer used?
--ufunc->uf_calls;
if (*msg_list != NULL && saved_msg_list != NULL)
{
msglist_T **plist = saved_msg_list;
+9 -5
View File
@@ -75,7 +75,7 @@ ex_vim9script(exarg_T *eap UNUSED)
if (STRCMP(p_cpo, CPO_VIM) != 0)
{
si->sn_save_cpo = vim_strsave(p_cpo);
set_option_value((char_u *)"cpo", 0L, (char_u *)CPO_VIM, 0);
set_option_value((char_u *)"cpo", 0L, (char_u *)CPO_VIM, OPT_NO_REDRAW);
}
#else
// No check for this being the first command, it doesn't matter.
@@ -102,6 +102,7 @@ not_in_vim9(exarg_T *eap)
case CMD_append:
case CMD_change:
case CMD_insert:
case CMD_open:
case CMD_t:
case CMD_xit:
semsg(_(e_command_not_supported_in_vim9_script_missing_var_str), eap->cmd);
@@ -257,7 +258,8 @@ find_exported(
char_u *name,
ufunc_T **ufunc,
type_T **type,
cctx_T *cctx)
cctx_T *cctx,
int verbose)
{
int idx = -1;
svar_T *sv;
@@ -271,7 +273,8 @@ find_exported(
sv = ((svar_T *)script->sn_var_vals.ga_data) + idx;
if (!sv->sv_export)
{
semsg(_(e_item_not_exported_in_script_str), name);
if (verbose)
semsg(_(e_item_not_exported_in_script_str), name);
return -1;
}
*type = sv->sv_type;
@@ -301,7 +304,8 @@ find_exported(
if (*ufunc == NULL)
{
semsg(_(e_item_not_found_in_script_str), name);
if (verbose)
semsg(_(e_item_not_found_in_script_str), name);
return -1;
}
}
@@ -532,7 +536,7 @@ handle_import(
ufunc_T *ufunc = NULL;
type_T *type;
idx = find_exported(sid, name, &ufunc, &type, cctx);
idx = find_exported(sid, name, &ufunc, &type, cctx, TRUE);
if (idx < 0 && ufunc == NULL)
goto erret;
+4 -2
View File
@@ -919,6 +919,8 @@ equal_type(type_T *type1, type_T *type2)
{
int i;
if (type1 == NULL || type2 == NULL)
return FALSE;
if (type1->tt_type != type2->tt_type)
return FALSE;
switch (type1->tt_type)
@@ -969,12 +971,12 @@ common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
// If either is VAR_UNKNOWN use the other type. An empty list/dict has no
// specific type.
if (type1->tt_type == VAR_UNKNOWN)
if (type1 == NULL || type1->tt_type == VAR_UNKNOWN)
{
*dest = type2;
return;
}
if (type2->tt_type == VAR_UNKNOWN)
if (type2 == NULL || type2->tt_type == VAR_UNKNOWN)
{
*dest = type1;
return;
+2 -2
View File
@@ -5865,8 +5865,8 @@ win_setminheight(void)
// loop until there is a 'winminheight' that is possible
while (p_wmh > 0)
{
room = Rows - p_ch - tabline_height();
needed = frame_minheight(topframe, NULL);
room = Rows - p_ch;
needed = min_rows() - 1; // 1 was added for the cmdline
if (room >= needed)
break;
--p_wmh;