Compare commits

...

16 Commits

Author SHA1 Message Date
Bram Moolenaar
30445cb6e9 patch 7.4.2006
Problem:    Crash when using tabnext in BufUnload autocmd. (Norio Takagi)
Solution:   First check that the current buffer is the right one. (Hirohito
            Higashi)
2016-07-09 15:21:02 +02:00
Bram Moolenaar
ee1deb4a00 patch 7.4.2005
Problem:    After using evalcmd() message output is in the wrong position.
            (Christian Brabandt)
Solution:   Reset msg_col.
2016-07-08 23:06:21 +02:00
Bram Moolenaar
65549bdef5 patch 7.4.2004
Problem:    GUI: cursor displayed in the wrong position.
Solution:   Correct screen_cur_col and screen_cur_row.
2016-07-08 22:52:37 +02:00
Bram Moolenaar
144445d15f patch 7.4.2003
Problem:    Still cursor flickering when a callback updates the screen. (David
            Samvelyan)
Solution:   Put the cursor in the right position after updating the screen.
2016-07-08 21:41:54 +02:00
Bram Moolenaar
a06ec8f345 patch 7.4.2002
Problem:    Crash when passing number to filter() or map().
Solution:   Convert to a string. (Ozaki Kiichi)
2016-07-08 20:11:07 +02:00
Bram Moolenaar
ba768495c2 patch 7.4.2001
Problem:    Tiny build fails. (Tony Mechelynck)
Solution:   Add #ifdef.
2016-07-08 15:32:54 +02:00
Bram Moolenaar
245a7cb6d3 patch 7.4.2000
Problem:    Evalcmd test fails.
Solution:   Add missing piece.
2016-07-08 10:53:12 +02:00
Bram Moolenaar
bc5d6dd1dd patch 7.4.1999
Problem:    evalcmd() doesn't work recursively.
Solution:   Use redir_evalcmd instead of redir_vname.
2016-07-07 23:04:18 +02:00
Bram Moolenaar
bf2cc5f36d patch 7.4.1998
Problem:    When writing buffer lines to a job there is no NL to NUL
            conversion.
Solution:   Make it work symmetrical with writing lines from a job into a
            buffer.
2016-07-07 20:45:06 +02:00
Bram Moolenaar
dcb1700186 patch 7.4.1997
Problem:    Cannot easily scroll the quickfix window.
Solution:   Add ":cbottom".
2016-07-07 18:58:59 +02:00
Bram Moolenaar
1e5e1231ac patch 7.4.1996
Problem:    Capturing the output of a command takes a few commands.
Solution:   Add evalcmd().
2016-07-07 17:33:02 +02:00
Bram Moolenaar
9d5d3c9c44 patch 7.4.1995
Problem:    GUI: cursor drawn in wrong place if a timer callback causes a
            screen update. (David Samvelyan)
Solution:   Also redraw the cursor when it's blinking and on.
2016-07-07 16:43:02 +02:00
Bram Moolenaar
05e418d436 patch 7.4.1994
Problem:    True-false test fails.
Solution:   Filter the dict to only keep the value that matters.
2016-07-07 16:35:16 +02:00
Bram Moolenaar
6bb450145e patch 7.4.1993
Problem:    Not all TRUE and FALSE arguments are tested.
Solution:   Add a few more tests.
2016-07-07 15:11:19 +02:00
Bram Moolenaar
e381d3d5e0 patch 7.4.1992
Problem:    Values for true and false can be confusing.
Solution:   Update the documentation.  Add a test.  Make v:true evaluate to
            TRUE for a non-zero-arg.
2016-07-07 14:50:41 +02:00
Bram Moolenaar
00efded106 patch 7.4.1991
Problem:    glob() does not add a symbolic link when there are no wildcards.
Solution:   Remove the call to mch_getperm().
2016-07-07 14:29:10 +02:00
34 changed files with 588 additions and 128 deletions

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 7.4. Last change: 2016 Jul 04
*eval.txt* For Vim version 7.4. Last change: 2016 Jul 06
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -100,14 +100,29 @@ To force conversion from String to Number, add zero to it: >
To avoid a leading zero to cause octal conversion, or for using a different
base, use |str2nr()|.
*TRUE* *FALSE*
For boolean operators Numbers are used. Zero is FALSE, non-zero is TRUE.
You can also use |v:false| and |v:true|. When TRUE is returned from a
function it is the Number one, FALSE is the number zero.
Note that in the command >
Note that in the command: >
:if "foo"
"foo" is converted to 0, which means FALSE. To test for a non-empty string,
use empty(): >
:" NOT executed
"foo" is converted to 0, which means FALSE. If the string starts with a
non-zero number it means TRUE: >
:if "8foo"
:" executed
To test for a non-empty string, use empty(): >
:if !empty("foo")
<
*non-zero-arg*
Function arguments often behave slightly different from |TRUE|: If the
argument is present and it evaluates to a non-zero Number, |v:true| or a
non-empty String, then the value is considere to be TRUE.
Note that " " and "0" are also non-empty strings, thus cause the mode to be
cleared. A List, Dictionary or Float is not a Number or String, thus
evaluates to FALSE.
*E745* *E728* *E703* *E729* *E730* *E731* *E908* *E910* *E913*
List, Dictionary, Funcref and Job types are not automatically converted.
@@ -694,7 +709,7 @@ expr1 *expr1* *E109*
expr2 ? expr1 : expr1
The expression before the '?' is evaluated to a number. If it evaluates to
non-zero, the result is the value of the expression between the '?' and ':',
|TRUE|, the result is the value of the expression between the '?' and ':',
otherwise the result is the value of the expression after the ':'.
Example: >
:echo lnum == 1 ? "top" : lnum
@@ -722,12 +737,12 @@ expr2 and expr3 *expr2* *expr3*
The "||" and "&&" operators take one argument on each side. The arguments
are (converted to) Numbers. The result is:
input output ~
n1 n2 n1 || n2 n1 && n2 ~
zero zero zero zero
zero non-zero non-zero zero
non-zero zero non-zero zero
non-zero non-zero non-zero non-zero
input output ~
n1 n2 n1 || n2 n1 && n2 ~
|FALSE| |FALSE| |FALSE| |FALSE|
|FALSE| |TRUE| |TRUE| |FALSE|
|TRUE| |FALSE| |TRUE| |FALSE|
|TRUE| |TRUE| |TRUE| |TRUE|
The operators can be concatenated, for example: >
@@ -743,8 +758,8 @@ arguments are not evaluated. This is like what happens in C. For example: >
let a = 1
echo a || b
This is valid even if there is no variable called "b" because "a" is non-zero,
so the result must be non-zero. Similarly below: >
This is valid even if there is no variable called "b" because "a" is |TRUE|,
so the result must be |TRUE|. Similarly below: >
echo exists("b") && b == "yes"
@@ -911,7 +926,7 @@ expr7 *expr7*
- expr7 unary minus *expr-unary--*
+ expr7 unary plus *expr-unary-+*
For '!' non-zero becomes zero, zero becomes one.
For '!' |TRUE| becomes |FALSE|, |FALSE| becomes |TRUE| (one).
For '-' the sign of the number is changed.
For '+' the number is unchanged.
@@ -1883,9 +1898,9 @@ atan2({expr}, {expr}) Float arc tangent of {expr1} / {expr2}
browse({save}, {title}, {initdir}, {default})
String put up a file requester
browsedir({title}, {initdir}) String put up a directory requester
bufexists({expr}) Number TRUE if buffer {expr} exists
buflisted({expr}) Number TRUE if buffer {expr} is listed
bufloaded({expr}) Number TRUE if buffer {expr} is loaded
bufexists({expr}) Number |TRUE| if buffer {expr} exists
buflisted({expr}) Number |TRUE| if buffer {expr} is listed
bufloaded({expr}) Number |TRUE| if buffer {expr} is loaded
bufname({expr}) String Name of the buffer {expr}
bufnr({expr} [, {create}]) Number Number of the buffer {expr}
bufwinid({expr}) Number window ID of buffer {expr}
@@ -1940,24 +1955,25 @@ cursor({lnum}, {col} [, {off}])
cursor({list}) Number move cursor to position in {list}
deepcopy({expr} [, {noref}]) any make a full copy of {expr}
delete({fname} [, {flags}]) Number delete the file or directory {fname}
did_filetype() Number TRUE if FileType autocommand event used
did_filetype() Number |TRUE| if FileType autocmd event used
diff_filler({lnum}) Number diff filler lines about {lnum}
diff_hlID({lnum}, {col}) Number diff highlighting at {lnum}/{col}
empty({expr}) Number TRUE if {expr} is empty
empty({expr}) Number |TRUE| if {expr} is empty
escape({string}, {chars}) String escape {chars} in {string} with '\'
eval({string}) any evaluate {string} into its value
eventhandler() Number TRUE if inside an event handler
evalcmd({command}) String execute {command} and get the output
eventhandler() Number |TRUE| if inside an event handler
executable({expr}) Number 1 if executable {expr} exists
exepath({expr}) String full path of the command {expr}
exists({expr}) Number TRUE if {expr} exists
exists({expr}) Number |TRUE| if {expr} exists
extend({expr1}, {expr2} [, {expr3}])
List/Dict insert items of {expr2} into {expr1}
exp({expr}) Float exponential of {expr}
expand({expr} [, {nosuf} [, {list}]])
any expand special keywords in {expr}
feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer
filereadable({file}) Number TRUE if {file} is a readable file
filewritable({file}) Number TRUE if {file} is a writable file
filereadable({file}) Number |TRUE| if {file} is a readable file
filewritable({file}) Number |TRUE| if {file} is a writable file
filter({expr}, {string}) List/Dict remove items from {expr} where
{string} is 0
finddir({name}[, {path}[, {count}]])
@@ -2022,17 +2038,17 @@ glob({expr} [, {nosuf} [, {list} [, {alllinks}]]])
glob2regpat({expr}) String convert a glob pat into a search pat
globpath({path}, {expr} [, {nosuf} [, {list} [, {alllinks}]]])
String do glob({expr}) for all dirs in {path}
has({feature}) Number TRUE if feature {feature} supported
has_key({dict}, {key}) Number TRUE if {dict} has entry {key}
has({feature}) Number |TRUE| if feature {feature} supported
has_key({dict}, {key}) Number |TRUE| if {dict} has entry {key}
haslocaldir([{winnr} [, {tabnr}]])
Number TRUE if the window executed |:lcd|
Number |TRUE| if the window executed |:lcd|
hasmapto({what} [, {mode} [, {abbr}]])
Number TRUE if mapping to {what} exists
Number |TRUE| if mapping to {what} exists
histadd({history}, {item}) String add an item to a history
histdel({history} [, {item}]) String remove an item from a history
histget({history} [, {index}]) String get the item {index} from a history
histnr({history}) Number highest index of a history
hlexists({name}) Number TRUE if highlight group {name} exists
hlexists({name}) Number |TRUE| if highlight group {name} exists
hlID({name}) Number syntax ID of highlight group {name}
hostname() String name of the machine Vim is running on
iconv({expr}, {from}, {to}) String convert encoding of {expr}
@@ -2049,9 +2065,9 @@ inputsave() Number save and clear typeahead
inputsecret({prompt} [, {text}]) String like input() but hiding the text
insert({list}, {item} [, {idx}]) List insert {item} in {list} [before {idx}]
invert({expr}) Number bitwise invert
isdirectory({directory}) Number TRUE if {directory} is a directory
islocked({expr}) Number TRUE if {expr} is locked
isnan({expr}) Number TRUE if {expr} is NaN
isdirectory({directory}) Number |TRUE| if {directory} is a directory
islocked({expr}) Number |TRUE| if {expr} is locked
isnan({expr}) Number |TRUE| if {expr} is NaN
items({dict}) List key-value pairs in {dict}
job_getchannel({job}) Channel get the channel handle for {job}
job_info({job}) Dict get information about {job}
@@ -2438,7 +2454,7 @@ assert_notmatch({pattern}, {actual} [, {msg}])
assert_true({actual} [, {msg}]) *assert_true()*
When {actual} is not true an error message is added to
|v:errors|, like with |assert_equal()|.
A value is true when it is a non-zero number. When {actual}
A value is TRUE when it is a non-zero number. When {actual}
is not a number the assert fails.
When {msg} is omitted an error in the form "Expected True but
got {actual}" is produced.
@@ -2483,9 +2499,9 @@ atan2({expr1}, {expr2}) *atan2()*
*browse()*
browse({save}, {title}, {initdir}, {default})
Put up a file requester. This only works when "has("browse")"
returns non-zero (only in some GUI versions).
returns |TRUE| (only in some GUI versions).
The input fields are:
{save} when non-zero, select file to write
{save} when |TRUE|, select file to write
{title} title for the requester
{initdir} directory to start browsing in
{default} default file name
@@ -2495,7 +2511,7 @@ browse({save}, {title}, {initdir}, {default})
*browsedir()*
browsedir({title}, {initdir})
Put up a directory requester. This only works when
"has("browse")" returns non-zero (only in some GUI versions).
"has("browse")" returns |TRUE| (only in some GUI versions).
On systems where a directory browser is not supported a file
browser is used. In that case: select a file in the directory
to be used.
@@ -2506,7 +2522,7 @@ browsedir({title}, {initdir})
browsing is not possible, an empty string is returned.
bufexists({expr}) *bufexists()*
The result is a Number, which is non-zero if a buffer called
The result is a Number, which is |TRUE| if a buffer called
{expr} exists.
If the {expr} argument is a number, buffer numbers are used.
If the {expr} argument is a string it must match a buffer name
@@ -2528,12 +2544,12 @@ bufexists({expr}) *bufexists()*
Obsolete name: buffer_exists().
buflisted({expr}) *buflisted()*
The result is a Number, which is non-zero if a buffer called
The result is a Number, which is |TRUE| if a buffer called
{expr} exists and is listed (has the 'buflisted' option set).
The {expr} argument is used like with |bufexists()|.
bufloaded({expr}) *bufloaded()*
The result is a Number, which is non-zero if a buffer called
The result is a Number, which is |TRUE| if a buffer called
{expr} exists and is loaded (shown in a window or hidden).
The {expr} argument is used like with |bufexists()|.
@@ -2785,7 +2801,7 @@ complete_add({expr}) *complete_add()*
complete_check() *complete_check()*
Check for a key typed while looking for completion matches.
This is to be used when looking for matches takes some time.
Returns non-zero when searching for matches is to be aborted,
Returns |TRUE| when searching for matches is to be aborted,
zero otherwise.
Only to be used by the function specified with the
'completefunc' option.
@@ -3045,7 +3061,7 @@ count({comp}, {expr} [, {ic} [, {start}]]) *count()*
in |List| or |Dictionary| {comp}.
If {start} is given then start with the item with this index.
{start} can only be used with a |List|.
When {ic} is given and it's non-zero then case is ignored.
When {ic} is given and it's |TRUE| then case is ignored.
*cscope_connection()*
@@ -3159,7 +3175,7 @@ delete({fname} [, {flags}]) *delete()*
when the line number is in a variable.
*did_filetype()*
did_filetype() Returns non-zero when autocommands are being executed and the
did_filetype() Returns |TRUE| when autocommands are being executed and the
FileType event has been triggered at least once. Can be used
to avoid triggering the FileType event again in the scripts
that detect the file type. |FileType|
@@ -3216,6 +3232,15 @@ eval({string}) Evaluate {string} and return the result. Especially useful to
them. Also works for |Funcref|s that refer to existing
functions.
evalcmd({command}) *evalcmd()*
Execute Ex {command} and return the output as a string. This
is equivalent to: >
redir => var
{command}
redir END
< To get a list of lines use: >
split(evalcmd(cmd), "\n")
eventhandler() *eventhandler()*
Returns 1 when inside an event handler. That is that Vim got
interrupted while waiting for the user to type a character,
@@ -3256,7 +3281,7 @@ exepath({expr}) *exepath()*
an empty string is returned.
*exists()*
exists({expr}) The result is a Number, which is non-zero if {expr} is
exists({expr}) The result is a Number, which is |TRUE| if {expr} is
defined, zero otherwise. The {expr} argument is a string,
which contains one of these:
&option-name Vim option (only checks if it exists,
@@ -3353,7 +3378,7 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()*
Expand wildcards and the following special keywords in {expr}.
'wildignorecase' applies.
If {list} is given and it is non-zero, a List will be returned.
If {list} is given and it is |TRUE|, a List will be returned.
Otherwise the result is a String and when there are several
matches, they are separated by <NL> characters. [Note: in
version 5.0 a space was used, which caused problems when a
@@ -3412,7 +3437,7 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()*
When {expr} does not start with '%', '#' or '<', it is
expanded like a file name is expanded on the command line.
'suffixes' and 'wildignore' are used, unless the optional
{nosuf} argument is given and it is non-zero.
{nosuf} argument is given and it is |TRUE|.
Names for non-existing files are included. The "**" item can
be used to search in a directory tree. For example, to find
all "README" files in the current directory and below: >
@@ -3504,9 +3529,9 @@ feedkeys({string} [, {mode}]) *feedkeys()*
Return value is always 0.
filereadable({file}) *filereadable()*
The result is a Number, which is TRUE when a file with the
The result is a Number, which is |TRUE| when a file with the
name {file} exists, and can be read. If {file} doesn't exist,
or is a directory, the result is FALSE. {file} is any
or is a directory, the result is |FALSE|. {file} is any
expression, which is used as a String.
If you don't care about the file being readable you can use
|glob()|.
@@ -3545,7 +3570,7 @@ filter({expr1}, {expr2}) *filter()*
If {expr2} is a |Funcref| it must take two arguments:
1. the key or the index of the current item.
2. the value of the current item.
The function must return TRUE if the item should be kept.
The function must return |TRUE| if the item should be kept.
Example that keeps the odd items of a list: >
func Odd(idx, val)
return a:idx % 2 == 1
@@ -4185,13 +4210,13 @@ getqflist() *getqflist()*
bufname() to get the name
lnum line number in the buffer (first line is 1)
col column number (first column is 1)
vcol non-zero: "col" is visual column
zero: "col" is byte index
vcol |TRUE|: "col" is visual column
|FALSE|: "col" is byte index
nr error number
pattern search pattern used to locate the error
text description of the error
type type of the error, 'E', '1', etc.
valid non-zero: recognized error message
valid |TRUE|: recognized error message
When there is no error list or it's empty an empty list is
returned. Quickfix list entries with non-existing buffer
@@ -4217,7 +4242,7 @@ getreg([{regname} [, 1 [, {list}]]]) *getreg()*
be restored with |setreg()|. For other registers the extra
argument is ignored, thus you can always give it.
If {list} is present and non-zero, the result type is changed
If {list} is present and |TRUE|, the result type is changed
to |List|. Each list item is one text line. Use it if you care
about zero bytes possibly present inside register: without
third argument both NLs and zero bytes are represented as NLs
@@ -4288,13 +4313,13 @@ glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) *glob()*
Expand the file wildcards in {expr}. See |wildcards| for the
use of special characters.
Unless the optional {nosuf} argument is given and is non-zero,
Unless the optional {nosuf} argument is given and is |TRUE|,
the 'suffixes' and 'wildignore' options apply: Names matching
one of the patterns in 'wildignore' will be skipped and
'suffixes' affect the ordering of matches.
'wildignorecase' always applies.
When {list} is present and it is non-zero the result is a List
When {list} is present and it is |TRUE| the result is a List
with all matching files. The advantage of using a List is,
you also get filenames containing newlines correctly.
Otherwise the result is a String and when there are several
@@ -4305,7 +4330,7 @@ glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) *glob()*
A name for a non-existing file is not included. A symbolic
link is only included if it points to an existing file.
However, when the {alllinks} argument is present and it is
non-zero then all symbolic links are included.
|TRUE| then all symbolic links are included.
For most systems backticks can be used to get files names from
any external command. Example: >
@@ -4342,12 +4367,12 @@ globpath({path}, {expr} [, {nosuf} [, {list} [, {alllinks}]]])
If the expansion fails for one of the directories, there is no
error message.
Unless the optional {nosuf} argument is given and is non-zero,
Unless the optional {nosuf} argument is given and is |TRUE|,
the 'suffixes' and 'wildignore' options apply: Names matching
one of the patterns in 'wildignore' will be skipped and
'suffixes' affect the ordering of matches.
When {list} is present and it is non-zero the result is a List
When {list} is present and it is |TRUE| the result is a List
with all matching files. The advantage of using a List is, you
also get filenames containing newlines correctly. Otherwise
the result is a String and when there are several matches,
@@ -4390,7 +4415,7 @@ hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()*
contains {what} in somewhere in the rhs (what it is mapped to)
and this mapping exists in one of the modes indicated by
{mode}.
When {abbr} is there and it is non-zero use abbreviations
When {abbr} is there and it is |TRUE| use abbreviations
instead of mappings. Don't forget to specify Insert and/or
Command-line mode.
Both the global mappings and the mappings local to the current
@@ -4549,7 +4574,7 @@ index({list}, {expr} [, {start} [, {ic}]]) *index()*
is not used here, case always matters.
If {start} is given then start looking at the item with index
{start} (may be negative for an item relative to the end).
When {ic} is given and it is non-zero, ignore case. Otherwise
When {ic} is given and it is |TRUE|, ignore case. Otherwise
case must match.
-1 is returned when {expr} is not found in {list}.
Example: >
@@ -4677,13 +4702,13 @@ invert({expr}) *invert()*
:let bits = invert(bits)
isdirectory({directory}) *isdirectory()*
The result is a Number, which is non-zero when a directory
The result is a Number, which is |TRUE| when a directory
with the name {directory} exists. If {directory} doesn't
exist, or isn't a directory, the result is FALSE. {directory}
exist, or isn't a directory, the result is |FALSE|. {directory}
is any expression, which is used as a String.
islocked({expr}) *islocked()* *E786*
The result is a Number, which is non-zero when {expr} is the
The result is a Number, which is |TRUE| when {expr} is the
name of a locked variable.
{expr} must be the name of a variable, |List| item or
|Dictionary| entry, not the variable itself! Example: >
@@ -4696,7 +4721,7 @@ islocked({expr}) *islocked()* *E786*
message. Use |exists()| to check for existence.
isnan({expr}) *isnan()*
Return non-zero if {expr} is a float with value NaN. >
Return |TRUE| if {expr} is a float with value NaN. >
echo isnan(0.0 / 0.0)
< 1 ~
@@ -5114,10 +5139,10 @@ maparg({name}[, {mode} [, {abbr} [, {dict}]]]) *maparg()*
"" Normal, Visual and Operator-pending
When {mode} is omitted, the modes for "" are used.
When {abbr} is there and it is non-zero use abbreviations
When {abbr} is there and it is |TRUE| use abbreviations
instead of mappings.
When {dict} is there and it is non-zero return a dictionary
When {dict} is there and it is |TRUE| return a dictionary
containing all the information of the mapping with the
following items:
"lhs" The {lhs} of the mapping.
@@ -5148,7 +5173,7 @@ mapcheck({name}[, {mode} [, {abbr}]]) *mapcheck()*
Check if there is a mapping that matches with {name} in mode
{mode}. See |maparg()| for {mode} and special names in
{name}.
When {abbr} is there and it is non-zero use abbreviations
When {abbr} is there and it is |TRUE| use abbreviations
instead of mappings.
A match happens with a mapping that starts with {name} and
with a mapping which is equal to the start of {name}.
@@ -5430,8 +5455,7 @@ mkdir({name} [, {path} [, {prot}]])
mode([expr]) Return a string that indicates the current mode.
If [expr] is supplied and it evaluates to a non-zero Number or
a non-empty String (|non-zero-arg|), then the full mode is
returned, otherwise only the first letter is returned. Note
that " " and "0" are also non-empty strings.
returned, otherwise only the first letter is returned.
n Normal
no Operator-pending
@@ -6541,8 +6565,8 @@ shellescape({string} [, {special}]) *shellescape()*
On MS-Windows and MS-DOS, when 'shellslash' is not set, it
will enclose {string} in double quotes and double all double
quotes within {string}.
For other systems, it will enclose {string} in single quotes
and replace all "'" with "'\''".
Otherwise it will enclose {string} in single quotes and
replace all "'" with "'\''".
When the {special} argument is present and it's a non-zero
Number or a non-empty String (|non-zero-arg|), then special
items such as "!", "%", "#" and "<cword>" will be preceded by
@@ -7294,7 +7318,7 @@ test_alloc_fail({id}, {countdown}, {repeat}) *test_alloc_fail()*
*test_disable_char_avail()*
test_disable_char_avail({expr})
When {expr} is 1 the internal char_avail() function will
return FALSE. When {expr} is 0 the char_avail() function will
return |FALSE|. When {expr} is 0 the char_avail() function will
function normally.
Only use this for a test where typeahead causes the test not
to work. E.g., to trigger the CursorMovedI autocommand event.
@@ -7543,16 +7567,12 @@ visualmode([expr]) *visualmode()*
Visual mode that was used.
If Visual mode is active, use |mode()| to get the Visual mode
(e.g., in a |:vmap|).
*non-zero-arg*
If [expr] is supplied and it evaluates to a non-zero Number or
a non-empty String, then the Visual mode will be cleared and
the old value is returned. Note that " " and "0" are also
non-empty strings, thus cause the mode to be cleared. A List,
Dictionary or Float is not a Number or String, thus does not
cause the mode to be cleared.
the old value is returned. See |non-zero-arg|.
wildmenumode() *wildmenumode()*
Returns non-zero when the wildmenu is active and zero
Returns |TRUE| when the wildmenu is active and |FALSE|
otherwise. See 'wildmenu' and 'wildmode'.
This can be used in mappings to handle the 'wildcharm' option
gracefully. (Makes only sense with |mapmode-c| mappings).

View File

@@ -437,6 +437,12 @@ EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST:
:lw[indow] [height] Same as ":cwindow", except use the window showing the
location list for the current window.
:cbo[ttom] Put the cursor in the last line of the quickfix window
and scroll to make it visible. This is useful for
when errors are added by an asynchronous callback.
Only call it once in a while if there are many
updates to avoid a lot of redrawing.
Normally the quickfix window is at the bottom of the screen. If there are
vertical splits, it's at the bottom of the rightmost column of windows. To
make it always occupy the full width: >

View File

@@ -2023,6 +2023,7 @@ test_arglist \
test_cmdline \
test_cursor_func \
test_delete \
test_evalcmd \
test_ex_undo \
test_expand \
test_expand_dllpath \
@@ -2068,11 +2069,12 @@ test_arglist \
test_statusline \
test_syn_attr \
test_syntax \
test_usercommands \
test_tabline \
test_tagjump \
test_timers \
test_true_false \
test_undolevels \
test_usercommands \
test_unlet \
test_viminfo \
test_viml \

View File

@@ -459,14 +459,6 @@ aucmd_abort:
#endif
buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0));
if (
#ifdef FEAT_WINDOWS
win_valid(win) &&
#else
win != NULL &&
#endif
win->w_buffer == buf)
win->w_buffer = NULL; /* make sure we don't use the buffer now */
#ifdef FEAT_AUTOCMD
/* Autocommands may have deleted the buffer. */
@@ -477,11 +469,6 @@ aucmd_abort:
return;
# endif
/* Autocommands may have opened or closed windows for this buffer.
* Decrement the count for the close we do here. */
if (buf->b_nwindows > 0)
--buf->b_nwindows;
/*
* It's possible that autocommands change curbuf to the one being deleted.
* This might cause the previous curbuf to be deleted unexpectedly. But
@@ -491,6 +478,20 @@ aucmd_abort:
*/
if (buf == curbuf && !is_curbuf)
return;
if (
#ifdef FEAT_WINDOWS
win_valid(win) &&
#else
win != NULL &&
#endif
win->w_buffer == buf)
win->w_buffer = NULL; /* make sure we don't use the buffer now */
/* Autocommands may have opened or closed windows for this buffer.
* Decrement the count for the close we do here. */
if (buf->b_nwindows > 0)
--buf->b_nwindows;
#endif
/* Change directories when the 'acd' option is set. */

View File

@@ -1313,14 +1313,20 @@ write_buf_line(buf_T *buf, linenr_T lnum, channel_T *channel)
char_u *line = ml_get_buf(buf, lnum, FALSE);
int len = (int)STRLEN(line);
char_u *p;
int i;
/* Need to make a copy to be able to append a NL. */
if ((p = alloc(len + 2)) == NULL)
return;
memcpy((char *)p, (char *)line, len);
for (i = 0; i < len; ++i)
if (p[i] == NL)
p[i] = NUL;
p[len] = NL;
p[len + 1] = NUL;
channel_send(channel, PART_IN, p, "write_buf_line()");
channel_send(channel, PART_IN, p, len + 1, "write_buf_line()");
vim_free(p);
}
@@ -2185,7 +2191,7 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
{
channel_send(channel,
part == PART_SOCK ? PART_SOCK : PART_IN,
json, (char *)cmd);
json, (int)STRLEN(json), (char *)cmd);
vim_free(json);
}
}
@@ -3380,9 +3386,8 @@ channel_handle_events(void)
* Return FAIL or OK.
*/
int
channel_send(channel_T *channel, int part, char_u *buf, char *fun)
channel_send(channel_T *channel, int part, char_u *buf, int len, char *fun)
{
int len = (int)STRLEN(buf);
int res;
sock_T fd;
@@ -3470,7 +3475,7 @@ send_common(
opt->jo_callback, opt->jo_partial, id);
}
if (channel_send(channel, part_send, text, fun) == OK
if (channel_send(channel, part_send, text, (int)STRLEN(text), fun) == OK
&& opt->jo_callback == NULL)
return channel;
return NULL;

View File

@@ -555,6 +555,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv);
static void f_empty(typval_T *argvars, typval_T *rettv);
static void f_escape(typval_T *argvars, typval_T *rettv);
static void f_eval(typval_T *argvars, typval_T *rettv);
static void f_evalcmd(typval_T *argvars, typval_T *rettv);
static void f_eventhandler(typval_T *argvars, typval_T *rettv);
static void f_executable(typval_T *argvars, typval_T *rettv);
static void f_exepath(typval_T *argvars, typval_T *rettv);
@@ -1133,6 +1134,7 @@ set_internal_string_var(char_u *name, char_u *value)
}
static lval_T *redir_lval = NULL;
#define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval)
static garray_T redir_ga; /* only valid when redir_lval is not NULL */
static char_u *redir_endp = NULL;
static char_u *redir_varname = NULL;
@@ -1250,6 +1252,12 @@ var_redir_stop(void)
{
typval_T tv;
if (EVALCMD_BUSY)
{
redir_lval = NULL;
return;
}
if (redir_lval != NULL)
{
/* If there was no error: assign the text to the variable. */
@@ -8556,6 +8564,7 @@ static struct fst
{"empty", 1, 1, f_empty},
{"escape", 2, 2, f_escape},
{"eval", 1, 1, f_eval},
{"evalcmd", 1, 1, f_evalcmd},
{"eventhandler", 0, 0, f_eventhandler},
{"executable", 1, 1, f_executable},
{"exepath", 1, 1, f_exepath},
@@ -9414,6 +9423,8 @@ non_zero_arg(typval_T *argvars)
{
return ((argvars[0].v_type == VAR_NUMBER
&& argvars[0].vval.v_number != 0)
|| (argvars[0].v_type == VAR_SPECIAL
&& argvars[0].vval.v_number == VVAL_TRUE)
|| (argvars[0].v_type == VAR_STRING
&& argvars[0].vval.v_string != NULL
&& *argvars[0].vval.v_string != NUL));
@@ -11334,6 +11345,65 @@ f_eval(typval_T *argvars, typval_T *rettv)
EMSG(_(e_trailing));
}
static garray_T redir_evalcmd_ga;
/*
* Append "value[value_len]" to the evalcmd() output.
*/
void
evalcmd_redir_str(char_u *value, int value_len)
{
int len;
if (value_len == -1)
len = (int)STRLEN(value); /* Append the entire string */
else
len = value_len; /* Append only "value_len" characters */
if (ga_grow(&redir_evalcmd_ga, len) == OK)
{
mch_memmove((char *)redir_evalcmd_ga.ga_data
+ redir_evalcmd_ga.ga_len, value, len);
redir_evalcmd_ga.ga_len += len;
}
}
/*
* "evalcmd()" function
*/
static void
f_evalcmd(typval_T *argvars, typval_T *rettv)
{
char_u *s;
int save_msg_silent = msg_silent;
int save_redir_evalcmd = redir_evalcmd;
garray_T save_ga;
rettv->vval.v_string = NULL;
rettv->v_type = VAR_STRING;
s = get_tv_string_chk(&argvars[0]);
if (s != NULL)
{
if (redir_evalcmd)
save_ga = redir_evalcmd_ga;
ga_init2(&redir_evalcmd_ga, (int)sizeof(char), 500);
redir_evalcmd = TRUE;
++msg_silent;
do_cmdline_cmd(s);
rettv->vval.v_string = redir_evalcmd_ga.ga_data;
msg_silent = save_msg_silent;
redir_evalcmd = save_redir_evalcmd;
if (redir_evalcmd)
redir_evalcmd_ga = save_ga;
/* "silent reg" or "silent echo x" leaves msg_col somewhere in the
* line. Put it back in the first column. */
msg_col = 0;
}
}
/*
* "eventhandler()" function
*/
@@ -11978,6 +12048,7 @@ filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
{
typval_T rettv;
typval_T argv[3];
char_u buf[NUMBUFLEN];
char_u *s;
int retval = FAIL;
int dummy;
@@ -11985,9 +12056,9 @@ filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
copy_tv(tv, &vimvars[VV_VAL].vv_tv);
argv[0] = vimvars[VV_KEY].vv_tv;
argv[1] = vimvars[VV_VAL].vv_tv;
s = expr->vval.v_string;
if (expr->v_type == VAR_FUNC)
{
s = expr->vval.v_string;
if (call_func(s, (int)STRLEN(s),
&rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL, NULL) == FAIL)
goto theend;
@@ -12004,6 +12075,9 @@ filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
}
else
{
s = get_tv_string_buf_chk(expr, buf);
if (s == NULL)
goto theend;
s = skipwhite(s);
if (eval1(&s, &rettv, TRUE) == FAIL)
goto theend;
@@ -16350,7 +16424,13 @@ f_mode(typval_T *argvars, typval_T *rettv)
buf[1] = NUL;
buf[2] = NUL;
if (VIsual_active)
if (time_for_testing == 93784)
{
/* Testing the two-character code. */
buf[0] = 'x';
buf[1] = '!';
}
else if (VIsual_active)
{
if (VIsual_select)
buf[0] = VIsual_mode + 's' - 'v';

View File

@@ -259,6 +259,9 @@ EX(CMD_catch, "catch", ex_catch,
EX(CMD_cbuffer, "cbuffer", ex_cbuffer,
BANG|RANGE|NOTADR|WORD1|TRLBAR,
ADDR_LINES),
EX(CMD_cbottom, "cbottom", ex_cbottom,
TRLBAR,
ADDR_LINES),
EX(CMD_cc, "cc", ex_cc,
RANGE|NOTADR|COUNT|TRLBAR|BANG,
ADDR_LINES),

View File

@@ -129,6 +129,7 @@ static int getargopt(exarg_T *eap);
# define ex_cclose ex_ni
# define ex_copen ex_ni
# define ex_cwindow ex_ni
# define ex_cbottom ex_ni
#endif
#if !defined(FEAT_QUICKFIX) || !defined(FEAT_EVAL)
# define ex_cexpr ex_ni
@@ -9454,6 +9455,14 @@ ex_redir(exarg_T *eap)
char_u *fname;
char_u *arg = eap->arg;
#ifdef FEAT_EVAL
if (redir_evalcmd)
{
EMSG(_("E930: Cannot use :redir inside evalcmd()"));
return;
}
#endif
if (STRICMP(eap->arg, "END") == 0)
close_redir();
else

View File

@@ -1106,6 +1106,7 @@ EXTERN FILE *redir_fd INIT(= NULL); /* message redirection file */
#ifdef FEAT_EVAL
EXTERN int redir_reg INIT(= 0); /* message redirection register */
EXTERN int redir_vname INIT(= 0); /* message redirection variable */
EXTERN int redir_evalcmd INIT(= 0); /* evalcmd() redirection */
#endif
#ifdef FEAT_LANGMAP

View File

@@ -818,6 +818,12 @@ gui_mch_is_blinking(void)
return blink_state != BLINK_NONE;
}
int
gui_mch_is_blink_off(void)
{
return blink_state == BLINK_OFF;
}
void
gui_mch_set_blinking(long waittime, long on, long off)
{

View File

@@ -5116,6 +5116,12 @@ gui_mch_destroy_scrollbar(scrollbar_T *sb)
int
gui_mch_is_blinking(void)
{
return FALSE;
}
int
gui_mch_is_blink_off(void)
{
return FALSE;
}

View File

@@ -2238,6 +2238,12 @@ gui_mch_is_blinking(void)
return blink_state != BLINK_NONE;
}
int
gui_mch_is_blink_off(void)
{
return blink_state == BLINK_OFF;
}
void
gui_mch_set_blinking(long wait, long on, long off)
{

View File

@@ -546,6 +546,12 @@ gui_mch_is_blinking(void)
return blink_state != BLINK_NONE;
}
int
gui_mch_is_blink_off(void)
{
return blink_state == BLINK_OFF;
}
void
gui_mch_set_blinking(long wait, long on, long off)
{

View File

@@ -3161,6 +3161,12 @@ gui_mch_is_blinking(void)
return blink_state != BLINK_NONE;
}
int
gui_mch_is_blink_off(void)
{
return blink_state == BLINK_OFF;
}
void
gui_mch_set_blinking(long waittime, long on, long off)
{

View File

@@ -3063,7 +3063,9 @@ redir_write(char_u *str, int maxlen)
while (cur_col < msg_col)
{
#ifdef FEAT_EVAL
if (redir_reg)
if (redir_evalcmd)
evalcmd_redir_str((char_u *)" ", -1);
else if (redir_reg)
write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
else if (redir_vname)
var_redir_str((char_u *)" ", -1);
@@ -3078,9 +3080,11 @@ redir_write(char_u *str, int maxlen)
}
#ifdef FEAT_EVAL
if (redir_reg)
if (redir_evalcmd)
evalcmd_redir_str(s, maxlen);
else if (redir_reg)
write_reg_contents(redir_reg, s, maxlen, TRUE);
if (redir_vname)
else if (redir_vname)
var_redir_str(s, maxlen);
#endif
@@ -3088,7 +3092,7 @@ redir_write(char_u *str, int maxlen)
while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
{
#ifdef FEAT_EVAL
if (!redir_reg && !redir_vname)
if (!redir_reg && !redir_vname && !redir_evalcmd)
#endif
if (redir_fd != NULL)
putc(*s, redir_fd);
@@ -3113,7 +3117,7 @@ redirecting(void)
{
return redir_fd != NULL || *p_vfile != NUL
#ifdef FEAT_EVAL
|| redir_reg || redir_vname
|| redir_reg || redir_vname || redir_evalcmd
#endif
;
}

View File

@@ -10864,7 +10864,7 @@ gen_expand_wildcards(
* "vim c:/" work. */
if (flags & EW_NOTFOUND)
addfile(&ga, t, flags | EW_DIR | EW_FILE);
else if (mch_getperm(t) >= 0)
else
addfile(&ga, t, flags);
vim_free(t);
}

View File

@@ -765,7 +765,8 @@ netbeans_end(void)
nb_send(char *buf, char *fun)
{
if (nb_channel != NULL)
channel_send(nb_channel, PART_SOCK, (char_u *)buf, fun);
channel_send(nb_channel, PART_SOCK, (char_u *)buf,
(int)STRLEN(buf), fun);
}
/*

View File

@@ -34,7 +34,7 @@ int channel_read_json_block(channel_T *channel, int part, int timeout_arg, int i
void common_channel_read(typval_T *argvars, typval_T *rettv, int raw);
channel_T *channel_fd2channel(sock_T fd, int *partp);
void channel_handle_events(void);
int channel_send(channel_T *channel, int part, char_u *buf, char *fun);
int channel_send(channel_T *channel, int part, char_u *buf, int len, char *fun);
channel_T *send_common(typval_T *argvars, char_u *text, int id, int eval, jobopt_T *opt, char *fun, int *part_read);
void ch_expr_common(typval_T *argvars, typval_T *rettv, int eval);
void ch_raw_common(typval_T *argvars, typval_T *rettv, int eval);

View File

@@ -81,12 +81,14 @@ int dict_add_list(dict_T *d, char *key, list_T *list);
dictitem_T *dict_find(dict_T *d, char_u *key, int len);
char_u *get_dict_string(dict_T *d, char_u *key, int save);
varnumber_T get_dict_number(dict_T *d, char_u *key);
char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
int string2float(char_u *text, float_T *value);
char_u *get_function_name(expand_T *xp, int idx);
char_u *get_expr_name(expand_T *xp, int idx);
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict_in);
buf_T *buflist_find_by_name(char_u *name, int curtab_only);
int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
void evalcmd_redir_str(char_u *value, int value_len);
void dict_extend(dict_T *d1, dict_T *d2, char_u *action);
void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
float_T vim_round(float_T f);
@@ -150,5 +152,4 @@ void ex_oldfiles(exarg_T *eap);
void reset_v_option_vars(void);
int modify_fname(char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen);
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags);
char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
/* vim: set ft=c : */

View File

@@ -2,6 +2,7 @@
void gui_mch_prepare(int *argc, char **argv);
void gui_mch_free_all(void);
int gui_mch_is_blinking(void);
int gui_mch_is_blink_off(void);
void gui_mch_set_blinking(long waittime, long on, long off);
void gui_mch_stop_blink(void);
void gui_mch_start_blink(void);

View File

@@ -15,6 +15,7 @@ void gui_mac_focus_change(EventRecord *event);
void gui_mac_update(EventRecord *event);
short gui_mch_get_mac_menu_item_index(vimmenu_T *menu, vimmenu_T *parent);
int gui_mch_is_blinking(void);
int gui_mch_is_blink_off(void);
void gui_mch_set_blinking(long wait, long on, long off);
void gui_mch_stop_blink(void);
void gui_mch_start_blink(void);

View File

@@ -40,6 +40,7 @@ void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags);
void gui_mch_draw_hollow_cursor(guicolor_T color);
void gui_mch_draw_part_cursor(int w, int h, guicolor_T color);
int gui_mch_is_blinking(void);
int gui_mch_is_blink_off(void);
void gui_mch_set_blinking(long wait, long on, long off);
void gui_mch_start_blink(void);
void gui_mch_stop_blink(void);

View File

@@ -2,6 +2,7 @@
int directx_enabled(void);
int gui_mch_set_rendering_options(char_u *s);
int gui_mch_is_blinking(void);
int gui_mch_is_blink_off(void);
void gui_mch_set_blinking(long wait, long on, long off);
void gui_mch_stop_blink(void);
void gui_mch_start_blink(void);

View File

@@ -54,6 +54,7 @@ void gui_mch_menu_hidden(vimmenu_T *menu, int hidden);
void gui_mch_draw_menubar(void);
void gui_x11_menu_cb(Widget w, XtPointer client_data, XtPointer call_data);
int gui_mch_is_blinking(void);
int gui_mch_is_blink_off(void);
void gui_mch_set_blinking(long waittime, long on, long off);
void gui_mch_stop_blink(void);
void gui_mch_start_blink(void);

View File

@@ -9,6 +9,7 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long
void ex_cwindow(exarg_T *eap);
void ex_cclose(exarg_T *eap);
void ex_copen(exarg_T *eap);
void ex_cbottom(exarg_T *eap);
linenr_T qf_current_entry(win_T *wp);
int bt_quickfix(buf_T *buf);
int bt_nofile(buf_T *buf);

View File

@@ -2807,6 +2807,41 @@ ex_copen(exarg_T *eap)
update_topline(); /* scroll to show the line */
}
/*
* Move the cursor in the quickfix window to "lnum".
*/
static void
qf_win_goto(win_T *win, linenr_T lnum)
{
win_T *old_curwin = curwin;
curwin = win;
curbuf = win->w_buffer;
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = 0;
#ifdef FEAT_VIRTUALEDIT
curwin->w_cursor.coladd = 0;
#endif
curwin->w_curswant = 0;
update_topline(); /* scroll to show the line */
redraw_later(VALID);
curwin->w_redr_status = TRUE; /* update ruler */
curwin = old_curwin;
curbuf = curwin->w_buffer;
}
/*
* :cbottom command.
*/
void
ex_cbottom(exarg_T *eap UNUSED)
{
win_T *win = qf_find_win(&ql_info);
if (win != NULL && win->w_cursor.lnum != win->w_buffer->b_ml.ml_line_count)
qf_win_goto(win, win->w_buffer->b_ml.ml_line_count);
}
/*
* Return the number of the current entry (line number in the quickfix
* window).
@@ -2844,27 +2879,17 @@ qf_win_pos_update(
&& qf_index <= win->w_buffer->b_ml.ml_line_count
&& old_qf_index != qf_index)
{
win_T *old_curwin = curwin;
curwin = win;
curbuf = win->w_buffer;
if (qf_index > old_qf_index)
{
curwin->w_redraw_top = old_qf_index;
curwin->w_redraw_bot = qf_index;
win->w_redraw_top = old_qf_index;
win->w_redraw_bot = qf_index;
}
else
{
curwin->w_redraw_top = qf_index;
curwin->w_redraw_bot = old_qf_index;
win->w_redraw_top = qf_index;
win->w_redraw_bot = old_qf_index;
}
curwin->w_cursor.lnum = qf_index;
curwin->w_cursor.col = 0;
update_topline(); /* scroll to show the line */
redraw_later(VALID);
curwin->w_redr_status = TRUE; /* update ruler */
curwin = old_curwin;
curbuf = curwin->w_buffer;
qf_win_goto(win, qf_index);
}
return win != NULL;
}

View File

@@ -422,7 +422,7 @@ redraw_after_callback(void)
; /* do nothing */
else if (State & CMDLINE)
redrawcmdline();
else if ((State & NORMAL) || (State & INSERT))
else if (State & (NORMAL | INSERT))
{
update_screen(0);
setcursor();
@@ -432,9 +432,9 @@ redraw_after_callback(void)
#ifdef FEAT_GUI
if (gui.in_use)
{
/* Don't update the cursor while it is blinking, it will get
* updated soon and this avoids interrupting the blinking. */
if (!gui_mch_is_blinking())
/* Don't update the cursor when it is blinking and off to avoid
* flicker. */
if (!gui_mch_is_blink_off())
gui_update_cursor(FALSE, FALSE);
gui_mch_flush();
}
@@ -486,8 +486,6 @@ update_curbuf(int type)
}
/*
* update_screen()
*
* Based on the current value of curwin->w_topline, transfer a screenfull
* of stuff from Filemem to ScreenLines[], and update curwin->w_botline.
*/
@@ -499,6 +497,10 @@ update_screen(int type)
#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
int did_one;
#endif
#ifdef FEAT_GUI
int gui_cursor_col;
int gui_cursor_row;
#endif
/* Don't do anything if the screen structures are (not yet) valid. */
if (!screen_valid(TRUE))
@@ -696,7 +698,11 @@ update_screen(int type)
* scrolling may make it difficult to redraw the text under
* it. */
if (gui.in_use)
{
gui_cursor_col = gui.cursor_col;
gui_cursor_row = gui.cursor_row;
gui_undraw_cursor();
}
#endif
}
#endif
@@ -752,7 +758,15 @@ update_screen(int type)
{
out_flush(); /* required before updating the cursor */
if (did_one)
{
/* Put the GUI position where the cursor was, gui_update_cursor()
* uses that. */
gui.col = gui_cursor_col;
gui.row = gui_cursor_row;
gui_update_cursor(FALSE, FALSE);
screen_cur_col = gui.col;
screen_cur_row = gui.row;
}
gui_update_scrollbars(FALSE);
}
#endif

View File

@@ -5,9 +5,10 @@ source test_assign.vim
source test_autocmd.vim
source test_cursor_func.vim
source test_delete.vim
source test_evalcmd.vim
source test_ex_undo.vim
source test_expr.vim
source test_expand.vim
source test_expr.vim
source test_expand_dllpath.vim
source test_feedkeys.vim
source test_fnamemodify.vim
@@ -33,6 +34,7 @@ source test_syn_attr.vim
source test_tabline.vim
source test_tagjump.vim
source test_timers.vim
source test_true_false.vim
source test_undolevels.vim
source test_unlet.vim
source test_window_cmd.vim

View File

@@ -60,3 +60,21 @@ function Test_bufunload()
augroup! test_bufunload_group
endfunc
" SEGV occurs in older versions. (At least 7.4.2005 or older)
function Test_autocmd_bufunload_with_tabnext()
tabedit
tabfirst
augroup test_autocmd_bufunload_with_tabnext_group
autocmd!
autocmd BufUnload <buffer> tabnext
augroup END
quit
call assert_equal(2, tabpagenr('$'))
augroup! test_autocmd_bufunload_with_tabnext_group
tablast
quit
endfunc

View File

@@ -0,0 +1,33 @@
" test evalcmd()
func NestedEval()
let nested = evalcmd('echo "nested\nlines"')
echo 'got: "' . nested . '"'
endfunc
func NestedRedir()
redir => var
echo 'broken'
redir END
endfunc
func Test_evalcmd()
call assert_equal("\nnocompatible", evalcmd('set compatible?'))
call assert_equal("\nsomething\nnice", evalcmd('echo "something\nnice"'))
call assert_equal("noendofline", evalcmd('echon "noendofline"'))
call assert_equal("", evalcmd(123))
call assert_equal("\ngot: \"\nnested\nlines\"", evalcmd('call NestedEval()'))
redir => redired
echo 'this'
let evaled = evalcmd('echo "that"')
echo 'theend'
redir END
call assert_equal("\nthis\ntheend", redired)
call assert_equal("\nthat", evaled)
call assert_fails('call evalcmd("doesnotexist")', 'E492:')
call assert_fails('call evalcmd(3.4)', 'E806:')
call assert_fails('call evalcmd("call NestedRedir()")', 'E930:')
endfunc

View File

@@ -5,10 +5,12 @@ func Test_filter_map_list_expr_string()
" filter()
call assert_equal([2, 3, 4], filter([1, 2, 3, 4], 'v:val > 1'))
call assert_equal([3, 4], filter([1, 2, 3, 4], 'v:key > 1'))
call assert_equal([], filter([1, 2, 3, 4], 0))
" map()
call assert_equal([2, 4, 6, 8], map([1, 2, 3, 4], 'v:val * 2'))
call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], 'v:key * 2'))
call assert_equal([9, 9, 9, 9], map([1, 2, 3, 4], 9))
endfunc
" dict with expression string
@@ -18,10 +20,12 @@ func Test_filter_map_dict_expr_string()
" filter()
call assert_equal({"bar": 2, "baz": 3}, filter(copy(dict), 'v:val > 1'))
call assert_equal({"foo": 1, "baz": 3}, filter(copy(dict), 'v:key > "bar"'))
call assert_equal({}, filter(copy(dict), 0))
" map()
call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), 'v:val * 2'))
call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), 'v:key[0]'))
call assert_equal({"foo": 9, "bar": 9, "baz": 9}, map(copy(dict), 9))
endfunc
" list with funcref

View File

@@ -1414,3 +1414,16 @@ echo string(loc_two)
call delete('Xone', 'rf')
call delete('Xtwo', 'rf')
endfunc
function Test_cbottom()
call setqflist([{'filename': 'foo', 'lnum': 42}])
copen
let wid = win_getid()
call assert_equal(1, line('.'))
wincmd w
call setqflist([{'filename': 'var', 'lnum': 24}], 'a')
cbottom
call win_gotoid(wid)
call assert_equal(2, line('.'))
cclose
endfunc

View File

@@ -0,0 +1,150 @@
" Test behavior of boolean-like values.
" Test what is explained at ":help TRUE" and ":help FALSE".
func Test_if()
if v:false
call assert_true(false, 'v:false is false')
endif
if 0
call assert_true(false, 'zero is false')
endif
if "0"
call assert_true(false, 'zero string is false')
endif
if "foo"
call assert_true(false, 'foo is false')
endif
if " "
call assert_true(false, 'space is false')
endif
if empty("foo")
call assert_true(false, 'foo is not empty')
endif
if v:true
else
call assert_true(false, 'v:true is true')
endif
if 1
else
call assert_true(false, 'one is true')
endif
if "1"
else
call assert_true(false, 'one string is true')
endif
if "1foo"
else
call assert_true(false, 'one in string is true')
endif
call assert_fails('if [1]', 'E745')
call assert_fails('if {1: 1}', 'E728')
call assert_fails('if function("string")', 'E703')
call assert_fails('if 1.3")', 'E805')
endfunc
function Try_arg_true_false(expr, false_val, true_val)
for v in ['v:false', '0', '"0"', '"foo"', '" "']
let r = eval(substitute(a:expr, '%v%', v, ''))
call assert_equal(a:false_val, r, 'result for ' . v . ' is not ' . string(a:false_val) . ' but ' . string(r))
endfor
for v in ['v:true', '1', '"1"', '"1foo"']
let r = eval(substitute(a:expr, '%v%', v, ''))
call assert_equal(a:true_val, r, 'result for ' . v . ' is not ' . string(a:true_val) . ' but ' . string(r))
endfor
endfunc
" Test using TRUE or FALSE values for an argument.
func Test_true_false_arg()
call Try_arg_true_false('count(["a", "A"], "a", %v%)', 1, 2)
set wildignore=*.swp
call Try_arg_true_false('expand("foo.swp", %v%)', "", "foo.swp")
call Try_arg_true_false('expand("foo.vim", 0, %v%)', "foo.vim", ["foo.vim"])
call setreg('a', ['x', 'y'])
call Try_arg_true_false('getreg("a", 1, %v%)', "x\ny\n", ['x', 'y'])
set wildignore=*.vim
call Try_arg_true_false('glob("runtest.vim", %v%)', "", "runtest.vim")
set wildignore=*.swp
call Try_arg_true_false('glob("runtest.vim", 0, %v%)', "runtest.vim", ["runtest.vim"])
if has('unix')
silent !ln -s doesntexit Xlink
call Try_arg_true_false('glob("Xlink", 0, 0, %v%)', "", "Xlink")
silent !rm Xlink
endif
set wildignore=*.vim
call Try_arg_true_false('globpath(".", "runtest.vim", %v%)', "", "./runtest.vim")
set wildignore=*.swp
call Try_arg_true_false('globpath(".", "runtest.vim", 0, %v%)', "./runtest.vim", ["./runtest.vim"])
if has('unix')
silent !ln -s doesntexit Xlink
call Try_arg_true_false('globpath(".", "Xlink", 0, 0, %v%)', "", "./Xlink")
silent !rm Xlink
endif
abbr asdf asdff
call Try_arg_true_false('hasmapto("asdff", "i", %v%)', 0, 1)
call Try_arg_true_false('index(["a", "A"], "A", 0, %v%)', 1, 0)
function FilterMapArg(d)
if type(a:d) == type({})
return filter(a:d, 'v:key == "rhs"')
endif
return a:d
endfunction
call Try_arg_true_false('maparg("asdf", "i", %v%)', "", "asdff")
call Try_arg_true_false('FilterMapArg(maparg("asdf", "i", 1, %v%))', "asdff", {'rhs': 'asdff'})
call Try_arg_true_false('hasmapto("asdf", "i", %v%)', 0, 1)
new colored
call setline(1, '<here>')
syn match brackets "<.*>"
syn match here "here" transparent
let brackets_id = synID(1, 1, 0)
let here_id = synID(1, 3, 0)
call Try_arg_true_false('synID(1, 3, %v%)', here_id, brackets_id)
bwipe!
endfunc
function Try_arg_non_zero(expr, false_val, true_val)
for v in ['v:false', '0', '[1]', '{2:3}', '3.4']
let r = eval(substitute(a:expr, '%v%', v, ''))
call assert_equal(a:false_val, r, 'result for ' . v . ' is not ' . a:false_val . ' but ' . r)
endfor
for v in ['v:true', '1', '" "', '"0"']
let r = eval(substitute(a:expr, '%v%', v, ''))
call assert_equal(a:true_val, r, 'result for ' . v . ' is not ' . a:true_val . ' but ' . r)
endfor
endfunc
" Test using non-zero-arg for an argument.
func Test_non_zero_arg()
call test_settime(93784)
call Try_arg_non_zero("mode(%v%)", 'x', 'x!')
call test_settime(0)
call Try_arg_non_zero("shellescape('foo%', %v%)", "'foo%'", "'foo\\%'")
" visualmode() needs to be called twice to check
for v in [v:false, 0, [1], {2:3}, 3.4]
normal vv
let r = visualmode(v)
call assert_equal('v', r, 'result for ' . string(v) . ' is not "v" but ' . r)
let r = visualmode(v)
call assert_equal('v', r, 'result for ' . string(v) . ' is not "v" but ' . r)
endfor
for v in [v:true, 1, " ", "0"]
normal vv
let r = visualmode(v)
call assert_equal('v', r, 'result for ' . v . ' is not "v" but ' . r)
let r = visualmode(v)
call assert_equal('', r, 'result for ' . v . ' is not "" but ' . r)
endfor
endfunc

View File

@@ -758,6 +758,38 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2006,
/**/
2005,
/**/
2004,
/**/
2003,
/**/
2002,
/**/
2001,
/**/
2000,
/**/
1999,
/**/
1998,
/**/
1997,
/**/
1996,
/**/
1995,
/**/
1994,
/**/
1993,
/**/
1992,
/**/
1991,
/**/
1990,
/**/