Compare commits

...

14 Commits

Author SHA1 Message Date
Bram Moolenaar
c6e9d7063d patch 8.2.4489: failing test for comparing v:null with number
Problem:    Failing test for comparing v:null with number.
Solution:   Allow comparing v:null with number in legacy script.
            (Ken Takata, closes #9873)  Also do this for float.
2022-03-02 13:13:30 +00:00
Bram Moolenaar
f6b0c79742 patch 8.2.4488: build error with +eval but without +channel or +job
Problem:    Build error with +eval but without +channel or +job.
Solution:   Add #ifdef. (John Marriott)
2022-03-01 19:52:48 +00:00
Bram Moolenaar
7a22224875 patch 8.2.4487: Vim9: cannot compare with v:null
Problem:    Vim9: cannot compare with v:null.
Solution:   Allow comparing anything with v:null. (closes #9866)
2022-03-01 19:23:24 +00:00
Bram Moolenaar
f01af9c4e6 patch 8.2.4486: MS-Windows GUI: slow scrolling with maximized window
Problem:    MS-Windows GUI: slow scrolling with maximized window.
Solution:   Use a better way to check the window is on screen. (Ken Takata,
            closes #9865)
2022-03-01 16:02:26 +00:00
Bram Moolenaar
3e7637bd26 patch 8.2.4485: compiler warning for uninitialized variable
Problem:    Compiler warning for uninitialized variable.
Solution:   Initialize the variable. (John Marriott)
2022-02-28 21:02:19 +00:00
Bram Moolenaar
1983f1aa31 patch 8.2.4484: Vim9: some error messages are not tested
Problem:    Vim9: some error messages are not tested.
Solution:   Add a few more test cases.  Delete dead code.
2022-02-28 20:55:02 +00:00
Yegappan Lakshmanan
5de4c4372d patch 8.2.4483: command completion makes two rounds to collect matches
Problem:    Command completion makes two rounds to collect matches.
Solution:   Use a growarray to collect matches. (Yegappan Lakshmanan,
            closes #9860)
2022-02-28 13:28:38 +00:00
Yegappan Lakshmanan
afd4ae35d6 patch 8.2.4482: no fuzzy cmdline completion for user defined completion
Problem:    No fuzzy cmdline completion for user defined completion.
Solution:   Add fuzzy completion for user defined completion. (Yegappan
            Lakshmanan, closes #9858)
2022-02-27 21:03:21 +00:00
Bram Moolenaar
5c52be40fb patch 8.2.4481: cmdline popup menu not removed when 'lazyredraw' is set
Problem:    Cmdline popup menu not removed when 'lazyredraw' is set.
Solution:   Temporarily reset 'lazyredraw' when removing the popup menu.
            (closes #9857)
2022-02-27 14:28:31 +00:00
xtkoba
cbef12e60b patch 8.2.4480: suspending with CTRL-Z does not work on Android
Problem:    Suspending with CTRL-Z does not work on Android.
Solution:   Do not handle SIGTSTP. (closes #9854)
2022-02-27 12:31:52 +00:00
Yegappan Lakshmanan
6caeda2fce patch 8.2.4479: no fuzzy completieon for maps and abbreviations
Problem:    No fuzzy completieon for maps and abbreviations.
Solution:   Fuzzy complete maps and abbreviations. (Yegappan Lakshmanan,
            closes #9856)
2022-02-27 12:07:30 +00:00
Yegappan Lakshmanan
00333cb3b3 patch 8.2.4478: crash when using fuzzy completion
Problem:    Crash when using fuzzy completion.
Solution:   Temporary fix: put back regexp. (closes #9852, closes #9851)
2022-02-26 16:05:08 +00:00
Bram Moolenaar
29ab6ce9f3 patch 8.2.4477: crash when using fuzzy completion
Problem:    Crash when using fuzzy completion.
Solution:   Temporary fix: put back regexp. (closes #9851)
2022-02-26 15:52:08 +00:00
Bram Moolenaar
c51cf03298 Update runtime files. 2022-02-26 12:25:45 +00:00
65 changed files with 28096 additions and 9088 deletions

View File

@@ -3,7 +3,7 @@ vim9script
# Vim functions for file type detection
#
# Maintainer: Bram Moolenaar <Bram@vim.org>
# Last Change: 2022 Feb 05
# Last Change: 2022 Feb 22
# These functions are moved here from runtime/filetype.vim to make startup
# faster.

View File

@@ -153,6 +153,7 @@ DOCS = \
version6.txt \
version7.txt \
version8.txt \
version9.txt \
vi_diff.txt \
vim9.txt \
visual.txt \
@@ -298,6 +299,7 @@ HTMLS = \
version6.html \
version7.html \
version8.html \
version9.html \
vi_diff.html \
vimindex.html \
vim9.html \

View File

@@ -1639,7 +1639,7 @@ Examples for reading and writing compressed files: >
: autocmd BufReadPre,FileReadPre *.gz set bin
: autocmd BufReadPost,FileReadPost *.gz '[,']!gunzip
: autocmd BufReadPost,FileReadPost *.gz set nobin
: autocmd BufReadPost,FileReadPost *.gz execute ":doautocmd BufReadPost " . expand("%:r")
: autocmd BufReadPost,FileReadPost *.gz execute ":doautocmd BufReadPost " .. expand("%:r")
: autocmd BufWritePost,FileWritePost *.gz !mv <afile> <afile>:r
: autocmd BufWritePost,FileWritePost *.gz !gzip <afile>:r
@@ -1738,7 +1738,7 @@ To insert the current date and time in a *.html file when writing it: >
: else
: let l = line("$")
: endif
: exe "1," . l . "g/Last modified: /s/Last modified: .*/Last modified: " .
: exe "1," .. l .. "g/Last modified: /s/Last modified: .*/Last modified: " ..
: \ strftime("%Y %b %d")
:endfun

View File

@@ -1,4 +1,4 @@
*builtin.txt* For Vim version 8.2. Last change: 2022 Feb 18
*builtin.txt* For Vim version 8.2. Last change: 2022 Feb 23
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -854,7 +854,7 @@ argv([{nr} [, {winid}]])
:let i = 0
:while i < argc()
: let f = escape(fnameescape(argv(i)), '.')
: exe 'amenu Arg.' . f . ' :e ' . f . '<CR>'
: exe 'amenu Arg.' .. f .. ' :e ' .. f .. '<CR>'
: let i = i + 1
:endwhile
< Without the {nr} argument, or when {nr} is -1, a |List| with
@@ -1134,7 +1134,7 @@ bufwinid({buf}) *bufwinid()*
see |bufname()| above. If buffer {buf} doesn't exist or
there is no such window, -1 is returned. Example: >
echo "A window containing buffer 1 is " . (bufwinid(1))
echo "A window containing buffer 1 is " .. (bufwinid(1))
<
Only deals with the current tab page.
@@ -1147,7 +1147,7 @@ bufwinnr({buf}) *bufwinnr()*
If buffer {buf} doesn't exist or there is no such window, -1
is returned. Example: >
echo "A window containing buffer 1 is " . (bufwinnr(1))
echo "A window containing buffer 1 is " .. (bufwinnr(1))
< The number can be used with |CTRL-W_w| and ":wincmd w"
|:wincmd|.
@@ -1197,7 +1197,7 @@ byteidx({expr}, {nr}) *byteidx()*
byteidxcomp({expr}, {nr}) *byteidxcomp()*
Like byteidx(), except that a composing character is counted
as a separate character. Example: >
let s = 'e' . nr2char(0x301)
let s = 'e' .. nr2char(0x301)
echo byteidx(s, 1)
echo byteidxcomp(s, 1)
echo byteidxcomp(s, 2)
@@ -1392,7 +1392,7 @@ col({expr}) The result is a Number, which is the byte index of the column
col(".") column of cursor
col("$") length of cursor line plus one
col("'t") column of mark t
col("'" . markname) column of mark markname
col("'" .. markname) column of mark markname
< The first column is 1. 0 is returned for an error.
For an uppercase mark the column may actually be in another
buffer.
@@ -1401,7 +1401,7 @@ col({expr}) The result is a Number, which is the byte index of the column
line. This can be used to obtain the column in Insert mode: >
:imap <F2> <C-O>:let save_ve = &ve<CR>
\<C-O>:set ve=all<CR>
\<C-O>:echo col(".") . "\n" <Bar>
\<C-O>:echo col(".") .. "\n" <Bar>
\let &ve = save_ve<CR>
< Can also be used as a |method|: >
@@ -2247,12 +2247,12 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
:e extension only
Example: >
:let &tags = expand("%:p:h") . "/tags"
:let &tags = expand("%:p:h") .. "/tags"
< Note that when expanding a string that starts with '%', '#' or
'<', any following text is ignored. This does NOT work: >
:let doesntwork = expand("%:h.bak")
< Use this: >
:let doeswork = expand("%:h") . ".bak"
:let doeswork = expand("%:h") .. ".bak"
< Also note that expanding "<cfile>" and others only returns the
referenced file name without further expansion. If "<cfile>"
is "~/.cshrc", you need to do another expand() to have the
@@ -2633,7 +2633,7 @@ fnameescape({string}) *fnameescape()*
and |:write|). And a "-" by itself (special after |:cd|).
Example: >
:let fname = '+some str%nge|name'
:exe "edit " . fnameescape(fname)
:exe "edit " .. fnameescape(fname)
< results in executing: >
edit \+some\ str\%nge\|name
<
@@ -2814,7 +2814,7 @@ function({name} [, {arglist}] [, {dict}])
< The Dictionary is only useful when calling a "dict" function.
In that case the {dict} is passed in as "self". Example: >
function Callback() dict
echo "called for " . self.name
echo "called for " .. self.name
endfunction
...
let context = {"name": "example"}
@@ -3013,7 +3013,7 @@ getbufvar({buf}, {varname} [, {def}]) *getbufvar()*
string is returned, there is no error message.
Examples: >
:let bufmodified = getbufvar(1, "&mod")
:echo "todo myvar = " . getbufvar("todo", "myvar")
:echo "todo myvar = " .. getbufvar("todo", "myvar")
< Can also be used as a |method|: >
GetBufnr()->getbufvar(varname)
@@ -3074,9 +3074,9 @@ getchar([expr]) *getchar()*
This example positions the mouse as it would normally happen: >
let c = getchar()
if c == "\<LeftMouse>" && v:mouse_win > 0
exe v:mouse_win . "wincmd w"
exe v:mouse_win .. "wincmd w"
exe v:mouse_lnum
exe "normal " . v:mouse_col . "|"
exe "normal " .. v:mouse_col .. "|"
endif
<
When using bracketed paste only the first character is
@@ -3873,7 +3873,7 @@ gettabwinvar({tabnr}, {winnr}, {varname} [, {def}]) *gettabwinvar()*
empty string is returned, there is no error message.
Examples: >
:let list_is_on = gettabwinvar(1, 2, '&list')
:echo "myvar = " . gettabwinvar(3, 1, 'myvar')
:echo "myvar = " .. gettabwinvar(3, 1, 'myvar')
<
To obtain all window-local variables use: >
gettabwinvar({tabnr}, {winnr}, '&')
@@ -4006,7 +4006,7 @@ getwinvar({winnr}, {varname} [, {def}]) *getwinvar()*
Like |gettabwinvar()| for the current tabpage.
Examples: >
:let list_is_on = getwinvar(2, '&list')
:echo "myvar = " . getwinvar(1, 'myvar')
:echo "myvar = " .. getwinvar(1, 'myvar')
< Can also be used as a |method|: >
GetWinnr()->getwinvar(varname)
@@ -4261,7 +4261,7 @@ histdel({history} [, {item}]) *histdel()*
The following three are equivalent: >
:call histdel("search", histnr("search"))
:call histdel("search", -1)
:call histdel("search", '^'.histget("search", -1).'$')
:call histdel("search", '^' .. histget("search", -1) .. '$')
<
To delete the last search pattern and use the last-but-one for
the "n" command and 'hlsearch': >
@@ -4280,7 +4280,7 @@ histget({history} [, {index}]) *histget()*
Examples:
Redo the second last search from history. >
:execute '/' . histget("search", -2)
:execute '/' .. histget("search", -2)
< Define an Ex command ":H {num}" that supports re-execution of
the {num}th entry from the output of |:history|. >
@@ -4526,7 +4526,7 @@ input({prompt} [, {text} [, {completion}]]) *input()*
|:execute| or |:normal|.
Example with a mapping: >
:nmap \x :call GetFoo()<CR>:exe "/" . Foo<CR>
:nmap \x :call GetFoo()<CR>:exe "/" .. Foo<CR>
:function GetFoo()
: call inputsave()
: let g:Foo = input("enter search pattern: ")
@@ -4700,7 +4700,7 @@ items({dict}) *items()*
order. Also see |keys()| and |values()|.
Example: >
for [key, value] in items(mydict)
echo key . ': ' . value
echo key .. ': ' .. value
endfor
< Can also be used as a |method|: >
@@ -4715,7 +4715,7 @@ join({list} [, {sep}]) *join()*
{sep} is omitted a single space is used.
Note that {sep} is not added at the end. You might want to
add it there too: >
let lines = join(mylist, "\n") . "\n"
let lines = join(mylist, "\n") .. "\n"
< String items are used as-is. |Lists| and |Dictionaries| are
converted into a string like with |string()|.
The opposite function is |split()|.
@@ -4927,7 +4927,7 @@ line({expr} [, {winid}]) *line()*
line(".") line number of the cursor
line(".", winid) idem, in window "winid"
line("'t") line number of mark t
line("'" . marker) line number of mark marker
line("'" .. marker) line number of mark marker
<
To jump to the last known position when opening a file see
|last-position-jump|.
@@ -5161,7 +5161,7 @@ map({expr1}, {expr2}) *map()*
current byte. For a |String| |v:key| has the index of the
current character.
Example: >
:call map(mylist, '"> " . v:val . " <"')
:call map(mylist, '"> " .. v:val .. " <"')
< This puts "> " before and " <" after each item in "mylist".
Note that {expr2} is the result of an expression and is then
@@ -5175,19 +5175,19 @@ map({expr1}, {expr2}) *map()*
The function must return the new value of the item. Example
that changes each value by "key-value": >
func KeyValue(key, val)
return a:key . '-' . a:val
return a:key .. '-' .. a:val
endfunc
call map(myDict, function('KeyValue'))
< It is shorter when using a |lambda|: >
call map(myDict, {key, val -> key . '-' . val})
call map(myDict, {key, val -> key .. '-' .. val})
< If you do not use "val" you can leave it out: >
call map(myDict, {key -> 'item: ' . key})
call map(myDict, {key -> 'item: ' .. key})
< If you do not use "key" you can use a short name: >
call map(myDict, {_, val -> 'item: ' . val})
call map(myDict, {_, val -> 'item: ' .. val})
<
The operation is done in-place for a |List| and |Dictionary|.
If you want it to remain unmodified make a copy first: >
:let tlist = map(copy(mylist), ' v:val . "\t"')
:let tlist = map(copy(mylist), ' v:val .. "\t"')
< Returns {expr1}, the |List| or |Dictionary| that was filtered,
or a new |Blob| or |String|.
@@ -5263,7 +5263,7 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
then the global mappings.
This function can be used to map a key even when it's already
mapped, and have it do the original mapping too. Sketch: >
exe 'nnoremap <Tab> ==' . maparg('<Tab>', 'n')
exe 'nnoremap <Tab> ==' .. maparg('<Tab>', 'n')
< Can also be used as a |method|: >
GetKey()->maparg('n')
@@ -5786,7 +5786,7 @@ mkdir({name} [, {path} [, {prot}]])
{name}. Thus if you create /tmp/foo/bar then /tmp/foo will be
created with 0o755.
Example: >
:call mkdir($HOME . "/tmp/foo/bar", "p", 0o700)
:call mkdir($HOME .. "/tmp/foo/bar", "p", 0o700)
< This function is not available in the |sandbox|.
@@ -6227,7 +6227,7 @@ prompt_setcallback({buf}, {expr}) *prompt_setcallback()*
stopinsert
close
else
call append(line('$') - 1, 'Entered: "' . a:text . '"')
call append(line('$') - 1, 'Entered: "' .. a:text .. '"')
" Reset 'modified' to allow the buffer to be closed.
set nomodified
endif
@@ -6424,7 +6424,7 @@ readdir({directory} [, {expr} [, {dict}]]) *readdir()*
function! s:tree(dir)
return {a:dir : map(readdir(a:dir),
\ {_, x -> isdirectory(x) ?
\ {x : s:tree(a:dir . '/' . x)} : x})}
\ {x : s:tree(a:dir .. '/' .. x)} : x})}
endfunction
echo s:tree(".")
<
@@ -6686,7 +6686,7 @@ remote_peek({serverid} [, {retvar}]) *remote_peek()*
{only available when compiled with the |+clientserver| feature}
Examples: >
:let repl = ""
:echo "PEEK: ".remote_peek(id, "repl").": ".repl
:echo "PEEK: " .. remote_peek(id, "repl") .. ": " .. repl
< Can also be used as a |method|: >
ServerId()->remote_peek()
@@ -6724,12 +6724,12 @@ remote_send({server}, {string} [, {idvar}])
Note: Any errors will be reported in the server and may mess
up the display.
Examples: >
:echo remote_send("gvim", ":DropAndReply ".file, "serverid").
:echo remote_send("gvim", ":DropAndReply " .. file, "serverid") ..
\ remote_read(serverid)
:autocmd NONE RemoteReply *
\ echo remote_read(expand("<amatch>"))
:echo remote_send("gvim", ":sleep 10 | echo ".
:echo remote_send("gvim", ":sleep 10 | echo " ..
\ 'server2client(expand("<client>"), "HELLO")<CR>')
<
Can also be used as a |method|: >
@@ -6754,7 +6754,7 @@ remove({list}, {idx} [, {end}]) *remove()*
points to an item before {idx} this is an error.
See |list-index| for possible values of {idx} and {end}.
Example: >
:echo "last item: " . remove(mylist, -1)
:echo "last item: " .. remove(mylist, -1)
:call remove(mylist, 0, 9)
<
Use |delete()| to remove a file.
@@ -6770,13 +6770,13 @@ remove({blob}, {idx} [, {end}])
byte as {end} a |Blob| with one byte is returned. When {end}
points to a byte before {idx} this is an error.
Example: >
:echo "last byte: " . remove(myblob, -1)
:echo "last byte: " .. remove(myblob, -1)
:call remove(mylist, 0, 9)
remove({dict}, {key})
Remove the entry from {dict} with key {key} and return it.
Example: >
:echo "removed " . remove(dict, "one")
:echo "removed " .. remove(dict, "one")
< If there is no {key} in {dict} this is an error.
rename({from}, {to}) *rename()*
@@ -6907,7 +6907,7 @@ screencol() *screencol()*
column inside the command line, which is 1 when the command is
executed. To get the cursor position in the file use one of
the following mappings: >
nnoremap <expr> GG ":echom ".screencol()."\n"
nnoremap <expr> GG ":echom " .. screencol() .. "\n"
nnoremap <silent> GG :echom screencol()<CR>
nnoremap GG <Cmd>echom screencol()<CR>
<
@@ -7031,7 +7031,7 @@ search({pattern} [, {flags} [, {stopline} [, {timeout} [, {skip}]]]])
Example (goes over all files in the argument list): >
:let n = 1
:while n <= argc() " loop over all files in arglist
: exe "argument " . n
: exe "argument " .. n
: " start at the last char in the file and wrap for the
: " first search to find match at start of file
: normal G$
@@ -7115,11 +7115,11 @@ searchcount([{options}]) *searchcount()*
return printf(' /%s [%d/%d]', @/,
\ result.current, result.total)
endfunction
let &statusline .= '%{LastSearchCount()}'
let &statusline ..= '%{LastSearchCount()}'
" Or if you want to show the count only when
" 'hlsearch' was on
" let &statusline .=
" let &statusline ..=
" \ '%{v:hlsearch ? LastSearchCount() : ""}'
<
You can also update the search count, which can be useful in a
@@ -7943,10 +7943,10 @@ shellescape({string} [, {special}]) *shellescape()*
character inside single quotes.
Example of use with a |:!| command: >
:exe '!dir ' . shellescape(expand('<cfile>'), 1)
:exe '!dir ' .. shellescape(expand('<cfile>'), 1)
< This results in a directory listing for the file under the
cursor. Example of use with |system()|: >
:call system("chmod +w -- " . shellescape(expand("%")))
:call system("chmod +w -- " .. shellescape(expand("%")))
< See also |::S|.
Can also be used as a |method|: >
@@ -8719,7 +8719,7 @@ substitute({string}, {pat}, {sub}, {flags}) *substitute()*
When {sub} starts with "\=", the remainder is interpreted as
an expression. See |sub-replace-expression|. Example: >
:echo substitute(s, '%\(\x\x\)',
\ '\=nr2char("0x" . submatch(1))', 'g')
\ '\=nr2char("0x" .. submatch(1))', 'g')
< When {sub} is a Funcref that function is called, with one
optional argument. Example: >
@@ -8727,7 +8727,7 @@ substitute({string}, {pat}, {sub}, {flags}) *substitute()*
< The optional argument is a list which contains the whole
matched string and up to nine submatches, like what
|submatch()| returns. Example: >
:echo substitute(s, '%\(\x\x\)', {m -> '0x' . m[1]}, 'g')
:echo substitute(s, '%\(\x\x\)', {m -> '0x' .. m[1]}, 'g')
< Can also be used as a |method|: >
GetString()->substitute(pat, sub, flags)
@@ -8916,8 +8916,8 @@ system({expr} [, {input}]) *system()* *E677*
This is not to be used for interactive commands.
The result is a String. Example: >
:let files = system("ls " . shellescape(expand('%:h')))
:let files = system('ls ' . expand('%:h:S'))
:let files = system('ls ' .. shellescape(expand('%:h')))
:let files = system('ls ' .. expand('%:h:S'))
< To make the result more system-independent, the shell output
is filtered to replace <CR> with <NL> for Macintosh, and
@@ -9098,7 +9098,7 @@ tempname() *tempname()* *temp-file-name*
doesn't exist. It can be used for a temporary file. The name
is different for at least 26 consecutive calls. Example: >
:let tmpfile = tempname()
:exe "redir > " . tmpfile
:exe "redir > " .. tmpfile
< For Unix, the file will be in a private directory |tempfile|.
For MS-Windows forward slashes are used when the 'shellslash'
option is set, or when 'shellcmdflag' starts with '-' and
@@ -9295,7 +9295,7 @@ trim({text} [, {mask} [, {dir}]]) *trim()*
Examples: >
echo trim(" some text ")
< returns "some text" >
echo trim(" \r\t\t\r RESERVE \t\n\x0B\xA0") . "_TAIL"
echo trim(" \r\t\t\r RESERVE \t\n\x0B\xA0") .. "_TAIL"
< returns "RESERVE_TAIL" >
echo trim("rm<Xrm<>X>rrm", "rm<>")
< returns "Xrm<>X" (characters in the middle are not removed) >
@@ -9486,7 +9486,7 @@ visualmode([{expr}]) *visualmode()*
character-wise, line-wise, or block-wise Visual mode
respectively.
Example: >
:exe "normal " . visualmode()
:exe "normal " .. visualmode()
< This enters the same Visual mode as before. It is also useful
in scripts if you wish to act differently depending on the
Visual mode that was used.
@@ -9690,7 +9690,7 @@ winheight({nr}) *winheight()*
An existing window always has a height of zero or more.
This excludes any window toolbar line.
Examples: >
:echo "The current window has " . winheight(0) . " lines."
:echo "The current window has " .. winheight(0) .. " lines."
< Can also be used as a |method|: >
GetWinid()->winheight()
@@ -9831,7 +9831,7 @@ winwidth({nr}) *winwidth()*
returned. When window {nr} doesn't exist, -1 is returned.
An existing window always has a width of zero or more.
Examples: >
:echo "The current window has " . winwidth(0) . " columns."
:echo "The current window has " .. winwidth(0) .. " columns."
:if winwidth(0) <= 50
: 50 wincmd |
:endif

View File

@@ -946,7 +946,7 @@ Consider using a character like "@" or ":". There is no problem if the result
of the expression contains the separation character.
Examples: >
:s@\n@\="\r" . expand("$HOME") . "\r"@
:s@\n@\="\r" .. expand("$HOME") .. "\r"@
This replaces an end-of-line with a new line containing the value of $HOME. >
s/E/\="\<Char-0x20ac>"/g
@@ -1123,7 +1123,7 @@ inside of strings can change! Also see 'softtabstop' option. >
the command. You need to escape the '|' and '"'
characters to prevent them from terminating the
command. Example: >
:put ='path' . \",/test\"
:put ='path' .. \",/test\"
< If there is no expression after '=', Vim uses the
previous expression. You can see it with ":dis =".

View File

@@ -91,7 +91,7 @@ And you should see the message in Vim. You can move the cursor a word forward:
To handle asynchronous communication a callback needs to be used: >
func MyHandler(channel, msg)
echo "from the handler: " . a:msg
echo "from the handler: " .. a:msg
endfunc
call ch_sendexpr(channel, 'hello!', {'callback': "MyHandler"})
Vim will not wait for a response. Now the server can send the response later
@@ -136,7 +136,7 @@ When using an IPv6 address, enclose it within square brackets. E.g.,
gets two arguments: the channel and the received message.
Example: >
func Handle(channel, msg)
echo 'Received: ' . a:msg
echo 'Received: ' .. a:msg
endfunc
let channel = ch_open("localhost:8765", {"callback": "Handle"})
<
@@ -1296,7 +1296,7 @@ prompt. >
" Function handling output from the shell: Added above the prompt.
func GotOutput(channel, msg)
call append(line("$") - 1, "- " . a:msg)
call append(line("$") - 1, "- " .. a:msg)
endfunc
" Function handling the shell exist: close the window.

View File

@@ -227,7 +227,7 @@ CTRL-\ e {expr} *c_CTRL-\_e*
Example: >
:cmap <F7> <C-\>eAppendSome()<CR>
:func AppendSome()
:let cmd = getcmdline() . " Some()"
:let cmd = getcmdline() .. " Some()"
:" place the cursor on the )
:call setcmdpos(strlen(cmd))
:return cmd

View File

@@ -382,13 +382,13 @@ Example (this does almost the same as 'diffexpr' being empty): >
function MyDiff()
let opt = ""
if &diffopt =~ "icase"
let opt = opt . "-i "
let opt = opt .. "-i "
endif
if &diffopt =~ "iwhite"
let opt = opt . "-b "
let opt = opt .. "-b "
endif
silent execute "!diff -a --binary " . opt . v:fname_in . " " . v:fname_new .
\ " > " . v:fname_out
silent execute "!diff -a --binary " .. opt .. v:fname_in .. " " .. v:fname_new ..
\ " > " .. v:fname_out
redraw!
endfunction
@@ -445,8 +445,8 @@ Example (this does the same as 'patchexpr' being empty): >
set patchexpr=MyPatch()
function MyPatch()
:call system("patch -o " . v:fname_out . " " . v:fname_in .
\ " < " . v:fname_diff)
:call system("patch -o " .. v:fname_out .. " " .. v:fname_in ..
\ " < " .. v:fname_diff)
endfunction
Make sure that using the "patch" program doesn't have unwanted side effects.

View File

@@ -444,9 +444,9 @@ does apply like to other wildcards.
Environment variables in the expression are expanded when evaluating the
expression, thus this works: >
:e `=$HOME . '/.vimrc'`
:e `=$HOME .. '/.vimrc'`
This does not work, $HOME is inside a string and used literally: >
:e `='$HOME' . '/.vimrc'`
:e `='$HOME' .. '/.vimrc'`
If the expression returns a string then names are to be separated with line
breaks. When the result is a |List| then each item is used as a name. Line

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.2. Last change: 2022 Feb 20
*eval.txt* For Vim version 8.2. Last change: 2022 Feb 21
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -470,7 +470,7 @@ It is also possible to put remaining items in a List variable: >
:for [i, j; rest] in listlist
: call Doit(i, j)
: if !empty(rest)
: echo "remainder: " . string(rest)
: echo "remainder: " .. string(rest)
: endif
:endfor
@@ -498,11 +498,11 @@ Functions that are useful with a List: >
:let list = split("a b c") " create list from items in a string
:let string = join(list, ', ') " create string from list items
:let s = string(list) " String representation of list
:call map(list, '">> " . v:val') " prepend ">> " to each item
:call map(list, '">> " .. v:val') " prepend ">> " to each item
Don't forget that a combination of features can make things simple. For
example, to add up all the numbers in a list: >
:exe 'let sum = ' . join(nrlist, '+')
:exe 'let sum = ' .. join(nrlist, '+')
1.4 Dictionaries ~
@@ -568,7 +568,7 @@ turn the Dictionary into a List and pass it to |:for|.
Most often you want to loop over the keys, using the |keys()| function: >
:for key in keys(mydict)
: echo key . ': ' . mydict[key]
: echo key .. ': ' .. mydict[key]
:endfor
The List of keys is unsorted. You may want to sort them first: >
@@ -576,13 +576,13 @@ The List of keys is unsorted. You may want to sort them first: >
To loop over the values use the |values()| function: >
:for v in values(mydict)
: echo "value: " . v
: echo "value: " .. v
:endfor
If you want both the key and the value use the |items()| function. It returns
a List in which each item is a List with two items, the key and the value: >
:for [key, value] in items(mydict)
: echo key . ': ' . value
: echo key .. ': ' .. value
:endfor
@@ -677,7 +677,7 @@ Functions that can be used with a Dictionary: >
:let small = min(dict) " minimum value in dict
:let xs = count(dict, 'x') " count nr of times 'x' appears in dict
:let s = string(dict) " String representation of dict
:call map(dict, '">> " . v:val') " prepend ">> " to each item
:call map(dict, '">> " .. v:val') " prepend ">> " to each item
1.5 Blobs ~
@@ -921,13 +921,13 @@ Expression nesting is limited to 1000 levels deep (300 when build with MSVC)
to avoid running out of stack and crashing. *E1169*
expr1 *expr1* *trinary* *falsy-operator* *??* *E109*
expr1 *expr1* *ternary* *falsy-operator* *??* *E109*
-----
The trinary operator: expr2 ? expr1 : expr1
The ternary operator: expr2 ? expr1 : expr1
The falsy operator: expr2 ?? expr1
Trinary operator ~
Ternary operator ~
In legacy script the expression before the '?' is evaluated to a number. If
it evaluates to |TRUE|, the result is the value of the expression between the
@@ -1530,7 +1530,7 @@ option *expr-option* *E112* *E113*
&l:option local option value
Examples: >
echo "tabstop is " . &tabstop
echo "tabstop is " .. &tabstop
if &insertmode
Any option name can be used here. See |options|. When using the local value
@@ -1820,7 +1820,7 @@ maintain a counter: >
echo "script executed for the first time"
else
let s:counter = s:counter + 1
echo "script executed " . s:counter . " times now"
echo "script executed " .. s:counter .. " times now"
endif
Note that this means that filetype plugins don't get a different set of script
@@ -1955,7 +1955,7 @@ v:completed_item
*v:count* *count-variable*
v:count The count given for the last Normal mode command. Can be used
to get the count before a mapping. Read-only. Example: >
:map _x :<C-U>echo "the count is " . v:count<CR>
:map _x :<C-U>echo "the count is " .. v:count<CR>
< Note: The <C-U> is required to remove the line range that you
get when typing ':' after a count.
When there are two counts, as in "3d2w", they are multiplied,
@@ -2829,9 +2829,9 @@ Example: >
: echohl Title
: echo a:title
: echohl None
: echo a:0 . " items:"
: echo a:0 .. " items:"
: for s in a:000
: echon ' ' . s
: echon ' ' .. s
: endfor
:endfunction
@@ -2874,7 +2874,7 @@ This function can then be called with: >
this works:
*function-range-example* >
:function Mynumber(arg)
: echo line(".") . " " . a:arg
: echo line(".") .. " " .. a:arg
:endfunction
:1,5call Mynumber(getline("."))
<
@@ -2885,7 +2885,7 @@ This function can then be called with: >
Example of a function that handles the range itself: >
:function Cont() range
: execute (a:firstline + 1) . "," . a:lastline . 's/^/\t\\ '
: execute (a:firstline + 1) .. "," .. a:lastline .. 's/^/\t\\ '
:endfunction
:4,8call Cont()
<
@@ -3077,7 +3077,7 @@ declarations and assignments do not use a command. |vim9-declaration|
This cannot be used to add an item to a |List|.
This cannot be used to set a byte in a String. You
can do that like this: >
:let var = var[0:2] . 'X' . var[4:]
:let var = var[0:2] .. 'X' .. var[4:]
< When {var-name} is a |Blob| then {idx} can be the
length of the blob, in which case one byte is
appended.
@@ -3147,7 +3147,7 @@ declarations and assignments do not use a command. |vim9-declaration|
is just like using the |:set| command: both the local
value and the global value are changed.
Example: >
:let &path = &path . ',/usr/local/include'
:let &path = &path .. ',/usr/local/include'
< This also works for terminal codes in the form t_xx.
But only for alphanumerical names. Example: >
:let &t_k1 = "\<Esc>[234;"
@@ -3425,6 +3425,8 @@ text...
:if {expr1} *:if* *:end* *:endif* *:en* *E171* *E579* *E580*
:en[dif] Execute the commands until the next matching ":else"
or ":endif" if {expr1} evaluates to non-zero.
Although the short forms work, it is recommended to
always use `:endif` to avoid confusion.
From Vim version 4.5 until 5.0, every Ex command in
between the ":if" and ":endif" is ignored. These two
@@ -4028,7 +4030,7 @@ exception most recently caught as long it is not finished.
:function! Caught()
: if v:exception != ""
: echo 'Caught "' . v:exception . '" in ' . v:throwpoint
: echo 'Caught "' . v:exception .. '" in ' .. v:throwpoint
: else
: echo 'Nothing caught'
: endif
@@ -4431,8 +4433,8 @@ a script in order to catch unexpected things.
:catch /^Vim:Interrupt$/
: echo "Script interrupted"
:catch /.*/
: echo "Internal error (" . v:exception . ")"
: echo " - occurred at " . v:throwpoint
: echo "Internal error (" .. v:exception .. ")"
: echo " - occurred at " .. v:throwpoint
:endtry
:" end of script
@@ -4628,7 +4630,7 @@ parentheses can be cut out from |v:exception| with the ":substitute" command.
:function! CheckRange(a, func)
: if a:a < 0
: throw "EXCEPT:MATHERR:RANGE(" . a:func . ")"
: throw "EXCEPT:MATHERR:RANGE(" .. a:func .. ")"
: endif
:endfunction
:
@@ -4655,7 +4657,7 @@ parentheses can be cut out from |v:exception| with the ":substitute" command.
: try
: execute "write" fnameescape(a:file)
: catch /^Vim(write):/
: throw "EXCEPT:IO(" . getcwd() . ", " . a:file . "):WRITEERR"
: throw "EXCEPT:IO(" .. getcwd() .. ", " .. a:file .. "):WRITEERR"
: endtry
:endfunction
:
@@ -4674,9 +4676,9 @@ parentheses can be cut out from |v:exception| with the ":substitute" command.
: let dir = substitute(v:exception, '.*(\(.\+\),\s*.\+).*', '\1', "")
: let file = substitute(v:exception, '.*(.\+,\s*\(.\+\)).*', '\1', "")
: if file !~ '^/'
: let file = dir . "/" . file
: let file = dir .. "/" .. file
: endif
: echo 'I/O error for "' . file . '"'
: echo 'I/O error for "' .. file .. '"'
:
:catch /^EXCEPT/
: echo "Unspecified error"
@@ -4744,7 +4746,7 @@ clauses, however, is executed.
: echo "inner finally"
: endtry
:catch
: echo 'outer catch-all caught "' . v:exception . '"'
: echo 'outer catch-all caught "' .. v:exception .. '"'
: finally
: echo "outer finally"
:endtry
@@ -4806,7 +4808,7 @@ Printing in Binary ~
: let n = a:nr
: let r = ""
: while n
: let r = '01'[n % 2] . r
: let r = '01'[n % 2] .. r
: let n = n / 2
: endwhile
: return r
@@ -4817,7 +4819,7 @@ Printing in Binary ~
:func String2Bin(str)
: let out = ''
: for ix in range(strlen(a:str))
: let out = out . '-' . Nr2Bin(char2nr(a:str[ix]))
: let out = out .. '-' .. Nr2Bin(char2nr(a:str[ix]))
: endfor
: return out[1:]
:endfunc

View File

@@ -507,7 +507,7 @@ Note the use of backslashes to avoid some characters to be interpreted by the
:function MyFoldText()
: let line = getline(v:foldstart)
: let sub = substitute(line, '/\*\|\*/\|{{{\d\=', '', 'g')
: return v:folddashes . sub
: return v:folddashes .. sub
:endfunction
Evaluating 'foldtext' is done in the |sandbox|. The current window is set to

View File

@@ -47,20 +47,20 @@ Numbers, subscripts and superscripts are available with 's' and 'S':
But some don't come defined by default. Those are digraph definitions you can
add in your ~/.vimrc file. >
exec 'digraph \\ '.char2nr('')
exec 'digraph \< '.char2nr('≼')
exec 'digraph \> '.char2nr('≽')
exec 'digraph (L '.char2nr('⊈')
exec 'digraph )L '.char2nr('⊉')
exec 'digraph (/ '.char2nr('⊄')
exec 'digraph )/ '.char2nr('⊅')
exec 'digraph )/ '.char2nr('⊅')
exec 'digraph U+ '.char2nr('⊎')
exec 'digraph 0- '.char2nr('⊖')
exec 'digraph \\ ' .. char2nr('')
exec 'digraph \< ' .. char2nr('≼')
exec 'digraph \> ' .. char2nr('≽')
exec 'digraph (L ' .. char2nr('⊈')
exec 'digraph )L ' .. char2nr('⊉')
exec 'digraph (/ ' .. char2nr('⊄')
exec 'digraph )/ ' .. char2nr('⊅')
exec 'digraph )/ ' .. char2nr('⊅')
exec 'digraph U+ ' .. char2nr('⊎')
exec 'digraph 0- ' .. char2nr('⊖')
" Euler's constant
exec 'digraph ne '.char2nr('𝑒')
exec 'digraph ne ' .. char2nr('𝑒')
" Raku's atomic operations marker
exec 'digraph @@ '.char2nr('⚛')
exec 'digraph @@ ' .. char2nr('⚛')
Alternatively, you can write Insert mode abbreviations that convert ASCII-
based operators into their single-character Unicode equivalent. >

View File

@@ -26,7 +26,7 @@ behavior of the plugin.
g:rustc_path~
Set this option to the path to rustc for use in the |:RustRun| and
|:RustExpand| commands. If unset, "rustc" will be located in $PATH: >
let g:rustc_path = $HOME."/bin/rustc"
let g:rustc_path = $HOME .. "/bin/rustc"
<
*g:rustc_makeprg_no_percent*
@@ -87,7 +87,7 @@ g:rust_bang_comment_leader~
g:ftplugin_rust_source_path~
Set this option to a path that should be prepended to 'path' for Rust
source files: >
let g:ftplugin_rust_source_path = $HOME.'/dev/rust'
let g:ftplugin_rust_source_path = $HOME .. '/dev/rust'
<
*g:rustfmt_command*

View File

@@ -109,8 +109,8 @@ must be configurable. The filetype plugin attempts to define many of the
standard objects, plus many additional ones. In order to make this as
flexible as possible, you can override the list of objects from within your
|vimrc| with the following: >
let g:ftplugin_sql_objects = 'function,procedure,event,table,trigger' .
\ ',schema,service,publication,database,datatype,domain' .
let g:ftplugin_sql_objects = 'function,procedure,event,table,trigger' ..
\ ',schema,service,publication,database,datatype,domain' ..
\ ',index,subscription,synchronization,view,variable'
The following |Normal| mode and |Visual| mode maps have been created which use
@@ -131,10 +131,10 @@ Repeatedly pressing ]} will cycle through each of these create statements: >
create index i1 on t1 (c1);
The default setting for g:ftplugin_sql_objects is: >
let g:ftplugin_sql_objects = 'function,procedure,event,' .
\ '\\(existing\\\\|global\\s\\+temporary\\s\\+\\)\\\{,1}' .
\ 'table,trigger' .
\ ',schema,service,publication,database,datatype,domain' .
let g:ftplugin_sql_objects = 'function,procedure,event,' ..
\ '\\(existing\\\\|global\\s\\+temporary\\s\\+\\)\\\{,1}' ..
\ 'table,trigger' ..
\ ',schema,service,publication,database,datatype,domain' ..
\ ',index,subscription,synchronization,view,variable'
The above will also handle these cases: >

View File

@@ -155,8 +155,8 @@ If you are running the X Window System, you can get information about the
window Vim is running in with these commands: >
:!xwininfo -id $WINDOWID
:!xprop -id $WINDOWID
:execute '!xwininfo -id ' . v:windowid
:execute '!xprop -id ' . v:windowid
:execute '!xwininfo -id ' .. v:windowid
:execute '!xprop -id ' .. v:windowid
<
*gui-IME* *iBus*
Input methods for international characters in X that rely on the XIM

View File

@@ -1,4 +1,4 @@
*help.txt* For Vim version 8.2. Last change: 2021 Dec 27
*help.txt* For Vim version 8.2. Last change: 2022 Feb 26
VIM - main help file
k
@@ -197,6 +197,7 @@ Versions ~
|version6.txt| Differences between Vim version 5.7 and 6.x
|version7.txt| Differences between Vim version 6.4 and 7.x
|version8.txt| Differences between Vim version 7.4 and 8.x
|version9.txt| Differences between Vim version 8.2 and 9.0
*sys-file-list*
Remarks about specific systems ~
|os_390.txt| OS/390 Unix

View File

@@ -1,4 +1,4 @@
*if_pyth.txt* For Vim version 8.2. Last change: 2022 Feb 07
*if_pyth.txt* For Vim version 8.2. Last change: 2022 Feb 22
VIM REFERENCE MANUAL by Paul Moore
@@ -25,6 +25,10 @@ The Python 3 interface is available only when Vim was compiled with the
|+python3| feature.
Both can be available at the same time, but read |python-2-and-3|.
NOTE: Python 2 is old and no longer being developed. Using Python 3 is highly
recommended. Python 2 support will be dropped when it does not work properly
anymore.
==============================================================================
1. Commands *python-commands*
@@ -923,7 +927,7 @@ The `:pyxdo` command works similar to `:pydo`.
*has-pythonx*
You can test if pyx* commands are available with: >
if has('pythonx')
echo 'pyx* commands are available. (Python ' . &pyx . ')'
echo 'pyx* commands are available. (Python ' .. &pyx .. ')'
endif
When compiled with only one of |+python| or |+python3|, the has() returns 1.

View File

@@ -879,9 +879,9 @@ Groß): >
endif
let res = []
let h = ''
for l in systemlist('aiksaurus '.shellescape(a:base))
for l in systemlist('aiksaurus ' .. shellescape(a:base))
if l[:3] == '=== '
let h = '('.substitute(l[4:], ' =*$', ')', '')
let h = '(' .. substitute(l[4:], ' =*$', ')', '')
elseif l ==# 'Alphabetically similar known words are: '
let h = "\U0001f52e"
elseif l[0] =~ '\a' || (h ==# "\U0001f52e" && l[0] ==# "\t")
@@ -1266,7 +1266,7 @@ An example that completes the names of the months: >
" find months matching with "a:base"
let res = []
for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")
if m =~ '^' . a:base
if m =~ '^' .. a:base
call add(res, m)
endif
endfor
@@ -1288,7 +1288,7 @@ The same, but now pretending searching for matches is slow: >
else
" find months matching with "a:base"
for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")
if m =~ '^' . a:base
if m =~ '^' .. a:base
call complete_add(m)
endif
sleep 300m " simulate searching for next match

View File

@@ -314,7 +314,7 @@ Here is an example that inserts a list number that increases: >
func ListItem()
let g:counter += 1
return g:counter . '. '
return g:counter .. '. '
endfunc
func ListReset()
@@ -1697,12 +1697,12 @@ The valid escape sequences are
Examples: >
command! -nargs=+ -complete=file MyEdit
\ for f in expand(<q-args>, 0, 1) |
\ exe '<mods> split ' . f |
\ exe '<mods> split ' .. f |
\ endfor
function! SpecialEdit(files, mods)
for f in expand(a:files, 0, 1)
exe a:mods . ' split ' . f
exe a:mods .. ' split ' .. f
endfor
endfunction
command! -nargs=+ -complete=file Sedit
@@ -1778,7 +1778,7 @@ This will invoke: >
: let i = 0
: while i < argc()
: if filereadable(argv(i))
: execute "e " . argv(i)
: execute "e " .. argv(i)
: execute a:command
: endif
: let i = i + 1

View File

@@ -1019,7 +1019,7 @@ These commands are not marks themselves, but jump to a mark:
:let lnum = line(".")
:keepjumps normal gg
:call SetLastChange()
:keepjumps exe "normal " . lnum . "G"
:keepjumps exe "normal " .. lnum .. "G"
<
Note that ":keepjumps" must be used for every command.
When invoking a function the commands in that function

View File

@@ -1142,7 +1142,7 @@ A jump table for the options with a short description can be found at |Q_op|.
If you like to keep a lot of backups, you could use a BufWritePre
autocommand to change 'backupext' just before writing the file to
include a timestamp. >
:au BufWritePre * let &bex = '-' . strftime("%Y%b%d%X") . '~'
:au BufWritePre * let &bex = '-' .. strftime("%Y%b%d%X") .. '~'
< Use 'backupdir' to put the backup in a different directory.
*'backupskip'* *'bsk'*
@@ -1167,7 +1167,7 @@ A jump table for the options with a short description can be found at |Q_op|.
Note that environment variables are not expanded. If you want to use
$HOME you must expand it explicitly, e.g.: >
:let &backupskip = escape(expand('$HOME'), '\') . '/tmp/*'
:let &backupskip = escape(expand('$HOME'), '\') .. '/tmp/*'
< Note that the default also makes sure that "crontab -e" works (when a
backup would be made by renaming the original file crontab won't see
@@ -1218,10 +1218,10 @@ A jump table for the options with a short description can be found at |Q_op|.
The evaluation of the expression must not have side effects!
Example: >
function MyBalloonExpr()
return 'Cursor is at line ' . v:beval_lnum .
\', column ' . v:beval_col .
\ ' of file ' . bufname(v:beval_bufnr) .
\ ' on word "' . v:beval_text . '"'
return 'Cursor is at line ' .. v:beval_lnum ..
\ ', column ' .. v:beval_col ..
\ ' of file ' .. bufname(v:beval_bufnr) ..
\ ' on word "' .. v:beval_text .. '"'
endfunction
set bexpr=MyBalloonExpr()
set ballooneval
@@ -1537,7 +1537,7 @@ A jump table for the options with a short description can be found at |Q_op|.
If the default value taken from $CDPATH is not what you want, include
a modified version of the following command in your vimrc file to
override it: >
:let &cdpath = ',' . substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g')
:let &cdpath = ',' .. substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g')
< This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
(parts of 'cdpath' can be passed to the shell to expand file names).
@@ -1582,8 +1582,8 @@ A jump table for the options with a short description can be found at |Q_op|.
set charconvert=CharConvert()
fun CharConvert()
system("recode "
\ . v:charconvert_from . ".." . v:charconvert_to
\ . " <" . v:fname_in . " >" v:fname_out)
\ .. v:charconvert_from .. ".." .. v:charconvert_to
\ .. " <" .. v:fname_in .. " >" .. v:fname_out)
return v:shell_error
endfun
< The related Vim variables are:
@@ -4887,7 +4887,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|+multi_lang| features}
Language to use for menu translation. Tells which file is loaded
from the "lang" directory in 'runtimepath': >
"lang/menu_" . &langmenu . ".vim"
"lang/menu_" .. &langmenu .. ".vim"
< (without the spaces). For example, to always use the Dutch menus, no
matter what $LANG is set to: >
:set langmenu=nl_NL.ISO_8859-1
@@ -5901,7 +5901,7 @@ A jump table for the options with a short description can be found at |Q_op|.
< To use an environment variable, you probably need to replace the
separator. Here is an example to append $INCL, in which directory
names are separated with a semi-colon: >
:let &path = &path . "," . substitute($INCL, ';', ',', 'g')
:let &path = &path .. "," .. substitute($INCL, ';', ',', 'g')
< Replace the ';' with a ':' or whatever separator is used. Note that
this doesn't work when $INCL contains a comma or white space.
@@ -8318,7 +8318,7 @@ A jump table for the options with a short description can be found at |Q_op|.
This option cannot be set in a modeline when 'modelineexpr' is off.
Example: >
:auto BufEnter * let &titlestring = hostname() . "/" . expand("%:p")
:auto BufEnter * let &titlestring = hostname() .. "/" .. expand("%:p")
:set title titlestring=%<%F%=%l/%L-%P titlelen=70
< The value of 'titlelen' is used to align items in the middle or right
of the available space.

View File

@@ -603,13 +603,13 @@ program to the new diff on VMS. Add this to your .vimrc file: >
function MyDiff()
let opt = ""
if &diffopt =~ "icase"
let opt = opt . "-i "
let opt = opt .. "-i "
endif
if &diffopt =~ "iwhite"
let opt = opt . "-b "
let opt = opt .. "-b "
endif
silent execute "!mc GNU:diff.exe -a " . opt . v:fname_in . " " . v:fname_new .
\ " > " . v:fname_out
silent execute "!mc GNU:diff.exe -a " .. opt .. v:fname_in .. " " .. v:fname_new ..
\ " > " .. v:fname_out
endfunction
endif

View File

@@ -963,7 +963,7 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
the cursor moves the display isn't updated for this change. An update
is done when using the |CTRL-L| command (the whole screen is updated).
Example, to highlight the column where the cursor currently is: >
:exe '/\%' . col(".") . 'c'
:exe '/\%' .. col(".") .. 'c'
< Alternatively use: >
/\%.c
< When 'hlsearch' is set and you move the cursor around and make changes

View File

@@ -968,7 +968,7 @@ itself:
fun! NetReadFixup(method, line1, line2)
if method == 3 " ftp (no <.netrc>)
let fourblanklines= line2 - 3
silent fourblanklines.",".line2."g/^\s*/d"
silent fourblanklines .. "," .. line2 .. "g/^\s*/d"
endif
endfunction
endif
@@ -1975,7 +1975,7 @@ To use this function, simply assign its output to |g:netrw_list_hide| option. >
Example: let g:netrw_list_hide= netrw_gitignore#Hide('my_gitignore_file')
Function can take additional files with git-ignore patterns.
Example: g:netrw_list_hide= netrw_gitignore#Hide() . '.*\.swp$'
Example: let g:netrw_list_hide= netrw_gitignore#Hide() .. '.*\.swp$'
Combining 'netrw_gitignore#Hide' with custom patterns.
<
@@ -2825,7 +2825,7 @@ your browsing preferences. (see also: |netrw-settings|)
Examples:
let g:netrw_list_hide= '.*\.swp$'
let g:netrw_list_hide= netrw_gitignore#Hide().'.*\.swp$'
let g:netrw_list_hide= netrw_gitignore#Hide() .. '.*\.swp$'
default: ""
*g:netrw_localcopycmd* ="cp" Linux/Unix/MacOS/Cygwin

View File

@@ -139,28 +139,28 @@ If there is no error, return zero or an empty string.
The default for non MS-Windows or VMS systems is to simply use "lpr" to print
the file: >
system('lpr' . (&printdevice == '' ? '' : ' -P' . &printdevice)
. ' ' . v:fname_in) . delete(v:fname_in) + v:shell_error
system('lpr' .. (&printdevice == '' ? '' : ' -P' .. &printdevice)
.. ' ' .. v:fname_in) .. delete(v:fname_in) + v:shell_error
On MS-Windows machines the default is to copy the file to the currently
specified printdevice: >
system('copy' . ' ' . v:fname_in . (&printdevice == ''
? ' LPT1:' : (' \"' . &printdevice . '\"')))
. delete(v:fname_in)
system('copy' .. ' ' .. v:fname_in .. (&printdevice == ''
? ' LPT1:' : (' \"' .. &printdevice .. '\"')))
.. delete(v:fname_in)
On VMS machines the default is to send the file to either the default or
currently specified printdevice: >
system('print' . (&printdevice == '' ? '' : ' /queue=' .
&printdevice) . ' ' . v:fname_in) . delete(v:fname_in)
system('print' .. (&printdevice == '' ? '' : ' /queue=' ..
&printdevice) .. ' ' .. v:fname_in) .. delete(v:fname_in)
If you change this option, using a function is an easy way to avoid having to
escape all the spaces. Example: >
:set printexpr=PrintFile(v:fname_in)
:function PrintFile(fname)
: call system("ghostview " . a:fname)
: call system("ghostview " .. a:fname)
: call delete(a:fname)
: return v:shell_error
:endfunc

View File

@@ -1,4 +1,4 @@
*quickfix.txt* For Vim version 8.2. Last change: 2022 Feb 08
*quickfix.txt* For Vim version 8.2. Last change: 2022 Feb 22
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -353,7 +353,7 @@ processing a quickfix or location list command, it will be aborted.
cursor position will not be changed. See |:cexpr| for
more information.
Example: >
:g/mypattern/caddexpr expand("%") . ":" . line(".") . ":" . getline(".")
:g/mypattern/caddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")
<
*:lad* *:addd* *:laddexpr*
:lad[dexpr] {expr} Same as ":caddexpr", except the location list for the
@@ -654,6 +654,24 @@ quickfix window. If there already is a window for that file, it is used
instead. If the buffer in the used window has changed, and the error is in
another file, jumping to the error will fail. You will first have to make
sure the window contains a buffer which can be abandoned.
The following steps are used to find a window to open the file selected from
the quickfix window:
1. If 'switchbuf' contains "usetab", then find a window in any tabpage
(starting with the first tabpage) that has the selected file and jump to
it.
2. Otherwise find a window displaying the selected file in the current tab
page (starting with the window before the quickfix window) and use it.
3. Otherwise find a window displaying a normal buffer ('buftype' is empty)
starting with the window before the quickfix window. If a window is found,
open the file in that window.
4. If a usable window is not found and 'switchbuf' contains "uselast", then
open the file in the last used window.
5. Otherwise open the file in the window before the quickfix window. If there
is no previous window, then open the file in the next window.
6. If a usable window is not found in the above steps, then create a new
horizontally split window above the quickfix window and open the file.
*CTRL-W_<Enter>* *CTRL-W_<CR>*
You can use CTRL-W <Enter> to open a new window and jump to the error there.
@@ -663,7 +681,7 @@ FileType event (also see |qf.vim|). Then the BufReadPost event is triggered,
using "quickfix" for the buffer name. This can be used to perform some action
on the listed errors. Example: >
au BufReadPost quickfix setlocal modifiable
\ | silent exe 'g/^/s//\=line(".")." "/'
\ | silent exe 'g/^/s//\=line(".") .. " "/'
\ | setlocal nomodifiable
This prepends the line number to each line. Note the use of "\=" in the
substitute string of the ":s" command, which is used to evaluate an

View File

@@ -101,7 +101,7 @@ precedence, otherwise the 'cursorline' highlighting.
Here is an example that places a sign "piet", displayed with the text ">>", in
line 23 of the current file: >
:sign define piet text=>> texthl=Search
:exe ":sign place 2 line=23 name=piet file=" . expand("%:p")
:exe ":sign place 2 line=23 name=piet file=" .. expand("%:p")
And here is the command to delete it again: >
:sign unplace 2

View File

@@ -131,8 +131,8 @@ zuG Undo |zW| and |zG|, remove the word from the internal
rare as this is a fairly uncommon command and all
intuitive commands for this are already taken. If you
want you can add mappings with e.g.: >
nnoremap z? :exe ':spellrare ' . expand('<cWORD>')<CR>
nnoremap z/ :exe ':spellrare! ' . expand('<cWORD>')<CR>
nnoremap z? :exe ':spellrare ' .. expand('<cWORD>')<CR>
nnoremap z/ :exe ':spellrare! ' .. expand('<cWORD>')<CR>
< |:spellundo|, |zuw|, or |zuW| can be used to undo this.
:spellr[rare]! {word} Add {word} as a rare word to the internal word

View File

@@ -1378,7 +1378,7 @@ resulting file, when executed with a ":source" command:
After restoring the Session, the full filename of your current Session is
available in the internal variable "v:this_session" |this_session-variable|.
An example mapping: >
:nmap <F2> :wa<Bar>exe "mksession! " . v:this_session<CR>:so ~/sessions/
:nmap <F2> :wa<Bar>exe "mksession! " .. v:this_session<CR>:so ~/sessions/
This saves the current Session, and starts off the command to load another.
A session includes all tab pages, unless "tabpages" was removed from

View File

@@ -653,7 +653,7 @@ evaluate to get a unique string to append to each ID used in a given document,
so that the full IDs will be unique even when combined with other content in a
larger HTML document. Example, to append _ and the buffer number to each ID: >
:let g:html_id_expr = '"_".bufnr("%")'
:let g:html_id_expr = '"_" .. bufnr("%")'
<
To append a string "_mystring" to the end of each ID: >
@@ -3607,8 +3607,8 @@ Do you want to draw with the mouse? Try the following: >
:function! GetPixel()
: let c = getline(".")[col(".") - 1]
: echo c
: exe "noremap <LeftMouse> <LeftMouse>r".c
: exe "noremap <LeftDrag> <LeftMouse>r".c
: exe "noremap <LeftMouse> <LeftMouse>r" .. c
: exe "noremap <LeftDrag> <LeftMouse>r" .. c
:endfunction
:noremap <RightMouse> <LeftMouse>:call GetPixel()<CR>
:set guicursor=n:hor20 " to see the color beneath the cursor
@@ -5567,9 +5567,9 @@ types.vim: *.[ch]
And put these lines in your .vimrc: >
" load the types.vim highlighting file, if it exists
autocmd BufRead,BufNewFile *.[ch] let fname = expand('<afile>:p:h') . '/types.vim'
autocmd BufRead,BufNewFile *.[ch] let fname = expand('<afile>:p:h') .. '/types.vim'
autocmd BufRead,BufNewFile *.[ch] if filereadable(fname)
autocmd BufRead,BufNewFile *.[ch] exe 'so ' . fname
autocmd BufRead,BufNewFile *.[ch] exe 'so ' .. fname
autocmd BufRead,BufNewFile *.[ch] endif
==============================================================================

View File

@@ -381,24 +381,24 @@ pages and define labels for them. Then get the label for each tab page. >
for i in range(tabpagenr('$'))
" select the highlighting
if i + 1 == tabpagenr()
let s .= '%#TabLineSel#'
let s ..= '%#TabLineSel#'
else
let s .= '%#TabLine#'
let s ..= '%#TabLine#'
endif
" set the tab page number (for mouse clicks)
let s .= '%' . (i + 1) . 'T'
let s ..= '%' .. (i + 1) .. 'T'
" the label is made by MyTabLabel()
let s .= ' %{MyTabLabel(' . (i + 1) . ')} '
let s ..= ' %{MyTabLabel(' .. (i + 1) .. ')} '
endfor
" after the last tab fill with TabLineFill and reset tab page nr
let s .= '%#TabLineFill#%T'
let s ..= '%#TabLineFill#%T'
" right-align the label to close the current tab page
if tabpagenr('$') > 1
let s .= '%=%#TabLine#%999Xclose'
let s ..= '%=%#TabLine#%999Xclose'
endif
return s
@@ -461,14 +461,14 @@ windows in the tab page and a '+' if there is a modified buffer: >
" Append the number of windows in the tab page if more than one
let wincount = tabpagewinnr(v:lnum, '$')
if wincount > 1
let label .= wincount
let label ..= wincount
endif
if label != ''
let label .= ' '
let label ..= ' '
endif
" Append the buffer name
return label . bufname(bufnrlist[tabpagewinnr(v:lnum) - 1])
return label .. bufname(bufnrlist[tabpagewinnr(v:lnum) - 1])
endfunction
set guitablabel=%{GuiTabLabel()}

View File

@@ -1355,6 +1355,7 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX*
+mouse various.txt /*+mouse*
+mouse_dec various.txt /*+mouse_dec*
+mouse_gpm various.txt /*+mouse_gpm*
+mouse_gpm/dyn various.txt /*+mouse_gpm\/dyn*
+mouse_jsbterm various.txt /*+mouse_jsbterm*
+mouse_netterm various.txt /*+mouse_netterm*
+mouse_pterm various.txt /*+mouse_pterm*
@@ -5861,6 +5862,7 @@ bug-fixes-5 version5.txt /*bug-fixes-5*
bug-fixes-6 version6.txt /*bug-fixes-6*
bug-fixes-7 version7.txt /*bug-fixes-7*
bug-fixes-8 version8.txt /*bug-fixes-8*
bug-fixes-9 version9.txt /*bug-fixes-9*
bug-reports intro.txt /*bug-reports*
bugreport.vim intro.txt /*bugreport.vim*
bugs intro.txt /*bugs*
@@ -6171,6 +6173,7 @@ compile-changes-5 version5.txt /*compile-changes-5*
compile-changes-6 version6.txt /*compile-changes-6*
compile-changes-7 version7.txt /*compile-changes-7*
compile-changes-8 version8.txt /*compile-changes-8*
compile-changes-9 version9.txt /*compile-changes-9*
compiler-compaqada ft_ada.txt /*compiler-compaqada*
compiler-decada ft_ada.txt /*compiler-decada*
compiler-gcc quickfix.txt /*compiler-gcc*
@@ -7820,6 +7823,7 @@ improvements-5 version5.txt /*improvements-5*
improvements-6 version6.txt /*improvements-6*
improvements-7 version7.txt /*improvements-7*
improvements-8 version8.txt /*improvements-8*
improvements-9 version9.txt /*improvements-9*
in_bot channel.txt /*in_bot*
in_buf channel.txt /*in_buf*
in_io-buffer channel.txt /*in_io-buffer*
@@ -7835,6 +7839,7 @@ incompatible-5 version5.txt /*incompatible-5*
incompatible-6 version6.txt /*incompatible-6*
incompatible-7 version7.txt /*incompatible-7*
incompatible-8 version8.txt /*incompatible-8*
incompatible-9 version9.txt /*incompatible-9*
indent() builtin.txt /*indent()*
indent-expression indent.txt /*indent-expression*
indent.txt indent.txt /*indent.txt*
@@ -8543,6 +8548,7 @@ new-5 version5.txt /*new-5*
new-6 version6.txt /*new-6*
new-7 version7.txt /*new-7*
new-8 version8.txt /*new-8*
new-9 version9.txt /*new-9*
new-GTK-GUI version5.txt /*new-GTK-GUI*
new-MzScheme version7.txt /*new-MzScheme*
new-Select-mode version5.txt /*new-Select-mode*
@@ -8576,6 +8582,7 @@ new-indent-flex version6.txt /*new-indent-flex*
new-items-6 version6.txt /*new-items-6*
new-items-7 version7.txt /*new-items-7*
new-items-8 version8.txt /*new-items-8*
new-items-9 version9.txt /*new-items-9*
new-line-continuation version5.txt /*new-line-continuation*
new-location-list version7.txt /*new-location-list*
new-lua version7.txt /*new-lua*
@@ -8625,6 +8632,7 @@ new-utf-8 version6.txt /*new-utf-8*
new-vertsplit version6.txt /*new-vertsplit*
new-vim-script version7.txt /*new-vim-script*
new-vim-script-8 version8.txt /*new-vim-script-8*
new-vim-script-9 version9.txt /*new-vim-script-9*
new-vim-server version6.txt /*new-vim-server*
new-vimgrep version7.txt /*new-vimgrep*
new-vimscript-8.2 version8.txt /*new-vimscript-8.2*
@@ -8743,7 +8751,8 @@ pascal.vim syntax.txt /*pascal.vim*
patches-8 version8.txt /*patches-8*
patches-8.1 version8.txt /*patches-8.1*
patches-8.2 version8.txt /*patches-8.2*
patches-after-8.2 version8.txt /*patches-after-8.2*
patches-9 version9.txt /*patches-9*
patches-after-8.2 version9.txt /*patches-after-8.2*
pathshorten() builtin.txt /*pathshorten()*
pattern pattern.txt /*pattern*
pattern-atoms pattern.txt /*pattern-atoms*
@@ -10011,6 +10020,7 @@ terminal.txt terminal.txt /*terminal.txt*
terminalprops() builtin.txt /*terminalprops()*
terminfo term.txt /*terminfo*
termresponse-variable eval.txt /*termresponse-variable*
ternary eval.txt /*ternary*
test-functions usr_41.txt /*test-functions*
test-functions-details testing.txt /*test-functions-details*
test_alloc_fail() testing.txt /*test_alloc_fail()*
@@ -10102,7 +10112,6 @@ tooltips gui.txt /*tooltips*
toupper() builtin.txt /*toupper()*
tr() builtin.txt /*tr()*
trim() builtin.txt /*trim()*
trinary eval.txt /*trinary*
trojan-horse starting.txt /*trojan-horse*
true vim9.txt /*true*
true-variable eval.txt /*true-variable*
@@ -10457,6 +10466,7 @@ version-7.4 version7.txt /*version-7.4*
version-8.0 version8.txt /*version-8.0*
version-8.1 version8.txt /*version-8.1*
version-8.2 version8.txt /*version-8.2*
version-9.0 version9.txt /*version-9.0*
version-variable eval.txt /*version-variable*
version4.txt version4.txt /*version4.txt*
version5.txt version5.txt /*version5.txt*
@@ -10471,6 +10481,8 @@ version8.0 version8.txt /*version8.0*
version8.1 version8.txt /*version8.1*
version8.2 version8.txt /*version8.2*
version8.txt version8.txt /*version8.txt*
version9.0 version9.txt /*version9.0*
version9.txt version9.txt /*version9.txt*
versionlong-variable eval.txt /*versionlong-variable*
vi intro.txt /*vi*
vi-differences vi_diff.txt /*vi-differences*
@@ -10486,6 +10498,8 @@ vim-7.4 version7.txt /*vim-7.4*
vim-8 version8.txt /*vim-8*
vim-8.1 version8.txt /*vim-8.1*
vim-8.2 version8.txt /*vim-8.2*
vim-9 version9.txt /*vim-9*
vim-9.0 version9.txt /*vim-9.0*
vim-additions vi_diff.txt /*vim-additions*
vim-announce intro.txt /*vim-announce*
vim-arguments starting.txt /*vim-arguments*

View File

@@ -724,7 +724,7 @@ matches the pattern "^# *define" it is not considered to be a comment.
If you want to list matches, and then select one to jump to, you could use a
mapping to do that for you. Here is an example: >
:map <F4> [I:let nr = input("Which one: ")<Bar>exe "normal " . nr ."[\t"<CR>
:map <F4> [I:let nr = input("Which one: ")<Bar>exe "normal " .. nr .. "[\t"<CR>
<
*[i*
[i Display the first line that contains the keyword

View File

@@ -984,7 +984,7 @@ an #if/#else/#endif block, the selection becomes linewise.
For MS-Windows and xterm the time for double clicking can be set with the
'mousetime' option. For the other systems this time is defined outside of Vim.
An example, for using a double click to jump to the tag under the cursor: >
:map <2-LeftMouse> :exe "tag ". expand("<cword>")<CR>
:map <2-LeftMouse> :exe "tag " .. expand("<cword>")<CR>
Dragging the mouse with a double click (button-down, button-up, button-down
and then drag) will result in whole words to be selected. This continues

View File

@@ -979,8 +979,8 @@ Currently supported commands:
< Calls a function defined like this: >
function Tapi_Impression(bufnum, arglist)
if len(a:arglist) == 2
echomsg "impression " . a:arglist[0]
echomsg "count " . a:arglist[1]
echomsg "impression " .. a:arglist[0]
echomsg "count " .. a:arglist[1]
endif
endfunc
< Output from `:echo` may be erased by a redraw, use `:echomsg`

View File

@@ -101,14 +101,14 @@ What you need:
create it with the shell command "mkid file1 file2 ..".
Put this in your .vimrc: >
map _u :call ID_search()<Bar>execute "/\\<" . g:word . "\\>"<CR>
map _n :n<Bar>execute "/\\<" . g:word . "\\>"<CR>
map _u :call ID_search()<Bar>execute "/\\<" .. g:word .. "\\>"<CR>
map _n :n<Bar>execute "/\\<" .. g:word .. "\\>"<CR>
function! ID_search()
let g:word = expand("<cword>")
let x = system("lid --key=none ". g:word)
let x = system("lid --key=none " .. g:word)
let x = substitute(x, "\n", " ", "g")
execute "next " . x
execute "next " .. x
endfun
To use it, place the cursor on a word, type "_u" and vim will load the file
@@ -356,13 +356,13 @@ This mapping will format any bullet list. It requires that there is an empty
line above and below each list entry. The expression commands are used to
be able to give comments to the parts of the mapping. >
:let m = ":map _f :set ai<CR>" " need 'autoindent' set
:let m = m . "{O<Esc>" " add empty line above item
:let m = m . "}{)^W" " move to text after bullet
:let m = m . "i <CR> <Esc>" " add space for indent
:let m = m . "gq}" " format text after the bullet
:let m = m . "{dd" " remove the empty line
:let m = m . "5lDJ" " put text after bullet
:let m = ":map _f :set ai<CR>" " need 'autoindent' set
:let m ..= "{O<Esc>" " add empty line above item
:let m ..= "}{)^W" " move to text after bullet
:let m ..= "i <CR> <Esc>" " add space for indent
:let m ..= "gq}" " format text after the bullet
:let m ..= "{dd" " remove the empty line
:let m ..= "5lDJ" " put text after bullet
:execute m |" define the mapping
(<> notation |<>|. Note that this is all typed literally. ^W is "^" "W", not
@@ -514,15 +514,15 @@ A slightly more advanced version is used in the |matchparen| plugin.
let c = '\['
let c2 = '\]'
endif
let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' .
let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' ..
\ '=~? "string\\|comment"'
execute 'if' s_skip '| let s_skip = 0 | endif'
let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip)
if m_lnum > 0 && m_lnum >= line('w0') && m_lnum <= line('w$')
exe 'match Search /\(\%' . c_lnum . 'l\%' . c_col .
\ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/'
exe 'match Search /\(\%' .. c_lnum .. 'l\%' .. c_col ..
\ 'c\)\|\(\%' .. m_lnum .. 'l\%' .. m_col .. 'c\)/'
let s:paren_hl_on = 1
endif
endfunction

View File

@@ -286,12 +286,12 @@ history file. E.g.: >
au BufReadPost * call ReadUndo()
au BufWritePost * call WriteUndo()
func ReadUndo()
if filereadable(expand('%:h'). '/UNDO/' . expand('%:t'))
if filereadable(expand('%:h') .. '/UNDO/' .. expand('%:t'))
rundo %:h/UNDO/%:t
endif
endfunc
func WriteUndo()
let dirname = expand('%:h') . '/UNDO'
let dirname = expand('%:h') .. '/UNDO'
if !isdirectory(dirname)
call mkdir(dirname)
endif

View File

@@ -270,7 +270,7 @@ line break. Revert with ":iunmap <C-U>".
Enable using the mouse if available. See 'mouse'.
>
vnoremap _g y:exe "grep /" . escape(@", '\\/') . "/ *.c *.h"<CR>
vnoremap _g y:exe "grep /" .. escape(@", '\\/') .. "/ *.c *.h"<CR>
This mapping yanks the visually selected text and searches for it in C files.
You can see that a mapping can be used to do quite complicated things. Still,

View File

@@ -267,7 +267,7 @@ g8 Print the hex values of the bytes used in the
name does not contain a single quote: >
:!ls '%'
< This should always work, but it's more typing: >
:exe "!ls " . shellescape(expand("%"))
:exe "!ls " .. shellescape(expand("%"))
< To get a literal "%" or "#" prepend it with a
backslash. For example, to list all files starting
with "%": >
@@ -650,7 +650,7 @@ N *+X11* Unix only: can restore window title |X11|
used. In this example |:silent| is used to avoid the
message about reading the file and |:unsilent| to be
able to list the first line of each file. >
:silent argdo unsilent echo expand('%') . ": " . getline(1)
:silent argdo unsilent echo expand('%') .. ": " .. getline(1)
<
*:verb* *:verbose*

File diff suppressed because it is too large Load Diff

26799
runtime/doc/version9.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
*vim9.txt* For Vim version 8.2. Last change: 2022 Feb 22
*vim9.txt* For Vim version 8.2. Last change: 2022 Feb 23
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -229,8 +229,17 @@ script "export" needs to be used. >
< *E1058* *E1075*
When using `:function` or `:def` to specify a nested function inside a `:def`
function and no namespace was given, this nested function is local to the code
block it is defined in. It is not possible to define a script-local function.
It is possible to define a global function by using the "g:" prefix.
block it is defined in. It cannot be used in `function()` with a string
argument, pass the function reference itself: >
def Outer()
def Inner()
echo 'inner'
enddef
var Fok = function(Inner) # OK
var Fbad = function('Inner') # does not work
It is not possible to define a script-local function. It is possible to
define a global function by using the "g:" prefix.
When referring to a function and no "s:" or "g:" prefix is used, Vim will
search for the function:

View File

@@ -473,7 +473,7 @@ These commands can also be executed with ":wincmd":
the |CursorHold| autocommand event). Or when a Normal mode
command is inconvenient.
The count can also be a window number. Example: >
:exe nr . "wincmd w"
:exe nr .. "wincmd w"
< This goes to window "nr".
==============================================================================
@@ -964,12 +964,12 @@ CTRL-W g } *CTRL-W_g}*
cursor. This is less clever than using |:ptag|, but you don't
need a tags file and it will also find matches in system
include files. Example: >
:au! CursorHold *.[ch] ++nested exe "silent! psearch " . expand("<cword>")
:au! CursorHold *.[ch] ++nested exe "silent! psearch " .. expand("<cword>")
< Warning: This can be slow.
Example *CursorHold-example* >
:au! CursorHold *.[ch] ++nested exe "silent! ptag " . expand("<cword>")
:au! CursorHold *.[ch] ++nested exe "silent! ptag " .. expand("<cword>")
This will cause a ":ptag" to be executed for the keyword under the cursor,
when the cursor hasn't moved for the time set with 'updatetime'. The "nested"
@@ -992,14 +992,14 @@ is no word under the cursor, and a few other things: >
:
: " Delete any existing highlight before showing another tag
: silent! wincmd P " jump to preview window
: if &previewwindow " if we really get there...
: if &previewwindow " if we really get there...
: match none " delete existing highlight
: wincmd p " back to old window
: endif
:
: " Try displaying a matching tag for the word under the cursor
: try
: exe "ptag " . w
: exe "ptag " .. w
: catch
: return
: endtry
@@ -1011,10 +1011,10 @@ is no word under the cursor, and a few other things: >
: endif
: call search("$", "b") " to end of previous line
: let w = substitute(w, '\\', '\\\\', "")
: call search('\<\V' . w . '\>') " position cursor on match
: call search('\<\V' .. w .. '\>') " position cursor on match
: " Add a match highlight to the word at this position
: hi previewWord term=bold ctermbg=green guibg=green
: exe 'match previewWord "\%' . line(".") . 'l\%' . col(".") . 'c\k*"'
: exe 'match previewWord "\%' .. line(".") .. 'l\%' .. col(".") .. 'c\k*"'
: wincmd p " back to old window
: endif
: endif

View File

@@ -1,7 +1,7 @@
" Vim indent file
" Language: Vim script
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2021 Nov 27
" Last Change: 2022 Feb 23
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
@@ -10,7 +10,7 @@ endif
let b:did_indent = 1
setlocal indentexpr=GetVimIndent()
setlocal indentkeys+==end,=},=else,=cat,=finall,=END,0\\,0=\"\\\
setlocal indentkeys+==endif,=enddef,=endfu,=endfor,=endwh,=endtry,=},=else,=cat,=finall,=END,0\\,0=\"\\\
setlocal indentkeys-=0#
setlocal indentkeys-=:
@@ -103,8 +103,9 @@ function GetVimIndentIntern()
" A line starting with :au does not increment/decrement indent.
" A { may start a block or a dict. Assume that when a } follows it's a
" terminated dict.
" ":function" starts a block but "function(" doesn't.
if prev_text !~ '^\s*au\%[tocmd]' && prev_text !~ '^\s*{.*}'
let i = match(prev_text, '\(^\||\)\s*\(export\s\+\)\?\({\|\(if\|wh\%[ile]\|for\|try\|cat\%[ch]\|fina\|finall\%[y]\|fu\%[nction]\|def\|el\%[seif]\)\>\)')
let i = match(prev_text, '\(^\||\)\s*\(export\s\+\)\?\({\|\(if\|wh\%[ile]\|for\|try\|cat\%[ch]\|fina\|finall\%[y]\|def\|el\%[seif]\)\>\|fu\%[nction]\s\)')
if i >= 0
let ind += shiftwidth()
if strpart(prev_text, i, 1) == '|' && has('syntax_items')
@@ -170,10 +171,15 @@ function GetVimIndentIntern()
let ind = ind + shiftwidth()
endif
" Subtract a 'shiftwidth' on a :endif, :endwhile, :catch, :finally, :endtry,
" :endfun, :enddef, :else and :augroup END.
if cur_text =~ '^\s*\(ene\@!\|cat\|finall\|el\|aug\%[roup]\s\+[eE][nN][dD]\)'
" Subtract a 'shiftwidth' on a :endif, :endwhile, :endfor, :catch, :finally,
" :endtry, :endfun, :enddef, :else and :augroup END.
" Although ":en" would be enough only match short command names as in
" 'indentkeys'.
if cur_text =~ '^\s*\(endif\|endwh\|endfor\|endtry\|endfu\|enddef\|cat\|finall\|else\|aug\%[roup]\s\+[eE][nN][dD]\)'
let ind = ind - shiftwidth()
if ind < 0
let ind = 0
endif
endif
return ind

View File

@@ -2814,38 +2814,39 @@ ExpandBufnames(
}
}
if (p != NULL)
{
if (round == 1)
++count;
else
{
if (options & WILD_HOME_REPLACE)
p = home_replace_save(buf, p);
else
p = vim_strsave(p);
if (p == NULL)
continue;
if (!fuzzy)
{
if (round == 1)
{
++count;
continue;
}
if (options & WILD_HOME_REPLACE)
p = home_replace_save(buf, p);
else
p = vim_strsave(p);
if (!fuzzy)
{
#ifdef FEAT_VIMINFO
if (matches != NULL)
{
matches[count].buf = buf;
matches[count].match = p;
count++;
}
else
#endif
(*file)[count++] = p;
}
else
{
fuzmatch[count].idx = count;
fuzmatch[count].str = p;
fuzmatch[count].score = score;
count++;
}
if (matches != NULL)
{
matches[count].buf = buf;
matches[count].match = p;
count++;
}
else
#endif
(*file)[count++] = p;
}
else
{
fuzmatch[count].idx = count;
fuzmatch[count].str = p;
fuzmatch[count].score = score;
count++;
}
}
if (count == 0) // no match found, break here

View File

@@ -16,15 +16,14 @@
static int cmd_showtail; // Only show path tail in lists ?
static void set_expand_context(expand_T *xp);
static int ExpandGeneric(expand_T *xp, regmatch_T *regmatch,
static int ExpandGeneric(char_u *pat, expand_T *xp, regmatch_T *regmatch,
char_u ***matches, int *numMatches,
char_u *((*func)(expand_T *, int)), int escaped,
char_u *fuzzystr);
char_u *((*func)(expand_T *, int)), int escaped);
static int ExpandFromContext(expand_T *xp, char_u *, char_u ***, int *, int);
static int expand_showtail(expand_T *xp);
static int expand_shellcmd(char_u *filepat, char_u ***matches, int *numMatches, int flagsarg);
#if defined(FEAT_EVAL)
static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char_u ***matches, int *numMatches);
static int ExpandUserDefined(char_u *pat, expand_T *xp, regmatch_T *regmatch, char_u ***matches, int *numMatches);
static int ExpandUserList(expand_T *xp, char_u ***matches, int *numMatches);
#endif
@@ -56,20 +55,19 @@ cmdline_fuzzy_completion_supported(expand_T *xp)
&& xp->xp_context != EXPAND_FILES_IN_PATH
&& xp->xp_context != EXPAND_FILETYPE
&& xp->xp_context != EXPAND_HELP
&& xp->xp_context != EXPAND_MAPPINGS
&& xp->xp_context != EXPAND_OLD_SETTING
&& xp->xp_context != EXPAND_OWNSYNTAX
&& xp->xp_context != EXPAND_PACKADD
&& xp->xp_context != EXPAND_SHELLCMD
&& xp->xp_context != EXPAND_TAGS
&& xp->xp_context != EXPAND_TAGS_LISTFILES
&& xp->xp_context != EXPAND_USER_DEFINED
&& xp->xp_context != EXPAND_USER_LIST);
}
/*
* Returns TRUE if fuzzy completion for cmdline completion is enabled and
* 'fuzzystr' is not empty.
* 'fuzzystr' is not empty. If search pattern is empty, then don't use fuzzy
* matching.
*/
int
cmdline_fuzzy_complete(char_u *fuzzystr)
@@ -378,9 +376,13 @@ int cmdline_pum_active(void)
*/
void cmdline_pum_remove(void)
{
int save_p_lz = p_lz;
pum_undisplay();
VIM_CLEAR(compl_match_array);
p_lz = FALSE; // avoid the popup menu hanging around
update_screen(0);
p_lz = save_p_lz;
redrawcmd();
}
@@ -1216,10 +1218,12 @@ set_cmd_index(char_u *cmd, exarg_T *eap, expand_T *xp, int *complp)
// Isolate the command and search for it in the command table.
// Exceptions:
// - the 'k' command can directly be followed by any character, but
// do accept "keepmarks", "keepalt" and "keepjumps".
// - the 'k' command can directly be followed by any character, but do
// accept "keepmarks", "keepalt" and "keepjumps". As fuzzy matching can
// find matches anywhere in the command name, do this only for command
// expansion based on regular expression and not for fuzzy matching.
// - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
if (*cmd == 'k' && cmd[1] != 'e')
if (!fuzzy && (*cmd == 'k' && cmd[1] != 'e'))
{
eap->cmdidx = CMD_k;
p = cmd + 1;
@@ -2370,7 +2374,7 @@ get_mapclear_arg(expand_T *xp UNUSED, int idx)
static int
ExpandOther(
char_u *pat,
expand_T *xp,
expand_T *xp,
regmatch_T *rmp,
char_u ***matches,
int *numMatches)
@@ -2439,16 +2443,10 @@ ExpandOther(
{
if (xp->xp_context == tab[i].context)
{
// Use fuzzy matching if 'wildoptions' has 'fuzzy'.
// If no search pattern is supplied, then don't use fuzzy
// matching and return all the found items.
int fuzzy = cmdline_fuzzy_complete(pat);
if (tab[i].ic)
rmp->rm_ic = TRUE;
ret = ExpandGeneric(xp, rmp, matches, numMatches,
tab[i].func, tab[i].escaped,
fuzzy ? pat : NULL);
ret = ExpandGeneric(pat, xp, rmp, matches, numMatches,
tab[i].func, tab[i].escaped);
break;
}
}
@@ -2496,7 +2494,8 @@ ExpandFromContext(
int ret;
int flags;
char_u *tofree = NULL;
int fuzzy = cmdline_fuzzy_complete(pat);
int fuzzy = cmdline_fuzzy_complete(pat)
&& cmdline_fuzzy_completion_supported(xp);
flags = map_wildopts_to_ewflags(options);
@@ -2595,10 +2594,10 @@ ExpandFromContext(
|| xp->xp_context == EXPAND_BOOL_SETTINGS)
ret = ExpandSettings(xp, &regmatch, pat, numMatches, matches);
else if (xp->xp_context == EXPAND_MAPPINGS)
ret = ExpandMappings(&regmatch, numMatches, matches);
ret = ExpandMappings(pat, &regmatch, numMatches, matches);
# if defined(FEAT_EVAL)
else if (xp->xp_context == EXPAND_USER_DEFINED)
ret = ExpandUserDefined(xp, &regmatch, matches, numMatches);
ret = ExpandUserDefined(pat, xp, &regmatch, matches, numMatches);
# endif
else
ret = ExpandOther(pat, xp, &regmatch, matches, numMatches);
@@ -2624,123 +2623,144 @@ ExpandFromContext(
*/
static int
ExpandGeneric(
char_u *pat,
expand_T *xp,
regmatch_T *regmatch,
char_u ***matches,
int *numMatches,
char_u *((*func)(expand_T *, int)),
// returns a string from the list
int escaped,
char_u *fuzzystr)
int escaped)
{
int i;
int count = 0;
int round;
garray_T ga;
char_u *str;
fuzmatch_str_T *fuzmatch = NULL;
int score = 0;
int fuzzy = (fuzzystr != NULL);
int funcsort = FALSE;
int score = 0;
int fuzzy;
int match;
// do this loop twice:
// round == 0: count the number of matching names
// round == 1: copy the matching names into allocated memory
for (round = 0; round <= 1; ++round)
{
for (i = 0; ; ++i)
{
str = (*func)(xp, i);
if (str == NULL) // end of list
break;
if (*str == NUL) // skip empty strings
continue;
fuzzy = cmdline_fuzzy_complete(pat);
*matches = NULL;
*numMatches = 0;
if (!fuzzy)
ga_init2(&ga, sizeof(char *), 30);
else
ga_init2(&ga, sizeof(fuzmatch_str_T), 30);
for (i = 0; ; ++i)
{
str = (*func)(xp, i);
if (str == NULL) // end of list
break;
if (*str == NUL) // skip empty strings
continue;
if (xp->xp_pattern[0] != NUL)
{
if (!fuzzy)
match = vim_regexec(regmatch, str, (colnr_T)0);
match = vim_regexec(regmatch, str, (colnr_T)0);
else
{
score = fuzzy_match_str(str, fuzzystr);
score = fuzzy_match_str(str, pat);
match = (score != 0);
}
if (!match)
continue;
if (round)
{
if (escaped)
str = vim_strsave_escaped(str, (char_u *)" \t\\.");
else
str = vim_strsave(str);
if (str == NULL)
{
if (fuzzy)
fuzmatch_str_free(fuzmatch, count);
else if (count > 0)
FreeWild(count, *matches);
*numMatches = 0;
*matches = NULL;
return FAIL;
}
if (fuzzy)
{
fuzmatch[count].idx = count;
fuzmatch[count].str = str;
fuzmatch[count].score = score;
}
else
(*matches)[count] = str;
# ifdef FEAT_MENU
if (func == get_menu_names && str != NULL)
{
// test for separator added by get_menu_names()
str += STRLEN(str) - 1;
if (*str == '\001')
*str = '.';
}
# endif
}
++count;
}
if (round == 0)
else
match = TRUE;
if (!match)
continue;
if (escaped)
str = vim_strsave_escaped(str, (char_u *)" \t\\.");
else
str = vim_strsave(str);
if (str == NULL)
{
if (count == 0)
return OK;
if (fuzzy)
fuzmatch = ALLOC_MULT(fuzmatch_str_T, count);
else
*matches = ALLOC_MULT(char_u *, count);
if ((fuzzy && (fuzmatch == NULL)) || (*matches == NULL))
if (!fuzzy)
{
*numMatches = 0;
*matches = NULL;
ga_clear_strings(&ga);
return FAIL;
}
*numMatches = count;
count = 0;
for (i = 0; i < ga.ga_len; ++i)
{
fuzmatch = &((fuzmatch_str_T *)ga.ga_data)[i];
vim_free(fuzmatch->str);
}
ga_clear(&ga);
return FAIL;
}
if (ga_grow(&ga, 1) == FAIL)
{
vim_free(str);
break;
}
if (fuzzy)
{
fuzmatch = &((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
fuzmatch->idx = ga.ga_len;
fuzmatch->str = str;
fuzmatch->score = score;
}
else
((char_u **)ga.ga_data)[ga.ga_len] = str;
# ifdef FEAT_MENU
if (func == get_menu_names)
{
// test for separator added by get_menu_names()
str += STRLEN(str) - 1;
if (*str == '\001')
*str = '.';
}
# endif
++ga.ga_len;
}
if (ga.ga_len == 0)
return OK;
// Sort the results. Keep menu's in the specified order.
if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS)
if (!fuzzy && xp->xp_context != EXPAND_MENUNAMES
&& xp->xp_context != EXPAND_MENUS)
{
if (xp->xp_context == EXPAND_EXPRESSION
|| xp->xp_context == EXPAND_FUNCTIONS
|| xp->xp_context == EXPAND_USER_FUNC
|| xp->xp_context == EXPAND_DISASSEMBLE)
{
// <SNR> functions should be sorted to the end.
qsort((void *)ga.ga_data, (size_t)ga.ga_len, sizeof(char_u *),
sort_func_compare);
else
sort_strings((char_u **)ga.ga_data, ga.ga_len);
}
if (!fuzzy)
{
*matches = ga.ga_data;
*numMatches = ga.ga_len;
}
else
{
int funcsort = FALSE;
if (xp->xp_context == EXPAND_EXPRESSION
|| xp->xp_context == EXPAND_FUNCTIONS
|| xp->xp_context == EXPAND_USER_FUNC
|| xp->xp_context == EXPAND_DISASSEMBLE)
// <SNR> functions should be sorted to the end.
funcsort = TRUE;
if (!fuzzy)
qsort((void *)*matches, (size_t)*numMatches, sizeof(char_u *),
sort_func_compare);
}
else
{
if (!fuzzy)
sort_strings(*matches, *numMatches);
}
if (fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len,
funcsort) == FAIL)
return FAIL;
*numMatches = ga.ga_len;
}
#if defined(FEAT_SYN_HL)
@@ -2749,10 +2769,6 @@ ExpandGeneric(
reset_expand_highlight();
#endif
if (fuzzy && fuzzymatches_to_strmatches(fuzmatch, matches, count,
funcsort) == FAIL)
return FAIL;
return OK;
}
@@ -2969,10 +2985,12 @@ call_user_expand_func(
}
/*
* Expand names with a function defined by the user.
* Expand names with a function defined by the user (EXPAND_USER_DEFINED and
* EXPAND_USER_LIST).
*/
static int
ExpandUserDefined(
char_u *pat,
expand_T *xp,
regmatch_T *regmatch,
char_u ***matches,
@@ -2983,15 +3001,23 @@ ExpandUserDefined(
char_u *e;
int keep;
garray_T ga;
int skip;
int fuzzy;
int match;
int score = 0;
fuzzy = cmdline_fuzzy_complete(pat);
*matches = NULL;
*numMatches = 0;
retstr = call_user_expand_func(call_func_retstr, xp);
if (retstr == NULL)
return FAIL;
ga_init2(&ga, sizeof(char *), 3);
if (!fuzzy)
ga_init2(&ga, sizeof(char *), 3);
else
ga_init2(&ga, sizeof(fuzmatch_str_T), 3);
for (s = retstr; *s != NUL; s = e)
{
e = vim_strchr(s, '\n');
@@ -3000,14 +3026,35 @@ ExpandUserDefined(
keep = *e;
*e = NUL;
skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0;
if (xp->xp_pattern[0] != NUL)
{
if (!fuzzy)
match = vim_regexec(regmatch, s, (colnr_T)0);
else
{
score = fuzzy_match_str(s, pat);
match = (score != 0);
}
}
else
match = TRUE; // match everything
*e = keep;
if (!skip)
if (match)
{
if (ga_grow(&ga, 1) == FAIL)
break;
((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, e - s);
if (!fuzzy)
((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, e - s);
else
{
fuzmatch_str_T *fuzmatch =
&((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
fuzmatch->idx = ga.ga_len;
fuzmatch->str = vim_strnsave(s, e - s);
fuzmatch->score = score;
}
++ga.ga_len;
}
@@ -3015,8 +3062,22 @@ ExpandUserDefined(
++e;
}
vim_free(retstr);
*matches = ga.ga_data;
*numMatches = ga.ga_len;
if (ga.ga_len == 0)
return OK;
if (!fuzzy)
{
*matches = ga.ga_data;
*numMatches = ga.ga_len;
}
else
{
if (fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len,
FALSE) == FAIL)
return FAIL;
*numMatches = ga.ga_len;
}
return OK;
}

View File

@@ -2816,29 +2816,33 @@ eval_variable(
}
// If a list or dict variable wasn't initialized, do it now.
if (tv->v_type == VAR_DICT && tv->vval.v_dict == NULL)
// Not for global variables, they are not declared.
if (ht != &globvarht)
{
tv->vval.v_dict = dict_alloc();
if (tv->vval.v_dict != NULL)
if (tv->v_type == VAR_DICT && tv->vval.v_dict == NULL)
{
++tv->vval.v_dict->dv_refcount;
tv->vval.v_dict->dv_type = alloc_type(type);
tv->vval.v_dict = dict_alloc();
if (tv->vval.v_dict != NULL)
{
++tv->vval.v_dict->dv_refcount;
tv->vval.v_dict->dv_type = alloc_type(type);
}
}
}
else if (tv->v_type == VAR_LIST && tv->vval.v_list == NULL)
{
tv->vval.v_list = list_alloc();
if (tv->vval.v_list != NULL)
else if (tv->v_type == VAR_LIST && tv->vval.v_list == NULL)
{
++tv->vval.v_list->lv_refcount;
tv->vval.v_list->lv_type = alloc_type(type);
tv->vval.v_list = list_alloc();
if (tv->vval.v_list != NULL)
{
++tv->vval.v_list->lv_refcount;
tv->vval.v_list->lv_type = alloc_type(type);
}
}
else if (tv->v_type == VAR_BLOB && tv->vval.v_blob == NULL)
{
tv->vval.v_blob = blob_alloc();
if (tv->vval.v_blob != NULL)
++tv->vval.v_blob->bv_refcount;
}
}
else if (tv->v_type == VAR_BLOB && tv->vval.v_blob == NULL)
{
tv->vval.v_blob = blob_alloc();
if (tv->vval.v_blob != NULL)
++tv->vval.v_blob->bv_refcount;
}
copy_tv(tv, rettv);
}

View File

@@ -3016,7 +3016,7 @@ is_point_onscreen(int x, int y)
}
/*
* Check if the whole area of the specified window is on-screen.
* Check if the whole client area of the specified window is on-screen.
*
* Note about DirectX: Windows 10 1809 or above no longer maintains image of
* the window portion that is off-screen. Scrolling by DWriteContext_Scroll()
@@ -3026,16 +3026,23 @@ is_point_onscreen(int x, int y)
is_window_onscreen(HWND hwnd)
{
RECT rc;
POINT p1, p2;
GetWindowRect(hwnd, &rc);
GetClientRect(hwnd, &rc);
p1.x = rc.left;
p1.y = rc.top;
p2.x = rc.right - 1;
p2.y = rc.bottom - 1;
ClientToScreen(hwnd, &p1);
ClientToScreen(hwnd, &p2);
if (!is_point_onscreen(rc.left, rc.top))
if (!is_point_onscreen(p1.x, p1.y))
return FALSE;
if (!is_point_onscreen(rc.left, rc.bottom))
if (!is_point_onscreen(p1.x, p2.y))
return FALSE;
if (!is_point_onscreen(rc.right, rc.top))
if (!is_point_onscreen(p2.x, p1.y))
return FALSE;
if (!is_point_onscreen(rc.right, rc.bottom))
if (!is_point_onscreen(p2.x, p2.y))
return FALSE;
return TRUE;
}

207
src/map.c
View File

@@ -1257,101 +1257,154 @@ set_context_in_map_cmd(
*/
int
ExpandMappings(
char_u *pat,
regmatch_T *regmatch,
int *num_file,
char_u ***file)
int *numMatches,
char_u ***matches)
{
mapblock_T *mp;
garray_T ga;
int hash;
int count;
int round;
char_u *p;
int i;
int fuzzy;
int match;
int score;
fuzmatch_str_T *fuzmatch;
fuzzy = cmdline_fuzzy_complete(pat);
validate_maphash();
*num_file = 0; // return values in case of FAIL
*file = NULL;
*numMatches = 0; // return values in case of FAIL
*matches = NULL;
// round == 1: Count the matches.
// round == 2: Build the array to keep the matches.
for (round = 1; round <= 2; ++round)
if (!fuzzy)
ga_init2(&ga, sizeof(char *), 3);
else
ga_init2(&ga, sizeof(fuzmatch_str_T), 3);
// First search in map modifier arguments
for (i = 0; i < 7; ++i)
{
count = 0;
for (i = 0; i < 7; ++i)
{
if (i == 0)
p = (char_u *)"<silent>";
else if (i == 1)
p = (char_u *)"<unique>";
if (i == 0)
p = (char_u *)"<silent>";
else if (i == 1)
p = (char_u *)"<unique>";
#ifdef FEAT_EVAL
else if (i == 2)
p = (char_u *)"<script>";
else if (i == 3)
p = (char_u *)"<expr>";
else if (i == 2)
p = (char_u *)"<script>";
else if (i == 3)
p = (char_u *)"<expr>";
#endif
else if (i == 4 && !expand_buffer)
p = (char_u *)"<buffer>";
else if (i == 5)
p = (char_u *)"<nowait>";
else if (i == 6)
p = (char_u *)"<special>";
else
else if (i == 4 && !expand_buffer)
p = (char_u *)"<buffer>";
else if (i == 5)
p = (char_u *)"<nowait>";
else if (i == 6)
p = (char_u *)"<special>";
else
continue;
if (!fuzzy)
match = vim_regexec(regmatch, p, (colnr_T)0);
else
{
score = fuzzy_match_str(p, pat);
match = (score != 0);
}
if (!match)
continue;
if (ga_grow(&ga, 1) == FAIL)
break;
if (fuzzy)
{
fuzmatch = &((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
fuzmatch->idx = ga.ga_len;
fuzmatch->str = vim_strsave(p);
fuzmatch->score = score;
}
else
((char_u **)ga.ga_data)[ga.ga_len] = vim_strsave(p);
++ga.ga_len;
}
for (hash = 0; hash < 256; ++hash)
{
if (expand_isabbrev)
{
if (hash > 0) // only one abbrev list
break; // for (hash)
mp = first_abbr;
}
else if (expand_buffer)
mp = curbuf->b_maphash[hash];
else
mp = maphash[hash];
for (; mp; mp = mp->m_next)
{
if (!(mp->m_mode & expand_mapmodes))
continue;
if (vim_regexec(regmatch, p, (colnr_T)0))
{
if (round == 1)
++count;
else
(*file)[count++] = vim_strsave(p);
}
}
p = translate_mapping(mp->m_keys);
if (p == NULL)
continue;
for (hash = 0; hash < 256; ++hash)
{
if (expand_isabbrev)
{
if (hash > 0) // only one abbrev list
break; // for (hash)
mp = first_abbr;
}
else if (expand_buffer)
mp = curbuf->b_maphash[hash];
if (!fuzzy)
match = vim_regexec(regmatch, p, (colnr_T)0);
else
mp = maphash[hash];
for (; mp; mp = mp->m_next)
{
if (mp->m_mode & expand_mapmodes)
{
p = translate_mapping(mp->m_keys);
if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0))
{
if (round == 1)
++count;
else
{
(*file)[count++] = p;
p = NULL;
}
}
vim_free(p);
}
} // for (mp)
} // for (hash)
score = fuzzy_match_str(p, pat);
match = (score != 0);
}
if (count == 0) // no match found
break; // for (round)
if (!match)
{
vim_free(p);
continue;
}
if (round == 1)
{
*file = ALLOC_MULT(char_u *, count);
if (*file == NULL)
return FAIL;
}
} // for (round)
if (ga_grow(&ga, 1) == FAIL)
{
vim_free(p);
break;
}
if (fuzzy)
{
fuzmatch = &((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
fuzmatch->idx = ga.ga_len;
fuzmatch->str = p;
fuzmatch->score = score;
}
else
((char_u **)ga.ga_data)[ga.ga_len] = p;
++ga.ga_len;
} // for (mp)
} // for (hash)
if (ga.ga_len == 0)
return FAIL;
if (!fuzzy)
{
*matches = ga.ga_data;
*numMatches = ga.ga_len;
}
else
{
if (fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len,
FALSE) == FAIL)
return FAIL;
*numMatches = ga.ga_len;
}
count = *numMatches;
if (count > 1)
{
char_u **ptr1;
@@ -1359,10 +1412,12 @@ ExpandMappings(
char_u **ptr3;
// Sort the matches
sort_strings(*file, count);
// Fuzzy matching already sorts the matches
if (!fuzzy)
sort_strings(*matches, count);
// Remove multiple entries
ptr1 = *file;
ptr1 = *matches;
ptr2 = ptr1 + 1;
ptr3 = ptr1 + count;
@@ -1378,7 +1433,7 @@ ExpandMappings(
}
}
*num_file = count;
*numMatches = count;
return (count == 0 ? FAIL : OK);
}

View File

@@ -887,8 +887,10 @@ sig_tstp SIGDEFARG(sigarg)
else
got_tstp = TRUE;
// this is not required on all systems, but it doesn't hurt anybody
#ifndef __ANDROID__
// this is not required on all systems
signal(SIGTSTP, (RETSIGTYPE (*)())sig_tstp);
#endif
SIGRETURN;
}
#endif

View File

@@ -8,7 +8,7 @@ int mode_str2flags(char_u *modechars);
int map_to_exists(char_u *str, char_u *modechars, int abbr);
int map_to_exists_mode(char_u *rhs, int mode, int abbr);
char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg, int forceit, int isabbrev, int isunmap, cmdidx_T cmdidx);
int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file);
int ExpandMappings(char_u *pat, regmatch_T *regmatch, int *num_file, char_u ***file);
int check_abbr(int c, char_u *ptr, int col, int mincol);
char_u *eval_map_expr(mapblock_T *mp, int c);
char_u *vim_strsave_escape_csi(char_u *p);

View File

@@ -57,6 +57,7 @@ int tv_check_lock(typval_T *tv, char_u *name, int use_gettext);
void copy_tv(typval_T *from, typval_T *to);
int typval_compare(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic);
int typval_compare_list(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, int *res);
int typval_compare_null(typval_T *tv1, typval_T *tv2);
int typval_compare_blob(typval_T *tv1, typval_T *tv2, exprtype_T type, int *res);
int typval_compare_dict(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, int *res);
int typval_compare_func(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, int *res);

View File

@@ -5006,7 +5006,7 @@ fuzzy_match_str(char_u *str, char_u *pat)
if (str == NULL || pat == NULL)
return 0;
fuzzy_match(str, pat, FALSE, &score, matchpos,
fuzzy_match(str, pat, TRUE, &score, matchpos,
sizeof(matchpos) / sizeof(matchpos[0]));
return score;

View File

@@ -0,0 +1,10 @@
| +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @73
|~| @73
| +0#0000001#e0e0e08|a|b@1|r|e|v|i|a|t|e| @4| +0#4040ff13#ffffff0@58
| +0#0000001#ffd7ff255|a|b|c|l|e|a|r| @7| +0#4040ff13#ffffff0@58
| +0#0000001#ffd7ff255|a|b|o|v|e|l|e|f|t| @5| +0#4040ff13#ffffff0@58
| +0#0000001#ffd7ff255|a|b|s|t|r|a|c|t| @6| +0#4040ff13#ffffff0@58
|:+0#0000000&|a|b@1|r|e|v|i|a|t|e> @63

View File

@@ -2181,6 +2181,11 @@ func Test_wildmenu_pum()
set tabline=%!MyTabLine()
set showtabline=2
endfunc
func DoFeedKeys()
let &wildcharm = char2nr("\t")
call feedkeys(":edit $VIMRUNTIME/\<Tab>\<Left>\<C-U>ab\<Tab>")
endfunc
[CODE]
call writefile(commands, 'Xtest')
@@ -2378,6 +2383,12 @@ func Test_wildmenu_pum()
call term_sendkeys(buf, "\<Esc>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_40', {})
" popup is cleared also when 'lazyredraw' is set
call term_sendkeys(buf, ":set showtabline=1 laststatus=1 lazyredraw\<CR>")
call term_sendkeys(buf, ":call DoFeedKeys()\<CR>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_41', {})
call term_sendkeys(buf, "\<Esc>")
call term_sendkeys(buf, "\<C-U>\<CR>")
call StopVimInTerminal(buf)
call delete('Xtest')
@@ -2444,9 +2455,8 @@ func Test_cmdline_complete_dlist()
call assert_equal("\"dlist 10 /pat/ | chistory", @:)
endfunc
" Test for 'fuzzy' in 'wildoptions' (fuzzy completion)
func Test_wildoptions_fuzzy()
" argument list (only for :argdel)
" argument list (only for :argdel) fuzzy completion
func Test_fuzzy_completion_arglist()
argadd change.py count.py charge.py
set wildoptions&
call feedkeys(":argdel cge\<C-A>\<C-B>\"\<CR>", 'tx')
@@ -2455,8 +2465,11 @@ func Test_wildoptions_fuzzy()
call feedkeys(":argdel cge\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"argdel change.py charge.py', @:)
%argdelete
set wildoptions&
endfunc
" autocmd group name fuzzy completion
" autocmd group name fuzzy completion
func Test_fuzzy_completion_autocmd()
set wildoptions&
augroup MyFuzzyGroup
augroup END
@@ -2470,8 +2483,11 @@ func Test_wildoptions_fuzzy()
call feedkeys(":augroup My*p\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"augroup My*p', @:)
augroup! MyFuzzyGroup
set wildoptions&
endfunc
" buffer name fuzzy completion
" buffer name fuzzy completion
func Test_fuzzy_completion_bufname()
set wildoptions&
edit SomeFile.txt
enew
@@ -2485,24 +2501,29 @@ func Test_wildoptions_fuzzy()
call feedkeys(":b S*File.txt\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"b S*File.txt', @:)
%bw!
set wildoptions&
endfunc
" buffer name (full path) fuzzy completion
if has('unix')
set wildoptions&
call mkdir('Xcmd/Xstate/Xfile.js', 'p')
edit Xcmd/Xstate/Xfile.js
cd Xcmd/Xstate
enew
call feedkeys(":b CmdStateFile\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"b CmdStateFile', @:)
set wildoptions=fuzzy
call feedkeys(":b CmdStateFile\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_match('Xcmd/Xstate/Xfile.js$', @:)
cd -
call delete('Xcmd', 'rf')
endif
" buffer name (full path) fuzzy completion
func Test_fuzzy_completion_bufname_fullpath()
CheckUnix
set wildoptions&
call mkdir('Xcmd/Xstate/Xfile.js', 'p')
edit Xcmd/Xstate/Xfile.js
cd Xcmd/Xstate
enew
call feedkeys(":b CmdStateFile\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"b CmdStateFile', @:)
set wildoptions=fuzzy
call feedkeys(":b CmdStateFile\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_match('Xcmd/Xstate/Xfile.js$', @:)
cd -
call delete('Xcmd', 'rf')
set wildoptions&
endfunc
" :behave suboptions fuzzy completion
" :behave suboptions fuzzy completion
func Test_fuzzy_completion_behave()
set wildoptions&
call feedkeys(":behave xm\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"behave xm', @:)
@@ -2517,10 +2538,15 @@ func Test_wildoptions_fuzzy()
call feedkeys(":behave win\<C-D>\<F4>\<C-B>\"\<CR>", 'tx')
call assert_equal('mswin', g:Sline)
call assert_equal('"behave win', @:)
set wildoptions&
endfunc
" colorscheme name fuzzy completion - NOT supported
" " colorscheme name fuzzy completion - NOT supported
" func Test_fuzzy_completion_colorscheme()
" endfunc
" built-in command name fuzzy completion
" built-in command name fuzzy completion
func Test_fuzzy_completion_cmdname()
set wildoptions&
call feedkeys(":sbwin\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sbwin', @:)
@@ -2531,24 +2557,31 @@ func Test_wildoptions_fuzzy()
call assert_equal('"sbrewind', @:)
call feedkeys(":sbr*d\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sbr*d', @:)
set wildoptions&
endfunc
" compiler name fuzzy completion - NOT supported
" " compiler name fuzzy completion - NOT supported
" func Test_fuzzy_completion_compiler()
" endfunc
" :cscope suboptions fuzzy completion
if has('cscope')
set wildoptions&
call feedkeys(":cscope ret\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"cscope ret', @:)
call feedkeys(":cscope re*t\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"cscope reset', @:)
set wildoptions=fuzzy
call feedkeys(":cscope ret\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"cscope reset', @:)
call feedkeys(":cscope re*t\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"cscope re*t', @:)
endif
" :cscope suboptions fuzzy completion
func Test_fuzzy_completion_cscope()
CheckFeature cscope
set wildoptions&
call feedkeys(":cscope ret\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"cscope ret', @:)
call feedkeys(":cscope re*t\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"cscope reset', @:)
set wildoptions=fuzzy
call feedkeys(":cscope ret\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"cscope reset', @:)
call feedkeys(":cscope re*t\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"cscope re*t', @:)
set wildoptions&
endfunc
" :diffget/:diffput buffer name fuzzy completion
" :diffget/:diffput buffer name fuzzy completion
func Test_fuzzy_completion_diff()
new SomeBuffer
diffthis
new OtherBuffer
@@ -2564,26 +2597,37 @@ func Test_wildoptions_fuzzy()
call feedkeys(":diffput sbuf\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"diffput SomeBuffer', @:)
%bw!
set wildoptions&
endfunc
" directory name fuzzy completion - NOT supported
" " directory name fuzzy completion - NOT supported
" func Test_fuzzy_completion_dirname()
" endfunc
" environment variable name fuzzy completion
" environment variable name fuzzy completion
func Test_fuzzy_completion_env()
set wildoptions&
call feedkeys(":echo $VUT\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"echo $VUT', @:)
set wildoptions=fuzzy
call feedkeys(":echo $VUT\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"echo $VIMRUNTIME', @:)
set wildoptions&
endfunc
" autocmd event fuzzy completion
" autocmd event fuzzy completion
func Test_fuzzy_completion_autocmd_event()
set wildoptions&
call feedkeys(":autocmd BWout\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"autocmd BWout', @:)
set wildoptions=fuzzy
call feedkeys(":autocmd BWout\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"autocmd BufWipeout', @:)
set wildoptions&
endfunc
" vim expression fuzzy completion
" vim expression fuzzy completion
func Test_fuzzy_completion_expr()
let g:PerPlaceCount = 10
set wildoptions&
call feedkeys(":let c = ppc\<Tab>\<C-B>\"\<CR>", 'tx')
@@ -2591,32 +2635,67 @@ func Test_wildoptions_fuzzy()
set wildoptions=fuzzy
call feedkeys(":let c = ppc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"let c = PerPlaceCount', @:)
" file name fuzzy completion - NOT supported
" files in path fuzzy completion - NOT supported
" filetype name fuzzy completion - NOT supported
" user defined function name completion
set wildoptions&
call feedkeys(":call Test_w_fuz\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"call Test_w_fuz', @:)
set wildoptions=fuzzy
call feedkeys(":call Test_w_fuz\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"call Test_wildoptions_fuzzy()', @:)
endfunc
" user defined command name completion
" " file name fuzzy completion - NOT supported
" func Test_fuzzy_completion_filename()
" endfunc
" " files in path fuzzy completion - NOT supported
" func Test_fuzzy_completion_filesinpath()
" endfunc
" " filetype name fuzzy completion - NOT supported
" func Test_fuzzy_completion_filetype()
" endfunc
" user defined function name completion
func Test_fuzzy_completion_userdefined_func()
set wildoptions&
call feedkeys(":call Test_f_u_f\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"call Test_f_u_f', @:)
set wildoptions=fuzzy
call feedkeys(":call Test_f_u_f\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"call Test_fuzzy_completion_userdefined_func()', @:)
set wildoptions&
endfunc
" <SNR> functions should be sorted to the end
func Test_fuzzy_completion_userdefined_snr_func()
func s:Sendmail()
endfunc
func SendSomemail()
endfunc
func S1e2n3dmail()
endfunc
set wildoptions=fuzzy
call feedkeys(":call sendmail\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"call SendSomemail() S1e2n3dmail() '
\ .. expand("<SID>") .. 'Sendmail()', @:)
set wildoptions&
delfunc s:Sendmail
delfunc SendSomemail
delfunc S1e2n3dmail
endfunc
" user defined command name completion
func Test_fuzzy_completion_userdefined_cmd()
set wildoptions&
call feedkeys(":MsFeat\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"MsFeat', @:)
set wildoptions=fuzzy
call feedkeys(":MsFeat\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"MissingFeature', @:)
set wildoptions&
endfunc
" :help tag fuzzy completion - NOT supported
" " :help tag fuzzy completion - NOT supported
" func Test_fuzzy_completion_helptag()
" endfunc
" highlight group name fuzzy completion
" highlight group name fuzzy completion
func Test_fuzzy_completion_hlgroup()
set wildoptions&
call feedkeys(":highlight SKey\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"highlight SKey', @:)
@@ -2627,8 +2706,11 @@ func Test_wildoptions_fuzzy()
call assert_equal('"highlight SpecialKey', @:)
call feedkeys(":highlight Sp*Key\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"highlight Sp*Key', @:)
set wildoptions&
endfunc
" :history suboptions fuzzy completion
" :history suboptions fuzzy completion
func Test_fuzzy_completion_history()
set wildoptions&
call feedkeys(":history dg\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"history dg', @:)
@@ -2639,46 +2721,110 @@ func Test_wildoptions_fuzzy()
call assert_equal('"history debug', @:)
call feedkeys(":history se*h\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"history se*h', @:)
set wildoptions&
endfunc
" :language locale name fuzzy completion
if has('unix')
set wildoptions&
call feedkeys(":lang psx\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"lang psx', @:)
set wildoptions=fuzzy
call feedkeys(":lang psx\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"lang POSIX', @:)
endif
" :language locale name fuzzy completion
func Test_fuzzy_completion_lang()
CheckUnix
set wildoptions&
call feedkeys(":lang psx\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"lang psx', @:)
set wildoptions=fuzzy
call feedkeys(":lang psx\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"lang POSIX', @:)
set wildoptions&
endfunc
" :mapclear buffer argument fuzzy completion
" :mapclear buffer argument fuzzy completion
func Test_fuzzy_completion_mapclear()
set wildoptions&
call feedkeys(":mapclear buf\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"mapclear buf', @:)
set wildoptions=fuzzy
call feedkeys(":mapclear buf\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"mapclear <buffer>', @:)
set wildoptions&
endfunc
" map name fuzzy completion - NOT supported
" map name fuzzy completion
func Test_fuzzy_completion_mapname()
" test regex completion works
set wildoptions=fuzzy
call feedkeys(":cnoremap <ex\<Tab> <esc> \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"cnoremap <expr> <esc> \<Tab>", @:)
nmap <plug>MyLongMap :p<CR>
call feedkeys(":nmap MLM\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"nmap <Plug>MyLongMap", @:)
call feedkeys(":nmap MLM \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"nmap MLM \t", @:)
call feedkeys(":nmap <F2> one two \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"nmap <F2> one two \t", @:)
" duplicate entries should be removed
vmap <plug>MyLongMap :<C-U>#<CR>
call feedkeys(":nmap MLM\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"nmap <Plug>MyLongMap", @:)
nunmap <plug>MyLongMap
vunmap <plug>MyLongMap
call feedkeys(":nmap ABC\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"nmap ABC\t", @:)
" results should be sorted by best match
nmap <Plug>format :
nmap <Plug>goformat :
nmap <Plug>TestFOrmat :
nmap <Plug>fendoff :
nmap <Plug>state :
nmap <Plug>FendingOff :
call feedkeys(":nmap <Plug>fo\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"nmap <Plug>format <Plug>TestFOrmat <Plug>FendingOff <Plug>goformat <Plug>fendoff", @:)
nunmap <Plug>format
nunmap <Plug>goformat
nunmap <Plug>TestFOrmat
nunmap <Plug>fendoff
nunmap <Plug>state
nunmap <Plug>FendingOff
set wildoptions&
endfunc
" menu name fuzzy completion
if has('gui_running')
set wildoptions&
call feedkeys(":menu pup\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"menu pup', @:)
set wildoptions=fuzzy
call feedkeys(":menu pup\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"menu PopUp.', @:)
endif
" abbreviation fuzzy completion
func Test_fuzzy_completion_abbr()
set wildoptions=fuzzy
call feedkeys(":iabbr wait\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"iabbr <nowait>", @:)
iabbr WaitForCompletion WFC
call feedkeys(":iabbr fcl\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"iabbr WaitForCompletion", @:)
call feedkeys(":iabbr a1z\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"iabbr a1z\t", @:)
iunabbrev WaitForCompletion
set wildoptions&
endfunc
" :messages suboptions fuzzy completion
" menu name fuzzy completion
func Test_fuzzy_completion_menu()
CheckGui
set wildoptions&
call feedkeys(":menu pup\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"menu pup', @:)
set wildoptions=fuzzy
call feedkeys(":menu pup\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"menu PopUp.', @:)
set wildoptions&
endfunc
" :messages suboptions fuzzy completion
func Test_fuzzy_completion_messages()
set wildoptions&
call feedkeys(":messages clr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"messages clr', @:)
set wildoptions=fuzzy
call feedkeys(":messages clr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"messages clear', @:)
set wildoptions&
endfunc
" :set option name fuzzy completion
" :set option name fuzzy completion
func Test_fuzzy_completion_option()
set wildoptions&
call feedkeys(":set brkopt\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"set brkopt', @:)
@@ -2691,8 +2837,11 @@ func Test_wildoptions_fuzzy()
set wildoptions=fuzzy
call feedkeys(":set fixeol\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"set fixendofline', @:)
set wildoptions&
endfunc
" :set <term_option>
" :set <term_option>
func Test_fuzzy_completion_term_option()
set wildoptions&
call feedkeys(":set t_E\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"set t_EC', @:)
@@ -2703,52 +2852,76 @@ func Test_wildoptions_fuzzy()
call assert_equal('"set t_EC', @:)
call feedkeys(":set <t_E\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"set <t_EC>', @:)
set wildoptions&
endfunc
" :packadd directory name fuzzy completion - NOT supported
" " :packadd directory name fuzzy completion - NOT supported
" func Test_fuzzy_completion_packadd()
" endfunc
" shell command name fuzzy completion - NOT supported
" " shell command name fuzzy completion - NOT supported
" func Test_fuzzy_completion_shellcmd()
" endfunc
" :sign suboptions fuzzy completion
" :sign suboptions fuzzy completion
func Test_fuzzy_completion_sign()
set wildoptions&
call feedkeys(":sign ufe\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign ufe', @:)
set wildoptions=fuzzy
call feedkeys(":sign ufe\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign undefine', @:)
set wildoptions&
endfunc
" :syntax suboptions fuzzy completion
" :syntax suboptions fuzzy completion
func Test_fuzzy_completion_syntax_cmd()
set wildoptions&
call feedkeys(":syntax kwd\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syntax kwd', @:)
set wildoptions=fuzzy
call feedkeys(":syntax kwd\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syntax keyword', @:)
set wildoptions&
endfunc
" syntax group name fuzzy completion
" syntax group name fuzzy completion
func Test_fuzzy_completion_syntax_group()
set wildoptions&
call feedkeys(":syntax list mpar\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syntax list mpar', @:)
set wildoptions=fuzzy
call feedkeys(":syntax list mpar\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syntax list MatchParen', @:)
set wildoptions&
endfunc
" :syntime suboptions fuzzy completion
if has('profile')
set wildoptions&
call feedkeys(":syntime clr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syntime clr', @:)
set wildoptions=fuzzy
call feedkeys(":syntime clr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syntime clear', @:)
endif
" :syntime suboptions fuzzy completion
func Test_fuzzy_completion_syntime()
CheckFeature profile
set wildoptions&
call feedkeys(":syntime clr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syntime clr', @:)
set wildoptions=fuzzy
call feedkeys(":syntime clr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syntime clear', @:)
set wildoptions&
endfunc
" tag name fuzzy completion - NOT supported
" " tag name fuzzy completion - NOT supported
" func Test_fuzzy_completion_tagname()
" endfunc
" tag name and file fuzzy completion - NOT supported
" " tag name and file fuzzy completion - NOT supported
" func Test_fuzzy_completion_tagfile()
" endfunc
" user names fuzzy completion - how to test this functionality?
" " user names fuzzy completion - how to test this functionality?
" func Test_fuzzy_completion_username()
" endfunc
" user defined variable name fuzzy completion
" user defined variable name fuzzy completion
func Test_fuzzy_completion_userdefined_var()
let g:SomeVariable=10
set wildoptions&
call feedkeys(":let SVar\<Tab>\<C-B>\"\<CR>", 'tx')
@@ -2756,8 +2929,11 @@ func Test_wildoptions_fuzzy()
set wildoptions=fuzzy
call feedkeys(":let SVar\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"let SomeVariable', @:)
set wildoptions&
endfunc
" Test for sorting the results by the best match
" Test for sorting the results by the best match
func Test_fuzzy_completion_cmd_sort_results()
%bw!
command T123format :
command T123goformat :
@@ -2775,9 +2951,11 @@ func Test_wildoptions_fuzzy()
delcommand T123state
delcommand T123FendingOff
%bw
set wildoptions&
endfunc
" Test for fuzzy completion of a command with lower case letters and a
" number
" Test for fuzzy completion of a command with lower case letters and a number
func Test_fuzzy_completion_cmd_alnum()
command Foo2Bar :
set wildoptions=fuzzy
call feedkeys(":foo2\<Tab>\<C-B>\"\<CR>", 'tx')
@@ -2787,9 +2965,46 @@ func Test_wildoptions_fuzzy()
call feedkeys(":bar\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"Foo2Bar', @:)
delcommand Foo2Bar
set wildoptions&
%bw!
endfunc
" Test for command completion for a command starting with 'k'
func Test_fuzzy_completion_cmd_k()
command KillKillKill :
set wildoptions&
call feedkeys(":killkill\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"killkill\<Tab>", @:)
set wildoptions=fuzzy
call feedkeys(":killkill\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"KillKillKill', @:)
delcom KillKillKill
set wildoptions&
endfunc
" Test for fuzzy completion for user defined custom completion function
func Test_fuzzy_completion_custom_func()
func Tcompl(a, c, p)
return "format\ngoformat\nTestFOrmat\nfendoff\nstate"
endfunc
command -nargs=* -complete=custom,Tcompl Fuzzy :
set wildoptions&
call feedkeys(":Fuzzy fo\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"Fuzzy format", @:)
call feedkeys(":Fuzzy xy\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"Fuzzy xy", @:)
call feedkeys(":Fuzzy ttt\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"Fuzzy ttt", @:)
set wildoptions=fuzzy
call feedkeys(":Fuzzy \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"Fuzzy format goformat TestFOrmat fendoff state", @:)
call feedkeys(":Fuzzy fo\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"Fuzzy format TestFOrmat goformat fendoff", @:)
call feedkeys(":Fuzzy xy\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"Fuzzy xy", @:)
call feedkeys(":Fuzzy ttt\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"Fuzzy TestFOrmat", @:)
delcom Fuzzy
set wildoptions&
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -550,6 +550,13 @@ def Test_assign_index()
bl[-2] = 0x66
assert_equal(0z77226644, bl)
lines =<< trim END
g:val = '22'
var bl = 0z11
bl[1] = g:val
END
v9.CheckDefExecAndScriptFailure(lines, 'E1030: Using a String as a Number: "22"')
# should not read the next line when generating "a.b"
var a = {}
a.b = {}
@@ -1233,12 +1240,18 @@ def Test_script_var_default()
var lines =<< trim END
vim9script
var l: list<number>
var li = [1, 2]
var bl: blob
var bli = 0z12
var d: dict<number>
var di = {'a': 1, 'b': 2}
def Echo()
assert_equal([], l)
assert_equal([1, 2], li)
assert_equal(0z, bl)
assert_equal(0z12, bli)
assert_equal({}, d)
assert_equal({'a': 1, 'b': 2}, di)
enddef
Echo()
END
@@ -1502,6 +1515,30 @@ def Test_assign_list()
END
v9.CheckDefAndScriptSuccess(lines)
lines =<< trim END
var l = [1, 2]
g:idx = 'x'
l[g:idx : 1] = [0]
echo l
END
v9.CheckDefExecAndScriptFailure(lines, 'E1030: Using a String as a Number: "x"')
lines =<< trim END
var l = [1, 2]
g:idx = 3
l[g:idx : 1] = [0]
echo l
END
v9.CheckDefExecAndScriptFailure(lines, 'E684: list index out of range: 3')
lines =<< trim END
var l = [1, 2]
g:idx = 'y'
l[1 : g:idx] = [0]
echo l
END
v9.CheckDefExecAndScriptFailure(lines, ['E1012: Type mismatch; expected number but got string', 'E1030: Using a String as a Number: "y"'])
v9.CheckDefFailure(["var l: list<number> = ['', true]"], 'E1012: Type mismatch; expected list<number> but got list<any>', 1)
v9.CheckDefFailure(["var l: list<list<number>> = [['', true]]"], 'E1012: Type mismatch; expected list<list<number>> but got list<list<any>>', 1)
enddef

View File

@@ -1846,6 +1846,8 @@ def Test_disassemble_compare()
['true != isFalse', 'COMPAREBOOL !='],
['v:none == isNull', 'COMPARESPECIAL =='],
['v:none != isNull', 'COMPARESPECIAL !='],
['"text" == isNull', 'COMPARENULL =='],
['"text" != isNull', 'COMPARENULL !='],
['111 == aNumber', 'COMPARENR =='],
['111 != aNumber', 'COMPARENR !='],

View File

@@ -712,6 +712,81 @@ def Test_expr4_equal()
unlet g:notReached
enddef
def Test_expr4_compare_null()
g:null_dict = test_null_dict()
g:not_null_list = []
var lines =<< trim END
assert_true(test_null_blob() == v:null)
assert_true(v:null == test_null_blob())
assert_false(test_null_blob() != v:null)
assert_false(v:null != test_null_blob())
if has('channel')
assert_true(test_null_channel() == v:null)
assert_true(v:null == test_null_channel())
assert_false(test_null_channel() != v:null)
assert_false(v:null != test_null_channel())
endif
assert_true(test_null_dict() == v:null)
assert_true(v:null == test_null_dict())
assert_false(test_null_dict() != v:null)
assert_false(v:null != test_null_dict())
assert_true(g:null_dict == v:null)
assert_true(v:null == g:null_dict)
assert_false(g:null_dict != v:null)
assert_false(v:null != g:null_dict)
assert_true(test_null_function() == v:null)
assert_true(v:null == test_null_function())
assert_false(test_null_function() != v:null)
assert_false(v:null != test_null_function())
if has('job')
assert_true(test_null_job() == v:null)
assert_true(v:null == test_null_job())
assert_false(test_null_job() != v:null)
assert_false(v:null != test_null_job())
endif
assert_true(test_null_list() == v:null)
assert_true(v:null == test_null_list())
assert_false(test_null_list() != v:null)
assert_false(v:null != test_null_list())
assert_false(g:not_null_list == v:null)
assert_false(v:null == g:not_null_list)
assert_true(g:not_null_list != v:null)
assert_true(v:null != g:not_null_list)
assert_true(test_null_partial() == v:null)
assert_true(v:null == test_null_partial())
assert_false(test_null_partial() != v:null)
assert_false(v:null != test_null_partial())
assert_true(test_null_string() == v:null)
assert_true(v:null == test_null_string())
assert_false(test_null_string() != v:null)
assert_false(v:null != test_null_string())
END
v9.CheckDefAndScriptSuccess(lines)
unlet g:null_dict
unlet g:not_null_list
v9.CheckDefAndScriptFailure(['echo 123 == v:null'], 'E1072: Cannot compare number with special')
v9.CheckDefAndScriptFailure(['echo v:null == 123'], 'E1072: Cannot compare special with number')
v9.CheckDefAndScriptFailure(['echo 123 != v:null'], 'E1072: Cannot compare number with special')
v9.CheckDefAndScriptFailure(['echo v:null != 123'], 'E1072: Cannot compare special with number')
v9.CheckDefAndScriptFailure(['echo true == v:null'], 'E1072: Cannot compare bool with special')
v9.CheckDefAndScriptFailure(['echo v:null == true'], 'E1072: Cannot compare special with bool')
v9.CheckDefAndScriptFailure(['echo true != v:null'], 'E1072: Cannot compare bool with special')
v9.CheckDefAndScriptFailure(['echo v:null != true'], 'E1072: Cannot compare special with bool')
v9.CheckDefAndScriptFailure(['echo false == v:null'], 'E1072: Cannot compare bool with special')
v9.CheckDefExecAndScriptFailure(['echo [] == v:none'], ['E1072: Cannot compare list with special', 'E691: Can only compare List with List'])
enddef
def Test_expr4_wrong_type()
for op in ['>', '>=', '<', '<=', '=~', '!~']
v9.CheckDefExecAndScriptFailure([
@@ -2782,6 +2857,23 @@ def Test_expr8_any_index_slice()
v9.CheckDefAndScriptSuccess(lines)
lines =<< trim END
vim9script
def PosIdx(s: string): string
return s[1]
enddef
def NegIdx(s: string): string
return s[-1]
enddef
set enc=latin1
assert_equal("\xe4", PosIdx("a\xe4\xe5"))
assert_equal("\xe5", NegIdx("a\xe4\xe5"))
set enc=utf-8
END
v9.CheckScriptSuccess(lines)
v9.CheckDefExecAndScriptFailure(['echo g:testblob[2]'], 'E979:', 1)
v9.CheckDefExecAndScriptFailure(['echo g:testblob[-3]'], 'E979:', 1)

View File

@@ -550,6 +550,44 @@ def Test_call_ufunc_count()
unlet g:counter
enddef
def Test_call_ufunc_failure()
var lines =<< trim END
vim9script
def Tryit()
g:Global(1, 2, 3)
enddef
func g:Global(a, b, c)
echo a:a a:b a:c
endfunc
defcompile
func! g:Global(a, b)
echo a:a a:b
endfunc
Tryit()
END
v9.CheckScriptFailure(lines, 'E118: Too many arguments for function: Global')
delfunc g:Global
lines =<< trim END
vim9script
g:Ref = function('len')
def Tryit()
g:Ref('x')
enddef
defcompile
g:Ref = function('add')
Tryit()
END
v9.CheckScriptFailure(lines, 'E119: Not enough arguments for function: add')
unlet g:Ref
enddef
def s:MyVarargs(arg: string, ...rest: list<string>): string
var res = arg
for s in rest

View File

@@ -6546,9 +6546,16 @@ func Test_type()
call assert_true(v:true != v:false)
call assert_true(v:null == 0)
call assert_false(v:null == 1)
call assert_false(v:null != 0)
call assert_true(v:none == 0)
call assert_false(v:none == 1)
call assert_false(v:none != 0)
if has('float')
call assert_true(v:null == 0.0)
call assert_false(v:null == 0.1)
call assert_false(v:null != 0.0)
endif
call assert_true(v:false is v:false)
call assert_true(v:true is v:true)

View File

@@ -1169,6 +1169,21 @@ typval_compare(
// it means TRUE.
n1 = (type == EXPR_ISNOT);
}
else if (((tv1->v_type == VAR_SPECIAL && tv1->vval.v_number == VVAL_NULL)
|| (tv2->v_type == VAR_SPECIAL
&& tv2->vval.v_number == VVAL_NULL))
&& tv1->v_type != tv2->v_type
&& (type == EXPR_EQUAL || type == EXPR_NEQUAL))
{
n1 = typval_compare_null(tv1, tv2);
if (n1 == MAYBE)
{
clear_tv(tv1);
return FAIL;
}
if (type == EXPR_NEQUAL)
n1 = !n1;
}
else if (tv1->v_type == VAR_BLOB || tv2->v_type == VAR_BLOB)
{
if (typval_compare_blob(tv1, tv2, type, &res) == FAIL)
@@ -1365,6 +1380,48 @@ typval_compare_list(
return OK;
}
/*
* Compare v:null/v:none with another type. Return TRUE if the value is NULL.
*/
int
typval_compare_null(typval_T *tv1, typval_T *tv2)
{
if ((tv1->v_type == VAR_SPECIAL && tv1->vval.v_number == VVAL_NULL)
|| (tv2->v_type == VAR_SPECIAL && tv2->vval.v_number == VVAL_NULL))
{
typval_T *tv = tv1->v_type == VAR_SPECIAL ? tv2 : tv1;
switch (tv->v_type)
{
case VAR_BLOB: return tv->vval.v_blob == NULL;
#ifdef FEAT_JOB_CHANNEL
case VAR_CHANNEL: return tv->vval.v_channel == NULL;
#endif
case VAR_DICT: return tv->vval.v_dict == NULL;
case VAR_FUNC: return tv->vval.v_string == NULL;
#ifdef FEAT_JOB_CHANNEL
case VAR_JOB: return tv->vval.v_job == NULL;
#endif
case VAR_LIST: return tv->vval.v_list == NULL;
case VAR_PARTIAL: return tv->vval.v_partial == NULL;
case VAR_STRING: return tv->vval.v_string == NULL;
case VAR_NUMBER: if (!in_vim9script())
return tv->vval.v_number == 0;
break;
#ifdef FEAT_FLOAT
case VAR_FLOAT: if (!in_vim9script())
return tv->vval.v_float == 0.0;
break;
#endif
default: break;
}
}
semsg(_(e_cannot_compare_str_with_str),
vartype_name(tv1->v_type), vartype_name(tv2->v_type));
return MAYBE;
}
/*
* Compare "tv1" to "tv2" as blobs acording to "type".
* Put the result, false or true, in "res".

View File

@@ -754,6 +754,32 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4489,
/**/
4488,
/**/
4487,
/**/
4486,
/**/
4485,
/**/
4484,
/**/
4483,
/**/
4482,
/**/
4481,
/**/
4480,
/**/
4479,
/**/
4478,
/**/
4477,
/**/
4476,
/**/

View File

@@ -134,6 +134,7 @@ typedef enum {
// comparative operations; isn_arg.op.op_type is exprtype_T, op_ic used
ISN_COMPAREBOOL,
ISN_COMPARESPECIAL,
ISN_COMPARENULL,
ISN_COMPARENR,
ISN_COMPAREFLOAT,
ISN_COMPARESTRING,

View File

@@ -1027,7 +1027,7 @@ call_by_name(
{
int func_idx = find_internal_func(name);
if (func_idx < 0)
if (func_idx < 0) // Impossible?
return FAIL;
if (check_internal_func(func_idx, argcount) < 0)
return FAIL;
@@ -1452,8 +1452,6 @@ get_split_sourceline(
char_u *p;
char_u *line;
if (*sp->nextline == NUL)
return NULL;
p = vim_strchr(sp->nextline, '\n');
if (p == NULL)
{
@@ -1911,11 +1909,11 @@ execute_storerange(isn_T *iptr, ectx_T *ectx)
else
n2 = (long)tv_get_number_chk(tv_idx2, &error);
if (error)
status = FAIL;
status = FAIL; // cannot happen?
else
{
listitem_T *li1 = check_range_index_one(
tv_dest->vval.v_list, &n1, FALSE);
tv_dest->vval.v_list, &n1, FALSE);
if (li1 == NULL)
status = FAIL;
@@ -3882,6 +3880,25 @@ exec_instructions(ectx_T *ectx)
}
break;
case ISN_COMPARENULL:
{
typval_T *tv1 = STACK_TV_BOT(-2);
typval_T *tv2 = STACK_TV_BOT(-1);
int res;
res = typval_compare_null(tv1, tv2);
if (res == MAYBE)
goto on_error;
if (iptr->isn_arg.op.op_type == EXPR_NEQUAL)
res = !res;
clear_tv(tv1);
clear_tv(tv2);
--ectx->ec_stack.ga_len;
tv1->v_type = VAR_BOOL;
tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
}
break;
// Operation with two number arguments
case ISN_OPNR:
case ISN_COMPARENR:
@@ -5903,6 +5920,7 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
case ISN_COMPAREBOOL:
case ISN_COMPARESPECIAL:
case ISN_COMPARENULL:
case ISN_COMPARENR:
case ISN_COMPAREFLOAT:
case ISN_COMPARESTRING:
@@ -5938,6 +5956,7 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
case ISN_COMPARESPECIAL:
type = "COMPARESPECIAL"; break;
case ISN_COMPARENULL: type = "COMPARENULL"; break;
case ISN_COMPARENR: type = "COMPARENR"; break;
case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
case ISN_COMPARESTRING:

View File

@@ -372,6 +372,24 @@ get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
|| ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
&& (type2 == VAR_NUMBER || type2 == VAR_FLOAT)))
isntype = ISN_COMPAREANY;
else if (type1 == VAR_SPECIAL || type2 == VAR_SPECIAL)
{
switch (type1 == VAR_SPECIAL ? type2 : type1)
{
case VAR_BLOB: break;
case VAR_CHANNEL: break;
case VAR_DICT: break;
case VAR_FUNC: break;
case VAR_JOB: break;
case VAR_LIST: break;
case VAR_PARTIAL: break;
case VAR_STRING: break;
default: semsg(_(e_cannot_compare_str_with_str),
vartype_name(type1), vartype_name(type2));
return ISN_DROP;
}
isntype = ISN_COMPARENULL;
}
if ((exprtype == EXPR_IS || exprtype == EXPR_ISNOT)
&& (isntype == ISN_COMPAREBOOL
@@ -388,7 +406,7 @@ get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
&& (type1 == VAR_BOOL || type1 == VAR_SPECIAL
|| type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
|| ((exprtype != EXPR_EQUAL && exprtype != EXPR_NEQUAL
&& exprtype != EXPR_IS && exprtype != EXPR_ISNOT
&& exprtype != EXPR_IS && exprtype != EXPR_ISNOT
&& (type1 == VAR_BLOB || type2 == VAR_BLOB
|| type1 == VAR_LIST || type2 == VAR_LIST))))
{
@@ -2131,6 +2149,7 @@ delete_instr(isn_T *isn)
case ISN_COMPAREFUNC:
case ISN_COMPARELIST:
case ISN_COMPARENR:
case ISN_COMPARENULL:
case ISN_COMPARESPECIAL:
case ISN_COMPARESTRING:
case ISN_CONCAT: