Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6e9d7063d | ||
|
|
f6b0c79742 | ||
|
|
7a22224875 | ||
|
|
f01af9c4e6 | ||
|
|
3e7637bd26 | ||
|
|
1983f1aa31 | ||
|
|
5de4c4372d | ||
|
|
afd4ae35d6 | ||
|
|
5c52be40fb | ||
|
|
cbef12e60b | ||
|
|
6caeda2fce | ||
|
|
00333cb3b3 | ||
|
|
29ab6ce9f3 | ||
|
|
c51cf03298 |
2
runtime/autoload/dist/ft.vim
vendored
2
runtime/autoload/dist/ft.vim
vendored
@@ -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.
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =".
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. >
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -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: >
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
==============================================================================
|
||||
|
||||
@@ -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()}
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
26799
runtime/doc/version9.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
59
src/buffer.c
59
src/buffer.c
@@ -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
|
||||
|
||||
295
src/cmdexpand.c
295
src/cmdexpand.c
@@ -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, ®match, pat, numMatches, matches);
|
||||
else if (xp->xp_context == EXPAND_MAPPINGS)
|
||||
ret = ExpandMappings(®match, numMatches, matches);
|
||||
ret = ExpandMappings(pat, ®match, numMatches, matches);
|
||||
# if defined(FEAT_EVAL)
|
||||
else if (xp->xp_context == EXPAND_USER_DEFINED)
|
||||
ret = ExpandUserDefined(xp, ®match, matches, numMatches);
|
||||
ret = ExpandUserDefined(pat, xp, ®match, matches, numMatches);
|
||||
# endif
|
||||
else
|
||||
ret = ExpandOther(pat, xp, ®match, 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
207
src/map.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
10
src/testdir/dumps/Test_wildmenu_pum_41.dump
Normal file
10
src/testdir/dumps/Test_wildmenu_pum_41.dump
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 !='],
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
57
src/typval.c
57
src/typval.c
@@ -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".
|
||||
|
||||
@@ -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,
|
||||
/**/
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user