commit
007d573147
|
@ -356,6 +356,8 @@ let s:MSGPACK_STANDARD_TYPES = {
|
|||
\type(''): 'binary',
|
||||
\type([]): 'array',
|
||||
\type({}): 'map',
|
||||
\type(v:true): 'boolean',
|
||||
\type(v:null): 'nil',
|
||||
\}
|
||||
|
||||
""
|
||||
|
@ -379,7 +381,7 @@ endfunction
|
|||
""
|
||||
" Dump boolean value.
|
||||
function s:msgpack_dump_boolean(v) abort
|
||||
return a:v._VAL ? 'TRUE' : 'FALSE'
|
||||
return (a:v is v:true || (a:v isnot v:false && a:v._VAL)) ? 'TRUE' : 'FALSE'
|
||||
endfunction
|
||||
|
||||
""
|
||||
|
|
|
@ -1418,6 +1418,13 @@ v:exception The value of the exception most recently caught and not
|
|||
:endtry
|
||||
< Output: "caught oops".
|
||||
|
||||
*v:false* *false-variable*
|
||||
v:false Special value used to put "false" in JSON and msgpack. See
|
||||
|json_encode()|. This value is converted to "false" when used
|
||||
as a String (e.g. in |expr5| with string concatenation
|
||||
operator) and to zero when used as a Number (e.g. in |expr5|
|
||||
or |expr7| when used with numeric operators).
|
||||
|
||||
*v:fcs_reason* *fcs_reason-variable*
|
||||
v:fcs_reason The reason why the |FileChangedShell| event was triggered.
|
||||
Can be used in an autocommand to decide what to do and/or what
|
||||
|
@ -1557,6 +1564,13 @@ v:msgpack_types Dictionary containing msgpack types used by |msgpackparse()|
|
|||
(not editable) empty lists. To check whether some list is one
|
||||
of msgpack types, use |is| operator.
|
||||
|
||||
*v:null* *null-variable*
|
||||
v:null Special value used to put "null" in JSON and NIL in msgpack.
|
||||
See |json_encode()|. This value is converted to "null" when
|
||||
used as a String (e.g. in |expr5| with string concatenation
|
||||
operator) and to zero when used as a Number (e.g. in |expr5|
|
||||
or |expr7| when used with numeric operators).
|
||||
|
||||
*v:oldfiles* *oldfiles-variable*
|
||||
v:oldfiles List of file names that is loaded from the |shada| file on
|
||||
startup. These are the files that Vim remembers marks for.
|
||||
|
@ -1722,6 +1736,13 @@ v:throwpoint The point where the exception most recently caught and not
|
|||
:endtry
|
||||
< Output: "Exception from test.vim, line 2"
|
||||
|
||||
*v:true* *true-variable*
|
||||
v:true Special value used to put "true" in JSON and msgpack. See
|
||||
|json_encode()|. This value is converted to "true" when used
|
||||
as a String (e.g. in |expr5| with string concatenation
|
||||
operator) and to one when used as a Number (e.g. in |expr5| or
|
||||
|expr7| when used with numeric operators).
|
||||
|
||||
*v:val* *val-variable*
|
||||
v:val Value of the current item of a |List| or |Dictionary|. Only
|
||||
valid while evaluating the expression used with |map()| and
|
||||
|
@ -1932,6 +1953,8 @@ jobstart( {cmd}[, {opts}]) Number Spawns {cmd} as a job
|
|||
jobstop( {job}) Number Stops a job
|
||||
jobwait( {ids}[, {timeout}]) Number Wait for a set of jobs
|
||||
join( {list} [, {sep}]) String join {list} items into one String
|
||||
json_decode( {expr}) any Convert {expr} from JSON
|
||||
json_encode( {expr}) String Convert {expr} to JSON
|
||||
keys( {dict}) List keys in {dict}
|
||||
len( {expr}) Number the length of {expr}
|
||||
libcall( {lib}, {func}, {arg}) String call {func} in library {lib} with {arg}
|
||||
|
@ -2222,17 +2245,17 @@ assert_equal({expected}, {actual}, [, {msg}])
|
|||
|
||||
assert_false({actual}, [, {msg}]) *assert_false()*
|
||||
When {actual} is not false an error message is added to
|
||||
|v:errors|, like with |assert_equal()|..
|
||||
A value is false when it is zero. When "{actual}" is not a
|
||||
number the assert fails.
|
||||
|v:errors|, like with |assert_equal()|.
|
||||
A value is false when it is zero or |v:false|. When "{actual}"
|
||||
is not a number or |v:false| the assert fails.
|
||||
When {msg} is omitted an error in the form "Expected False but
|
||||
got {actual}" is produced.
|
||||
|
||||
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-zeron number. When {actual}
|
||||
is not a number the assert fails.
|
||||
|v:errors|, like with |assert_equal()|.
|
||||
A value is true when it is a non-zero number or |v:true|.
|
||||
When {actual} is not a number or |v:true| the assert fails.
|
||||
When {msg} is omitted an error in the form "Expected True but
|
||||
got {actual}" is produced.
|
||||
|
||||
|
@ -2826,9 +2849,8 @@ diff_hlID({lnum}, {col}) *diff_hlID()*
|
|||
empty({expr}) *empty()*
|
||||
Return the Number 1 if {expr} is empty, zero otherwise.
|
||||
A |List| or |Dictionary| is empty when it does not have any
|
||||
items. A Number is empty when its value is zero.
|
||||
For a long |List| this is much faster than comparing the
|
||||
length with zero.
|
||||
items. A Number is empty when its value is zero. Special
|
||||
variable is empty when it is |v:false| or |v:null|.
|
||||
|
||||
escape({string}, {chars}) *escape()*
|
||||
Escape the characters in {chars} that occur in {string} with a
|
||||
|
@ -4291,6 +4313,46 @@ join({list} [, {sep}]) *join()*
|
|||
converted into a string like with |string()|.
|
||||
The opposite function is |split()|.
|
||||
|
||||
json_decode({expr}) *json_decode()*
|
||||
Convert {expr} from JSON object. Accepts |readfile()|-style
|
||||
list as the input, as well as regular string. May output any
|
||||
Vim value. When 'encoding' is not UTF-8 string is converted
|
||||
from UTF-8 to 'encoding', failing conversion fails
|
||||
json_decode(). In the following cases it will output
|
||||
|msgpack-special-dict|:
|
||||
1. Dictionary contains duplicate key.
|
||||
2. Dictionary contains empty key.
|
||||
3. String contains NUL byte. Two special dictionaries: for
|
||||
dictionary and for string will be emitted in case string
|
||||
with NUL byte was a dictionary key.
|
||||
|
||||
Note: function treats its input as UTF-8 always regardless of
|
||||
'encoding' value. This is needed because JSON source is
|
||||
supposed to be external (e.g. |readfile()|) and JSON standard
|
||||
allows only a few encodings, of which UTF-8 is recommended and
|
||||
the only one required to be supported. Non-UTF-8 characters
|
||||
are an error.
|
||||
|
||||
json_encode({expr}) *json_encode()*
|
||||
Convert {expr} into a JSON string. Accepts
|
||||
|msgpack-special-dict| as the input. Converts from 'encoding'
|
||||
to UTF-8 when encoding strings. Will not convert |Funcref|s,
|
||||
mappings with non-string keys (can be created as
|
||||
|msgpack-special-dict|), values with self-referencing
|
||||
containers, strings which contain non-UTF-8 characters,
|
||||
pseudo-UTF-8 strings which contain codepoints reserved for
|
||||
surrogate pairs (such strings are not valid UTF-8 strings).
|
||||
When converting 'encoding' is taken into account, if it is not
|
||||
"utf-8", then conversion is performed before encoding strings.
|
||||
Non-printable characters are converted into "\u1234" escapes
|
||||
or special escapes like "\t", other are dumped as-is.
|
||||
|
||||
Note: all characters above U+0079 are considered non-printable
|
||||
when 'encoding' is not UTF-8. This function always outputs
|
||||
UTF-8 strings as required by the standard thus when 'encoding'
|
||||
is not unicode resulting string will look incorrect if
|
||||
"\u1234" notation is not used.
|
||||
|
||||
keys({dict}) *keys()*
|
||||
Return a |List| with all the keys of {dict}. The |List| is in
|
||||
arbitrary order.
|
||||
|
@ -4818,7 +4880,7 @@ msgpackdump({list}) {Nvim} *msgpackdump()*
|
|||
(dictionary with zero items is represented by 0x80 byte in
|
||||
messagepack).
|
||||
|
||||
Limitations: *E951* *E952*
|
||||
Limitations: *E951* *E952* *E953*
|
||||
1. |Funcref|s cannot be dumped.
|
||||
2. Containers that reference themselves cannot be dumped.
|
||||
3. Dictionary keys are always dumped as STR strings.
|
||||
|
@ -4853,9 +4915,13 @@ msgpackparse({list}) {Nvim} *msgpackparse()*
|
|||
contains name of the key from |v:msgpack_types|):
|
||||
|
||||
Key Value ~
|
||||
nil Zero, ignored when dumping.
|
||||
boolean One or zero. When dumping it is only checked that
|
||||
value is a |Number|.
|
||||
nil Zero, ignored when dumping. This value cannot
|
||||
possibly appear in |msgpackparse()| output in Neovim
|
||||
versions which have |v:null|.
|
||||
boolean One or zero. When dumping it is only checked that
|
||||
value is a |Number|. This value cannot possibly
|
||||
appear in |msgpackparse()| output in Neovim versions
|
||||
which have |v:true| and |v:false|.
|
||||
integer |List| with four numbers: sign (-1 or 1), highest two
|
||||
bits, number with bits from 62nd to 31st, lowest 31
|
||||
bits. I.e. to get actual number one will need to use
|
||||
|
@ -6729,12 +6795,14 @@ trunc({expr}) *trunc()*
|
|||
|
||||
type({expr}) *type()*
|
||||
The result is a Number, depending on the type of {expr}:
|
||||
Number: 0
|
||||
String: 1
|
||||
Number: 0
|
||||
String: 1
|
||||
Funcref: 2
|
||||
List: 3
|
||||
List: 3
|
||||
Dictionary: 4
|
||||
Float: 5
|
||||
Float: 5
|
||||
Boolean: 6 (|v:true| and |v:false|)
|
||||
Null: 7 (|v:null|)
|
||||
To avoid the magic numbers it should be used this way: >
|
||||
:if type(myvar) == type(0)
|
||||
:if type(myvar) == type("")
|
||||
|
@ -6742,6 +6810,10 @@ type({expr}) *type()*
|
|||
:if type(myvar) == type([])
|
||||
:if type(myvar) == type({})
|
||||
:if type(myvar) == type(0.0)
|
||||
:if type(myvar) == type(v:true)
|
||||
< In place of checking for |v:null| type it is better to check
|
||||
for |v:null| directly as it is the only value of this type: >
|
||||
:if myvar is v:null
|
||||
|
||||
undofile({name}) *undofile()*
|
||||
Return the name of the undo file that would be used for a file
|
||||
|
|
|
@ -99,6 +99,22 @@ are always available and may be used simultaneously in separate plugins. The
|
|||
error out.
|
||||
4. Stringifyed infinite and NaN values now use |str2float()| and can be evaled
|
||||
back.
|
||||
5. (internal) Trying to print or stringify VAR_UNKNOWN in Vim results in
|
||||
nothing, |E908|, in Neovim it is internal error.
|
||||
|
||||
|json_decode()| behaviour changed:
|
||||
1. It may output |msgpack-special-dict|.
|
||||
2. |msgpack-special-dict| is emitted also in case of duplicate keys, while in
|
||||
Vim it errors out.
|
||||
3. It accepts only valid JSON. Trailing commas are not accepted.
|
||||
|
||||
|json_encode()| behaviour slightly changed: now |msgpack-special-dict| values
|
||||
are accepted, but |v:none| is not.
|
||||
|
||||
*v:none* variable is absent. In Vim it represents “no value” in “js” strings
|
||||
like "[,]" parsed as "[v:none]" by |js_decode()|.
|
||||
|
||||
*js_encode()* and *js_decode()* functions are also absent.
|
||||
|
||||
Viminfo text files were replaced with binary (messagepack) ShaDa files.
|
||||
Additional differences:
|
||||
|
|
|
@ -41,22 +41,25 @@ include_directories(${GENERATED_DIR})
|
|||
include_directories(${GENERATED_INCLUDES_DIR})
|
||||
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR})
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/os)
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/api)
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/api/private)
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/msgpack_rpc)
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/tui)
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/event)
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR})
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/os)
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/api)
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/api/private)
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/msgpack_rpc)
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/tui)
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/event)
|
||||
|
||||
file(GLOB NEOVIM_SOURCES *.c os/*.c api/*.c api/private/*.c msgpack_rpc/*.c
|
||||
tui/*.c event/*.c)
|
||||
file(GLOB NEOVIM_SOURCES *.c)
|
||||
|
||||
foreach(subdir
|
||||
os
|
||||
api
|
||||
api/private
|
||||
msgpack_rpc
|
||||
tui
|
||||
event
|
||||
eval
|
||||
)
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/${subdir})
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/${subdir})
|
||||
file(GLOB sources ${subdir}/*.c)
|
||||
list(APPEND NEOVIM_SOURCES ${sources})
|
||||
endforeach()
|
||||
|
||||
file(GLOB_RECURSE NEOVIM_HEADERS *.h)
|
||||
file(GLOB UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
|
||||
|
||||
|
|
|
@ -423,13 +423,16 @@ Object buffer_get_var(Buffer buffer, String name, Error *err)
|
|||
return dict_get_value(buf->b_vars, name, err);
|
||||
}
|
||||
|
||||
/// Sets a buffer-scoped (b:) variable. 'nil' value deletes the variable.
|
||||
/// Sets a buffer-scoped (b:) variable
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param name The variable name
|
||||
/// @param value The variable value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The old value
|
||||
/// @return The old value or nil if there was no previous value.
|
||||
///
|
||||
/// @warning It may return nil if there was no previous value
|
||||
/// or if previous value was `v:null`.
|
||||
Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
|
||||
{
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
|
@ -438,7 +441,27 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
|
|||
return (Object) OBJECT_INIT;
|
||||
}
|
||||
|
||||
return dict_set_value(buf->b_vars, name, value, err);
|
||||
return dict_set_value(buf->b_vars, name, value, false, err);
|
||||
}
|
||||
|
||||
/// Removes a buffer-scoped (b:) variable
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param name The variable name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The old value or nil if there was no previous value.
|
||||
///
|
||||
/// @warning It may return nil if there was no previous value
|
||||
/// or if previous value was `v:null`.
|
||||
Object buffer_del_var(Buffer buffer, String name, Error *err)
|
||||
{
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return (Object) OBJECT_INIT;
|
||||
}
|
||||
|
||||
return dict_set_value(buf->b_vars, name, NIL, true, err);
|
||||
}
|
||||
|
||||
/// Gets a buffer option value
|
||||
|
|
|
@ -99,4 +99,3 @@ struct key_value_pair {
|
|||
|
||||
|
||||
#endif // NVIM_API_PRIVATE_DEFS_H
|
||||
|
||||
|
|
|
@ -90,14 +90,17 @@ Object dict_get_value(dict_T *dict, String key, Error *err)
|
|||
}
|
||||
|
||||
/// Set a value in a dict. Objects are recursively expanded into their
|
||||
/// vimscript equivalents. Passing 'nil' as value deletes the key.
|
||||
/// vimscript equivalents.
|
||||
///
|
||||
/// @param dict The vimscript dict
|
||||
/// @param key The key
|
||||
/// @param value The new value
|
||||
/// @param del Delete key in place of setting it. Argument `value` is ignored in
|
||||
/// this case.
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the old value, if any
|
||||
Object dict_set_value(dict_T *dict, String key, Object value, Error *err)
|
||||
Object dict_set_value(dict_T *dict, String key, Object value, bool del,
|
||||
Error *err)
|
||||
{
|
||||
Object rv = OBJECT_INIT;
|
||||
|
||||
|
@ -118,7 +121,7 @@ Object dict_set_value(dict_T *dict, String key, Object value, Error *err)
|
|||
|
||||
dictitem_T *di = dict_find(dict, (uint8_t *)key.data, (int)key.size);
|
||||
|
||||
if (value.type == kObjectTypeNil) {
|
||||
if (del) {
|
||||
// Delete the key
|
||||
if (di == NULL) {
|
||||
// Doesn't exist, fail
|
||||
|
@ -397,13 +400,13 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
|||
|
||||
switch (obj.type) {
|
||||
case kObjectTypeNil:
|
||||
tv->v_type = VAR_NUMBER;
|
||||
tv->vval.v_number = 0;
|
||||
tv->v_type = VAR_SPECIAL;
|
||||
tv->vval.v_special = kSpecialVarNull;
|
||||
break;
|
||||
|
||||
case kObjectTypeBoolean:
|
||||
tv->v_type = VAR_NUMBER;
|
||||
tv->vval.v_number = obj.data.boolean;
|
||||
tv->v_type = VAR_SPECIAL;
|
||||
tv->vval.v_special = obj.data.boolean? kSpecialVarTrue: kSpecialVarFalse;
|
||||
break;
|
||||
|
||||
case kObjectTypeBuffer:
|
||||
|
@ -651,6 +654,21 @@ static Object vim_to_object_rec(typval_T *obj, PMap(ptr_t) *lookup)
|
|||
}
|
||||
|
||||
switch (obj->v_type) {
|
||||
case VAR_SPECIAL:
|
||||
switch (obj->vval.v_special) {
|
||||
case kSpecialVarTrue:
|
||||
case kSpecialVarFalse: {
|
||||
rv.type = kObjectTypeBoolean;
|
||||
rv.data.boolean = (obj->vval.v_special == kSpecialVarTrue);
|
||||
break;
|
||||
}
|
||||
case kSpecialVarNull: {
|
||||
rv.type = kObjectTypeNil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VAR_STRING:
|
||||
rv.type = kObjectTypeString;
|
||||
rv.data.string = cstr_to_string((char *) obj->vval.v_string);
|
||||
|
@ -730,6 +748,10 @@ static Object vim_to_object_rec(typval_T *obj, PMap(ptr_t) *lookup)
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VAR_UNKNOWN:
|
||||
case VAR_FUNC:
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
|
|
@ -54,13 +54,16 @@ Object tabpage_get_var(Tabpage tabpage, String name, Error *err)
|
|||
return dict_get_value(tab->tp_vars, name, err);
|
||||
}
|
||||
|
||||
/// Sets a tab-scoped (t:) variable. 'nil' value deletes the variable.
|
||||
/// Sets a tab-scoped (t:) variable
|
||||
///
|
||||
/// @param tabpage handle
|
||||
/// @param name The variable name
|
||||
/// @param value The variable value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The tab page handle
|
||||
/// @return The old value or nil if there was no previous value.
|
||||
///
|
||||
/// @warning It may return nil if there was no previous value
|
||||
/// or if previous value was `v:null`.
|
||||
Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
|
||||
{
|
||||
tabpage_T *tab = find_tab_by_handle(tabpage, err);
|
||||
|
@ -69,7 +72,27 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
|
|||
return (Object) OBJECT_INIT;
|
||||
}
|
||||
|
||||
return dict_set_value(tab->tp_vars, name, value, err);
|
||||
return dict_set_value(tab->tp_vars, name, value, false, err);
|
||||
}
|
||||
|
||||
/// Removes a tab-scoped (t:) variable
|
||||
///
|
||||
/// @param tabpage handle
|
||||
/// @param name The variable name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The old value or nil if there was no previous value.
|
||||
///
|
||||
/// @warning It may return nil if there was no previous value
|
||||
/// or if previous value was `v:null`.
|
||||
Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
|
||||
{
|
||||
tabpage_T *tab = find_tab_by_handle(tabpage, err);
|
||||
|
||||
if (!tab) {
|
||||
return (Object) OBJECT_INIT;
|
||||
}
|
||||
|
||||
return dict_set_value(tab->tp_vars, name, NIL, true, err);
|
||||
}
|
||||
|
||||
/// Gets the current window in a tab page
|
||||
|
|
|
@ -331,15 +331,31 @@ Object vim_get_var(String name, Error *err)
|
|||
return dict_get_value(&globvardict, name, err);
|
||||
}
|
||||
|
||||
/// Sets a global variable. Passing 'nil' as value deletes the variable.
|
||||
/// Sets a global variable
|
||||
///
|
||||
/// @param name The variable name
|
||||
/// @param value The variable value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the old value if any
|
||||
/// @return The old value or nil if there was no previous value.
|
||||
///
|
||||
/// @warning It may return nil if there was no previous value
|
||||
/// or if previous value was `v:null`.
|
||||
Object vim_set_var(String name, Object value, Error *err)
|
||||
{
|
||||
return dict_set_value(&globvardict, name, value, err);
|
||||
return dict_set_value(&globvardict, name, value, false, err);
|
||||
}
|
||||
|
||||
/// Removes a global variable
|
||||
///
|
||||
/// @param name The variable name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The old value or nil if there was no previous value.
|
||||
///
|
||||
/// @warning It may return nil if there was no previous value
|
||||
/// or if previous value was `v:null`.
|
||||
Object vim_del_var(String name, Error *err)
|
||||
{
|
||||
return dict_set_value(&globvardict, name, NIL, true, err);
|
||||
}
|
||||
|
||||
/// Gets a vim variable
|
||||
|
|
|
@ -197,13 +197,16 @@ Object window_get_var(Window window, String name, Error *err)
|
|||
return dict_get_value(win->w_vars, name, err);
|
||||
}
|
||||
|
||||
/// Sets a window-scoped (w:) variable. 'nil' value deletes the variable.
|
||||
/// Sets a window-scoped (w:) variable
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param name The variable name
|
||||
/// @param value The variable value
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The old value
|
||||
/// @return The old value or nil if there was no previous value.
|
||||
///
|
||||
/// @warning It may return nil if there was no previous value
|
||||
/// or if previous value was `v:null`.
|
||||
Object window_set_var(Window window, String name, Object value, Error *err)
|
||||
{
|
||||
win_T *win = find_window_by_handle(window, err);
|
||||
|
@ -212,7 +215,27 @@ Object window_set_var(Window window, String name, Object value, Error *err)
|
|||
return (Object) OBJECT_INIT;
|
||||
}
|
||||
|
||||
return dict_set_value(win->w_vars, name, value, err);
|
||||
return dict_set_value(win->w_vars, name, value, false, err);
|
||||
}
|
||||
|
||||
/// Removes a window-scoped (w:) variable
|
||||
///
|
||||
/// @param window The window handle
|
||||
/// @param name The variable name
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return The old value or nil if there was no previous value.
|
||||
///
|
||||
/// @warning It may return nil if there was no previous value
|
||||
/// or if previous value was `v:null`.
|
||||
Object window_del_var(Window window, String name, Error *err)
|
||||
{
|
||||
win_T *win = find_window_by_handle(window, err);
|
||||
|
||||
if (!win) {
|
||||
return (Object) OBJECT_INIT;
|
||||
}
|
||||
|
||||
return dict_set_value(win->w_vars, name, NIL, true, err);
|
||||
}
|
||||
|
||||
/// Gets a window option value
|
||||
|
|
|
@ -8,17 +8,32 @@
|
|||
// defined(__has_feature) && __has_feature(...). Therefore we define Clang's
|
||||
// __has_feature and __has_extension macro's before referring to them.
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_extension
|
||||
#define __has_extension __has_feature
|
||||
# define __has_extension __has_feature
|
||||
#endif
|
||||
|
||||
/// STATIC_ASSERT(condition, message) - assert at compile time if !cond
|
||||
/// @def STATIC_ASSERT
|
||||
/// @brief Assert at compile time if condition is not satisfied.
|
||||
///
|
||||
/// example:
|
||||
/// STATIC_ASSERT(sizeof(void *) == 8, "need 64-bits mode");
|
||||
/// Should be put on its own line, followed by a semicolon.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// STATIC_ASSERT(sizeof(void *) == 8, "Expected 64-bit mode");
|
||||
///
|
||||
/// @param[in] condition Condition to check, should be an integer constant
|
||||
/// expression.
|
||||
/// @param[in] message Message which will be given if check fails.
|
||||
|
||||
/// @def STATIC_ASSERT_EXPR
|
||||
/// @brief Like #STATIC_ASSERT, but can be used where expressions are used.
|
||||
///
|
||||
/// STATIC_ASSERT_EXPR may be put in brace initializer lists. Error message
|
||||
/// given in this case is not very nice with the current implementation though
|
||||
/// and `message` argument is ignored.
|
||||
|
||||
// define STATIC_ASSERT as C11's _Static_assert whenever either C11 mode is
|
||||
// detected or the compiler is known to support it. Note that Clang in C99
|
||||
|
@ -29,50 +44,74 @@
|
|||
// clearer messages we get from _Static_assert, we suppress the warnings
|
||||
// temporarily.
|
||||
|
||||
#define STATIC_ASSERT_PRAGMA_START
|
||||
#define STATIC_ASSERT_PRAGMA_END
|
||||
#define STATIC_ASSERT(...) \
|
||||
do { \
|
||||
STATIC_ASSERT_PRAGMA_START \
|
||||
STATIC_ASSERT_STATEMENT(__VA_ARGS__); \
|
||||
STATIC_ASSERT_PRAGMA_END \
|
||||
} while (0)
|
||||
|
||||
// the easiest case, when the mode is C11 (generic compiler) or Clang
|
||||
// advertises explicit support for c_static_assert, meaning it won't warn.
|
||||
#if __STDC_VERSION__ >= 201112L || __has_feature(c_static_assert)
|
||||
#define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
|
||||
# define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg)
|
||||
// if we're dealing with gcc >= 4.6 in C99 mode, we can still use
|
||||
// _Static_assert but we need to suppress warnings, this is pretty ugly.
|
||||
#elif (!defined(__clang__) && !defined(__INTEL_COMPILER)) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
||||
#define STATIC_ASSERT(cond, msg) \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-pedantic\"") \
|
||||
_Static_assert(cond, msg); \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
|
||||
# define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg)
|
||||
|
||||
# undef STATIC_ASSERT_PRAGMA_START
|
||||
# define STATIC_ASSERT_PRAGMA_START \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-pedantic\"") \
|
||||
|
||||
# undef STATIC_ASSERT_PRAGMA_END
|
||||
# define STATIC_ASSERT_PRAGMA_END \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
|
||||
// the same goes for clang in C99 mode, but we suppress a different warning
|
||||
#elif defined(__clang__) && __has_extension(c_static_assert)
|
||||
#define STATIC_ASSERT(cond, msg) \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wc11-extensions\"") \
|
||||
_Static_assert(cond, msg); \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
|
||||
# define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg)
|
||||
|
||||
# undef STATIC_ASSERT_PRAGMA_START
|
||||
# define STATIC_ASSERT_PRAGMA_START \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wc11-extensions\"") \
|
||||
|
||||
# undef STATIC_ASSERT_PRAGMA_END
|
||||
# define STATIC_ASSERT_PRAGMA_END \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
|
||||
// TODO(aktau): verify that this works, don't have MSVC on hand.
|
||||
#elif _MSC_VER >= 1600
|
||||
#define STATIC_ASSERT(cond, msg) static_assert(cond, msg)
|
||||
|
||||
# define STATIC_ASSERT_STATEMENT(cond, msg) static_assert(cond, msg)
|
||||
|
||||
// fallback for compilers that don't support _Static_assert or static_assert
|
||||
// not as pretty but gets the job done. Credit goes to Pádraig Brady and
|
||||
// contributors.
|
||||
#else
|
||||
#define ASSERT_CONCAT_(a, b) a##b
|
||||
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
|
||||
// These can't be used after statements in c89.
|
||||
#ifdef __COUNTER__
|
||||
#define STATIC_ASSERT(e,m) \
|
||||
{ enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }; }
|
||||
#else
|
||||
// This can't be used twice on the same line so ensure if using in headers
|
||||
// that the headers are not included twice (by wrapping in #ifndef...#endif)
|
||||
// Note it doesn't cause an issue when used on same line of separate modules
|
||||
// compiled with gcc -combine -fwhole-program.
|
||||
#define STATIC_ASSERT(e,m) \
|
||||
{ enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }; }
|
||||
#endif
|
||||
# define STATIC_ASSERT_STATEMENT STATIC_ASSERT_EXPR
|
||||
#endif
|
||||
|
||||
#define ASSERT_CONCAT_(a, b) a##b
|
||||
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
|
||||
// These can't be used after statements in c89.
|
||||
#ifdef __COUNTER__
|
||||
# define STATIC_ASSERT_EXPR(e, m) \
|
||||
((enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }) 0)
|
||||
#else
|
||||
// This can't be used twice on the same line so ensure if using in headers
|
||||
// that the headers are not included twice (by wrapping in #ifndef...#endif)
|
||||
// Note it doesn't cause an issue when used on same line of separate modules
|
||||
// compiled with gcc -combine -fwhole-program.
|
||||
# define STATIC_ASSERT_EXPR(e, m) \
|
||||
((enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }) 0)
|
||||
#endif
|
||||
|
||||
#endif // NVIM_ASSERT_H
|
||||
|
|
|
@ -658,9 +658,9 @@ void ex_diffupdate(exarg_T *eap)
|
|||
}
|
||||
|
||||
// We need three temp file names.
|
||||
char_u *tmp_orig = vim_tempname();
|
||||
char_u *tmp_new = vim_tempname();
|
||||
char_u *tmp_diff = vim_tempname();
|
||||
char *tmp_orig = (char *) vim_tempname();
|
||||
char *tmp_new = (char *) vim_tempname();
|
||||
char *tmp_diff = (char *) vim_tempname();
|
||||
|
||||
if ((tmp_orig == NULL) || (tmp_new == NULL) || (tmp_diff == NULL)) {
|
||||
goto theend;
|
||||
|
@ -670,11 +670,11 @@ void ex_diffupdate(exarg_T *eap)
|
|||
// are no differences. Can't use the return value, it's non-zero when
|
||||
// there are differences.
|
||||
// May try twice, first with "-a" and then without.
|
||||
int io_error = FALSE;
|
||||
int ok = FALSE;
|
||||
int io_error = false;
|
||||
bool ok = false;
|
||||
for (;;) {
|
||||
ok = FALSE;
|
||||
FILE *fd = mch_fopen((char *)tmp_orig, "w");
|
||||
ok = false;
|
||||
FILE *fd = mch_fopen(tmp_orig, "w");
|
||||
|
||||
if (fd == NULL) {
|
||||
io_error = TRUE;
|
||||
|
@ -683,7 +683,7 @@ void ex_diffupdate(exarg_T *eap)
|
|||
io_error = TRUE;
|
||||
}
|
||||
fclose(fd);
|
||||
fd = mch_fopen((char *)tmp_new, "w");
|
||||
fd = mch_fopen(tmp_new, "w");
|
||||
|
||||
if (fd == NULL) {
|
||||
io_error = TRUE;
|
||||
|
@ -693,7 +693,7 @@ void ex_diffupdate(exarg_T *eap)
|
|||
}
|
||||
fclose(fd);
|
||||
diff_file(tmp_orig, tmp_new, tmp_diff);
|
||||
fd = mch_fopen((char *)tmp_diff, "r");
|
||||
fd = mch_fopen(tmp_diff, "r");
|
||||
|
||||
if (fd == NULL) {
|
||||
io_error = TRUE;
|
||||
|
@ -712,10 +712,10 @@ void ex_diffupdate(exarg_T *eap)
|
|||
}
|
||||
fclose(fd);
|
||||
}
|
||||
os_remove((char *)tmp_diff);
|
||||
os_remove((char *)tmp_new);
|
||||
os_remove(tmp_diff);
|
||||
os_remove(tmp_new);
|
||||
}
|
||||
os_remove((char *)tmp_orig);
|
||||
os_remove(tmp_orig);
|
||||
}
|
||||
|
||||
// When using 'diffexpr' break here.
|
||||
|
@ -756,7 +756,7 @@ void ex_diffupdate(exarg_T *eap)
|
|||
|
||||
// Write the first buffer to a tempfile.
|
||||
buf_T *buf = curtab->tp_diffbuf[idx_orig];
|
||||
if (diff_write(buf, tmp_orig) == FAIL) {
|
||||
if (diff_write(buf, (char_u *) tmp_orig) == FAIL) {
|
||||
goto theend;
|
||||
}
|
||||
|
||||
|
@ -767,17 +767,17 @@ void ex_diffupdate(exarg_T *eap)
|
|||
continue; // skip buffer that isn't loaded
|
||||
}
|
||||
|
||||
if (diff_write(buf, tmp_new) == FAIL) {
|
||||
if (diff_write(buf, (char_u *) tmp_new) == FAIL) {
|
||||
continue;
|
||||
}
|
||||
diff_file(tmp_orig, tmp_new, tmp_diff);
|
||||
|
||||
// Read the diff output and add each entry to the diff list.
|
||||
diff_read(idx_orig, idx_new, tmp_diff);
|
||||
os_remove((char *)tmp_diff);
|
||||
os_remove((char *)tmp_new);
|
||||
diff_read(idx_orig, idx_new, (char_u *) tmp_diff);
|
||||
os_remove(tmp_diff);
|
||||
os_remove(tmp_new);
|
||||
}
|
||||
os_remove((char *)tmp_orig);
|
||||
os_remove(tmp_orig);
|
||||
|
||||
// force updating cursor position on screen
|
||||
curwin->w_valid_cursor.lnum = 0;
|
||||
|
@ -795,15 +795,16 @@ theend:
|
|||
/// @param tmp_orig
|
||||
/// @param tmp_new
|
||||
/// @param tmp_diff
|
||||
static void diff_file(char_u *tmp_orig, char_u *tmp_new, char_u *tmp_diff)
|
||||
static void diff_file(const char *const tmp_orig, const char *const tmp_new,
|
||||
const char *const tmp_diff)
|
||||
{
|
||||
if (*p_dex != NUL) {
|
||||
// Use 'diffexpr' to generate the diff file.
|
||||
eval_diff(tmp_orig, tmp_new, tmp_diff);
|
||||
} else {
|
||||
size_t len = STRLEN(tmp_orig) + STRLEN(tmp_new) + STRLEN(tmp_diff)
|
||||
+ STRLEN(p_srr) + 27;
|
||||
char_u *cmd = xmalloc(len);
|
||||
const size_t len = (strlen(tmp_orig) + strlen(tmp_new) + strlen(tmp_diff)
|
||||
+ STRLEN(p_srr) + 27);
|
||||
char *const cmd = xmalloc(len);
|
||||
|
||||
/* We don't want $DIFF_OPTIONS to get in the way. */
|
||||
if (os_getenv("DIFF_OPTIONS")) {
|
||||
|
@ -813,19 +814,17 @@ static void diff_file(char_u *tmp_orig, char_u *tmp_new, char_u *tmp_diff)
|
|||
/* Build the diff command and execute it. Always use -a, binary
|
||||
* differences are of no use. Ignore errors, diff returns
|
||||
* non-zero when differences have been found. */
|
||||
vim_snprintf((char *)cmd, len, "diff %s%s%s%s%s %s",
|
||||
diff_a_works == FALSE ? "" : "-a ",
|
||||
vim_snprintf(cmd, len, "diff %s%s%s%s%s %s",
|
||||
diff_a_works ? "-a " : "",
|
||||
"",
|
||||
(diff_flags & DIFF_IWHITE) ? "-b " : "",
|
||||
(diff_flags & DIFF_ICASE) ? "-i " : "",
|
||||
tmp_orig, tmp_new);
|
||||
append_redir(cmd, len, p_srr, tmp_diff);
|
||||
append_redir(cmd, len, (char *) p_srr, tmp_diff);
|
||||
block_autocmds(); // Avoid ShellCmdPost stuff
|
||||
(void)call_shell(
|
||||
cmd,
|
||||
kShellOptFilter | kShellOptSilent | kShellOptDoOut,
|
||||
NULL
|
||||
);
|
||||
(void)call_shell((char_u *) cmd,
|
||||
kShellOptFilter | kShellOptSilent | kShellOptDoOut,
|
||||
NULL);
|
||||
unblock_autocmds();
|
||||
xfree(cmd);
|
||||
}
|
||||
|
@ -902,9 +901,11 @@ void ex_diffpatch(exarg_T *eap)
|
|||
if (*p_pex != NUL) {
|
||||
// Use 'patchexpr' to generate the new file.
|
||||
#ifdef UNIX
|
||||
eval_patch(tmp_orig, fullname != NULL ? fullname : eap->arg, tmp_new);
|
||||
eval_patch((char *) tmp_orig,
|
||||
(char *) (fullname != NULL ? fullname : eap->arg),
|
||||
(char *) tmp_new);
|
||||
#else
|
||||
eval_patch(tmp_orig, eap->arg, tmp_new);
|
||||
eval_patch((char *) tmp_orig, (char *) eap->arg, (char *) tmp_new);
|
||||
#endif // ifdef UNIX
|
||||
} else {
|
||||
// Build the patch command and execute it. Ignore errors. Switch to
|
||||
|
|
|
@ -199,7 +199,7 @@ typedef struct insert_state {
|
|||
int did_restart_edit; // remember if insert mode was restarted
|
||||
// after a ctrl+o
|
||||
bool nomove;
|
||||
uint8_t *ptr;
|
||||
char_u *ptr;
|
||||
} InsertState;
|
||||
|
||||
|
||||
|
@ -270,8 +270,8 @@ static void insert_enter(InsertState *s)
|
|||
s->ptr = (char_u *)"i";
|
||||
}
|
||||
|
||||
set_vim_var_string(VV_INSERTMODE, s->ptr, 1);
|
||||
set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */
|
||||
set_vim_var_string(VV_INSERTMODE, (char *) s->ptr, 1);
|
||||
set_vim_var_string(VV_CHAR, NULL, -1);
|
||||
apply_autocmds(EVENT_INSERTENTER, NULL, NULL, false, curbuf);
|
||||
|
||||
// Make sure the cursor didn't move. Do call check_cursor_col() in
|
||||
|
@ -7239,15 +7239,15 @@ static void ins_insert(int replaceState)
|
|||
return;
|
||||
}
|
||||
|
||||
set_vim_var_string(VV_INSERTMODE,
|
||||
(char_u *)((State & REPLACE_FLAG) ? "i" :
|
||||
replaceState == VREPLACE ? "v" :
|
||||
"r"), 1);
|
||||
apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, FALSE, curbuf);
|
||||
if (State & REPLACE_FLAG)
|
||||
set_vim_var_string(VV_INSERTMODE, ((State & REPLACE_FLAG) ? "i" :
|
||||
replaceState == VREPLACE ? "v" :
|
||||
"r"), 1);
|
||||
apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, false, curbuf);
|
||||
if (State & REPLACE_FLAG) {
|
||||
State = INSERT | (State & LANGMAP);
|
||||
else
|
||||
} else {
|
||||
State = replaceState | (State & LANGMAP);
|
||||
}
|
||||
AppendCharToRedobuff(K_INS);
|
||||
showmode();
|
||||
ui_cursor_shape(); /* may show different cursor shape */
|
||||
|
@ -8480,22 +8480,22 @@ static colnr_T get_nolist_virtcol(void)
|
|||
*/
|
||||
static char_u *do_insert_char_pre(int c)
|
||||
{
|
||||
char_u buf[MB_MAXBYTES + 1];
|
||||
char buf[MB_MAXBYTES + 1];
|
||||
|
||||
// Return quickly when there is nothing to do.
|
||||
if (!has_event(EVENT_INSERTCHARPRE)) {
|
||||
return NULL;
|
||||
}
|
||||
if (has_mbyte) {
|
||||
buf[(*mb_char2bytes)(c, buf)] = NUL;
|
||||
buf[(*mb_char2bytes)(c, (char_u *) buf)] = NUL;
|
||||
} else {
|
||||
buf[0] = c;
|
||||
buf[1] = NUL;
|
||||
}
|
||||
|
||||
/* Lock the text to avoid weird things from happening. */
|
||||
++textlock;
|
||||
set_vim_var_string(VV_CHAR, buf, -1); /* set v:char */
|
||||
// Lock the text to avoid weird things from happening.
|
||||
textlock++;
|
||||
set_vim_var_string(VV_CHAR, buf, -1);
|
||||
|
||||
char_u *res = NULL;
|
||||
if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf)) {
|
||||
|
@ -8506,8 +8506,8 @@ static char_u *do_insert_char_pre(int c)
|
|||
res = vim_strsave(get_vim_var_str(VV_CHAR));
|
||||
}
|
||||
|
||||
set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */
|
||||
--textlock;
|
||||
set_vim_var_string(VV_CHAR, NULL, -1);
|
||||
textlock--;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
1990
src/nvim/eval.c
1990
src/nvim/eval.c
File diff suppressed because it is too large
Load Diff
|
@ -1,12 +1,17 @@
|
|||
#ifndef NVIM_EVAL_H
|
||||
#define NVIM_EVAL_H
|
||||
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/profile.h"
|
||||
#include "nvim/hashtab.h" // For hashtab_T
|
||||
#include "nvim/garray.h" // For garray_T
|
||||
#include "nvim/buffer_defs.h" // For scid_T
|
||||
#include "nvim/ex_cmds_defs.h" // For exarg_T
|
||||
|
||||
#define COPYID_INC 2
|
||||
#define COPYID_MASK (~0x1)
|
||||
|
||||
// All user-defined functions are found in this hashtable.
|
||||
EXTERN hashtab_T func_hashtab;
|
||||
extern hashtab_T func_hashtab;
|
||||
|
||||
// Structure to hold info for a user function.
|
||||
typedef struct ufunc ufunc_T;
|
||||
|
@ -46,8 +51,8 @@ EXTERN ufunc_T dumuf;
|
|||
#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
|
||||
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
|
||||
|
||||
/* Defines for Vim variables. These must match vimvars[] in eval.c! */
|
||||
enum {
|
||||
/// Defines for Vim variables
|
||||
typedef enum {
|
||||
VV_COUNT,
|
||||
VV_COUNT1,
|
||||
VV_PREVCOUNT,
|
||||
|
@ -114,15 +119,35 @@ enum {
|
|||
VV_ERRORS,
|
||||
VV_MSGPACK_TYPES,
|
||||
VV_EVENT,
|
||||
VV_LEN, // number of v: vars
|
||||
};
|
||||
VV_FALSE,
|
||||
VV_TRUE,
|
||||
VV_NULL,
|
||||
VV__NULL_LIST, // List with NULL value. For test purposes only.
|
||||
VV__NULL_DICT, // Dictionary with NULL value. For test purposes only.
|
||||
} VimVarIndex;
|
||||
|
||||
/// All recognized msgpack types
|
||||
typedef enum {
|
||||
kMPNil,
|
||||
kMPBoolean,
|
||||
kMPInteger,
|
||||
kMPFloat,
|
||||
kMPString,
|
||||
kMPBinary,
|
||||
kMPArray,
|
||||
kMPMap,
|
||||
kMPExt,
|
||||
#define LAST_MSGPACK_TYPE kMPExt
|
||||
} MessagePackType;
|
||||
|
||||
/// Array mapping values from MessagePackType to corresponding list pointers
|
||||
extern const list_T *eval_msgpack_type_lists[LAST_MSGPACK_TYPE + 1];
|
||||
|
||||
#undef LAST_MSGPACK_TYPE
|
||||
|
||||
/// Maximum number of function arguments
|
||||
#define MAX_FUNC_ARGS 20
|
||||
|
||||
int vim_to_msgpack(msgpack_packer *const, typval_T *const,
|
||||
const char *const objname);
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval.h.generated.h"
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,13 @@
|
|||
#ifndef NVIM_EVAL_DECODE_H
|
||||
#define NVIM_EVAL_DECODE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/eval_defs.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/decode.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_DECODE_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,75 @@
|
|||
#ifndef NVIM_EVAL_ENCODE_H
|
||||
#define NVIM_EVAL_ENCODE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/vim.h" // For STRLEN
|
||||
|
||||
/// Convert VimL value to msgpack string
|
||||
///
|
||||
/// @param[out] packer Packer to save results in.
|
||||
/// @param[in] tv Dumped value.
|
||||
/// @param[in] objname Object name, used for error message.
|
||||
///
|
||||
/// @return OK in case of success, FAIL otherwise.
|
||||
int encode_vim_to_msgpack(msgpack_packer *const packer,
|
||||
typval_T *const tv,
|
||||
const char *const objname);
|
||||
|
||||
/// Convert VimL value to :echo output
|
||||
///
|
||||
/// @param[out] packer Packer to save results in.
|
||||
/// @param[in] tv Dumped value.
|
||||
/// @param[in] objname Object name, used for error message.
|
||||
///
|
||||
/// @return OK in case of success, FAIL otherwise.
|
||||
int encode_vim_to_echo(garray_T *const packer,
|
||||
typval_T *const tv,
|
||||
const char *const objname);
|
||||
|
||||
/// Structure defining state for read_from_list()
|
||||
typedef struct {
|
||||
const listitem_T *li; ///< Item currently read.
|
||||
size_t offset; ///< Byte offset inside the read item.
|
||||
size_t li_length; ///< Length of the string inside the read item.
|
||||
} ListReaderState;
|
||||
|
||||
/// Initialize ListReaderState structure
|
||||
static inline ListReaderState encode_init_lrstate(const list_T *const list)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
return (ListReaderState) {
|
||||
.li = list->lv_first,
|
||||
.offset = 0,
|
||||
.li_length = (list->lv_first->li_tv.vval.v_string == NULL
|
||||
? 0
|
||||
: STRLEN(list->lv_first->li_tv.vval.v_string)),
|
||||
};
|
||||
}
|
||||
|
||||
/// Array mapping values from SpecialVarValue enum to names
|
||||
extern const char *const encode_special_var_names[];
|
||||
|
||||
/// First codepoint in high surrogates block
|
||||
#define SURROGATE_HI_START 0xD800
|
||||
|
||||
/// Last codepoint in high surrogates block
|
||||
#define SURROGATE_HI_END 0xDBFF
|
||||
|
||||
/// First codepoint in low surrogates block
|
||||
#define SURROGATE_LO_START 0xDC00
|
||||
|
||||
/// Last codepoint in low surrogates block
|
||||
#define SURROGATE_LO_END 0xDFFF
|
||||
|
||||
/// First character that needs to be encoded as surrogate pair
|
||||
#define SURROGATE_FIRST_CHAR 0x10000
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/encode.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_ENCODE_H
|
|
@ -16,39 +16,52 @@ typedef double float_T;
|
|||
typedef struct listvar_S list_T;
|
||||
typedef struct dictvar_S dict_T;
|
||||
|
||||
/*
|
||||
* Structure to hold an internal variable without a name.
|
||||
*/
|
||||
typedef struct {
|
||||
char v_type; /* see below: VAR_NUMBER, VAR_STRING, etc. */
|
||||
char v_lock; /* see below: VAR_LOCKED, VAR_FIXED */
|
||||
union {
|
||||
varnumber_T v_number; /* number value */
|
||||
float_T v_float; /* floating number value */
|
||||
char_u *v_string; /* string value (can be NULL!) */
|
||||
list_T *v_list; /* list value (can be NULL!) */
|
||||
dict_T *v_dict; /* dict value (can be NULL!) */
|
||||
} vval;
|
||||
} typval_T;
|
||||
/// Special variable values
|
||||
typedef enum {
|
||||
kSpecialVarFalse, ///< v:false
|
||||
kSpecialVarTrue, ///< v:true
|
||||
kSpecialVarNull, ///< v:null
|
||||
} SpecialVarValue;
|
||||
|
||||
/* Values for "v_type". */
|
||||
#define VAR_UNKNOWN 0
|
||||
#define VAR_NUMBER 1 /* "v_number" is used */
|
||||
#define VAR_STRING 2 /* "v_string" is used */
|
||||
#define VAR_FUNC 3 /* "v_string" is function name */
|
||||
#define VAR_LIST 4 /* "v_list" is used */
|
||||
#define VAR_DICT 5 /* "v_dict" is used */
|
||||
#define VAR_FLOAT 6 /* "v_float" is used */
|
||||
/// Variable lock status for typval_T.v_lock
|
||||
typedef enum {
|
||||
VAR_UNLOCKED = 0, ///< Not locked.
|
||||
VAR_LOCKED, ///< User lock, can be unlocked.
|
||||
VAR_FIXED, ///< Locked forever.
|
||||
} VarLockStatus;
|
||||
|
||||
/// VimL variable types, for use in typval_T.v_type
|
||||
typedef enum {
|
||||
VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
|
||||
VAR_NUMBER, ///< Number, .v_number is used.
|
||||
VAR_STRING, ///< String, .v_string is used.
|
||||
VAR_FUNC, ///< Function referene, .v_string is used for function name.
|
||||
VAR_LIST, ///< List, .v_list is used.
|
||||
VAR_DICT, ///< Dictionary, .v_dict is used.
|
||||
VAR_FLOAT, ///< Floating-point value, .v_float is used.
|
||||
VAR_SPECIAL, ///< Special value (true, false, null), .v_special
|
||||
///< is used.
|
||||
} VarType;
|
||||
|
||||
/// Structure that holds an internal variable value
|
||||
typedef struct {
|
||||
VarType v_type; ///< Variable type.
|
||||
VarLockStatus v_lock; ///< Variable lock status.
|
||||
union {
|
||||
varnumber_T v_number; ///< Number, for VAR_NUMBER.
|
||||
SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
|
||||
float_T v_float; ///< Floating-point number, for VAR_FLOAT.
|
||||
char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
|
||||
list_T *v_list; ///< List for VAR_LIST, can be NULL.
|
||||
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
|
||||
} vval; ///< Actual value.
|
||||
} typval_T;
|
||||
|
||||
/* Values for "dv_scope". */
|
||||
#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */
|
||||
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
|
||||
allowed to mask existing functions */
|
||||
|
||||
/* Values for "v_lock". */
|
||||
#define VAR_LOCKED 1 /* locked with lock(), can use unlock() */
|
||||
#define VAR_FIXED 2 /* locked forever */
|
||||
|
||||
/*
|
||||
* Structure to hold an item of a list: an internal variable without a name.
|
||||
*/
|
||||
|
@ -107,19 +120,18 @@ typedef struct dictitem_S dictitem_T;
|
|||
#define DI_FLAGS_LOCK 8 // "di_flags" value: locked variable
|
||||
#define DI_FLAGS_ALLOC 16 // "di_flags" value: separately allocated
|
||||
|
||||
/*
|
||||
* Structure to hold info about a Dictionary.
|
||||
*/
|
||||
/// Structure representing a Dictionary
|
||||
struct dictvar_S {
|
||||
char dv_lock; /* zero, VAR_LOCKED, VAR_FIXED */
|
||||
char dv_scope; /* zero, VAR_SCOPE, VAR_DEF_SCOPE */
|
||||
int dv_refcount; /* reference count */
|
||||
int dv_copyID; /* ID used by deepcopy() */
|
||||
hashtab_T dv_hashtab; /* hashtab that refers to the items */
|
||||
dict_T *dv_copydict; /* copied dict used by deepcopy() */
|
||||
dict_T *dv_used_next; /* next dict in used dicts list */
|
||||
dict_T *dv_used_prev; /* previous dict in used dicts list */
|
||||
QUEUE watchers; // dictionary key watchers set by user code
|
||||
VarLockStatus dv_lock; ///< Whole dictionary lock status.
|
||||
char dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
|
||||
///< dictionary represents a scope (i.e. g:, l: …).
|
||||
int dv_refcount; ///< Reference count.
|
||||
int dv_copyID; ///< ID used when recursivery traversing a value.
|
||||
hashtab_T dv_hashtab; ///< Hashtab containing all items.
|
||||
dict_T *dv_copydict; ///< Copied dict used by deepcopy().
|
||||
dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
|
||||
dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
|
||||
QUEUE watchers; ///< Dictionary key watchers set by user code.
|
||||
};
|
||||
|
||||
// structure used for explicit stack while garbage collecting hash tables
|
||||
|
|
|
@ -1326,15 +1326,17 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
|
|||
#endif
|
||||
|
||||
size_t len = STRLEN(cmd) + 1; // At least enough space for cmd + NULL.
|
||||
|
||||
|
||||
len += is_fish_shell ? sizeof("begin; ""; end") - 1
|
||||
: sizeof("("")") - 1;
|
||||
|
||||
if (itmp != NULL)
|
||||
if (itmp != NULL) {
|
||||
len += STRLEN(itmp) + sizeof(" { "" < "" } ") - 1;
|
||||
if (otmp != NULL)
|
||||
}
|
||||
if (otmp != NULL) {
|
||||
len += STRLEN(otmp) + STRLEN(p_srr) + 2; // two extra spaces (" "),
|
||||
char_u *buf = xmalloc(len);
|
||||
}
|
||||
char *const buf = xmalloc(len);
|
||||
|
||||
#if defined(UNIX)
|
||||
// Put delimiters around the command (for concatenated commands) when
|
||||
|
@ -1342,19 +1344,19 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
|
|||
if (itmp != NULL || otmp != NULL) {
|
||||
char *fmt = is_fish_shell ? "begin; %s; end"
|
||||
: "(%s)";
|
||||
vim_snprintf((char *)buf, len, fmt, (char *)cmd);
|
||||
vim_snprintf(buf, len, fmt, (char *)cmd);
|
||||
} else {
|
||||
STRCPY(buf, cmd);
|
||||
strncpy(buf, (char *) cmd, len);
|
||||
}
|
||||
|
||||
if (itmp != NULL) {
|
||||
STRCAT(buf, " < ");
|
||||
STRCAT(buf, itmp);
|
||||
strncat(buf, " < ", len);
|
||||
strncat(buf, (char *) itmp, len);
|
||||
}
|
||||
#else
|
||||
// For shells that don't understand braces around commands, at least allow
|
||||
// the use of commands in a pipe.
|
||||
STRCPY(buf, cmd);
|
||||
strncpy(buf, cmd, len);
|
||||
if (itmp != NULL) {
|
||||
char_u *p;
|
||||
|
||||
|
@ -1362,55 +1364,56 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
|
|||
// Don't do this when 'shellquote' is not empty, otherwise the
|
||||
// redirection would be inside the quotes.
|
||||
if (*p_shq == NUL) {
|
||||
p = vim_strchr(buf, '|');
|
||||
if (p != NULL)
|
||||
*p = NUL;
|
||||
}
|
||||
STRCAT(buf, " < ");
|
||||
STRCAT(buf, itmp);
|
||||
if (*p_shq == NUL) {
|
||||
p = vim_strchr(cmd, '|');
|
||||
p = strchr(buf, '|');
|
||||
if (p != NULL) {
|
||||
STRCAT(buf, " "); // Insert a space before the '|' for DOS
|
||||
STRCAT(buf, p);
|
||||
*p = NUL;
|
||||
}
|
||||
}
|
||||
strncat(buf, " < ", len);
|
||||
strncat(buf, (char *) itmp, len);
|
||||
if (*p_shq == NUL) {
|
||||
p = strchr(cmd, '|');
|
||||
if (p != NULL) {
|
||||
strncat(buf, " ", len); // Insert a space before the '|' for DOS
|
||||
strncat(buf, p, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (otmp != NULL) {
|
||||
append_redir(buf, len, p_srr, otmp);
|
||||
append_redir(buf, len, (char *) p_srr, (char *) otmp);
|
||||
}
|
||||
return buf;
|
||||
return (char_u *) buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append output redirection for file "fname" to the end of string buffer
|
||||
* "buf[buflen]"
|
||||
* Works with the 'shellredir' and 'shellpipe' options.
|
||||
* The caller should make sure that there is enough room:
|
||||
* STRLEN(opt) + STRLEN(fname) + 3
|
||||
*/
|
||||
void append_redir(char_u *buf, size_t buflen, char_u *opt, char_u *fname)
|
||||
/// Append output redirection for the given file to the end of the buffer
|
||||
///
|
||||
/// @param[out] buf Buffer to append to.
|
||||
/// @param[in] buflen Buffer length.
|
||||
/// @param[in] opt Separator or format string to append: will append
|
||||
/// `printf(' ' . opt, fname)` if `%s` is found in `opt` or
|
||||
/// a space, opt, a space and then fname if `%s` is not found
|
||||
/// there.
|
||||
/// @param[in] fname File name to append.
|
||||
void append_redir(char *const buf, const size_t buflen,
|
||||
const char *const opt, const char *const fname)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *end;
|
||||
|
||||
end = buf + STRLEN(buf);
|
||||
/* find "%s" */
|
||||
for (p = opt; (p = vim_strchr(p, '%')) != NULL; ++p) {
|
||||
if (p[1] == 's') /* found %s */
|
||||
char *const end = buf + strlen(buf);
|
||||
// find "%s"
|
||||
const char *p = opt;
|
||||
for (; (p = strchr(p, '%')) != NULL; p++) {
|
||||
if (p[1] == 's') { // found %s
|
||||
break;
|
||||
if (p[1] == '%') /* skip %% */
|
||||
++p;
|
||||
} else if (p[1] == '%') { // skip %%
|
||||
p++;
|
||||
}
|
||||
}
|
||||
if (p != NULL) {
|
||||
*end = ' '; /* not really needed? Not with sh, ksh or bash */
|
||||
vim_snprintf((char *)end + 1, (size_t)(buflen - (end + 1 - buf)),
|
||||
(char *)opt, (char *)fname);
|
||||
} else
|
||||
vim_snprintf((char *)end, (size_t)(buflen - (end - buf)),
|
||||
" %s %s",
|
||||
(char *)opt, (char *)fname);
|
||||
*end = ' '; // not really needed? Not with sh, ksh or bash
|
||||
vim_snprintf(end + 1, (size_t) (buflen - (end + 1 - buf)), opt, fname);
|
||||
} else {
|
||||
vim_snprintf(end, (size_t) (buflen - (end - buf)), " %s %s", opt, fname);
|
||||
}
|
||||
}
|
||||
|
||||
void print_line_no_prefix(linenr_T lnum, int use_number, int list)
|
||||
|
@ -2093,15 +2096,13 @@ do_ecmd (
|
|||
|
||||
if ((command != NULL || newlnum > (linenr_T)0)
|
||||
&& *get_vim_var_str(VV_SWAPCOMMAND) == NUL) {
|
||||
char_u *p;
|
||||
|
||||
/* Set v:swapcommand for the SwapExists autocommands. */
|
||||
size_t len = (command != NULL) ? STRLEN(command) + 3 : 30;
|
||||
p = xmalloc(len);
|
||||
// Set v:swapcommand for the SwapExists autocommands.
|
||||
const size_t len = (command != NULL) ? STRLEN(command) + 3 : 30;
|
||||
char *const p = xmalloc(len);
|
||||
if (command != NULL) {
|
||||
vim_snprintf((char *)p, len, ":%s\r", command);
|
||||
vim_snprintf(p, len, ":%s\r", command);
|
||||
} else {
|
||||
vim_snprintf((char *)p, len, "%" PRId64 "G", (int64_t)newlnum);
|
||||
vim_snprintf(p, len, "%" PRId64 "G", (int64_t)newlnum);
|
||||
}
|
||||
set_vim_var_string(VV_SWAPCOMMAND, p, -1);
|
||||
did_set_swapcommand = TRUE;
|
||||
|
|
|
@ -3168,27 +3168,27 @@ static char_u *get_mess_env(void)
|
|||
*/
|
||||
void set_lang_var(void)
|
||||
{
|
||||
char_u *loc;
|
||||
const char *loc;
|
||||
|
||||
# ifdef HAVE_GET_LOCALE_VAL
|
||||
loc = (char_u *)get_locale_val(LC_CTYPE);
|
||||
loc = get_locale_val(LC_CTYPE);
|
||||
# else
|
||||
/* setlocale() not supported: use the default value */
|
||||
loc = (char_u *)"C";
|
||||
// setlocale() not supported: use the default value
|
||||
loc = "C";
|
||||
# endif
|
||||
set_vim_var_string(VV_CTYPE, loc, -1);
|
||||
|
||||
/* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall
|
||||
* back to LC_CTYPE if it's empty. */
|
||||
# ifdef HAVE_WORKING_LIBINTL
|
||||
loc = get_mess_env();
|
||||
loc = (char *) get_mess_env();
|
||||
# else
|
||||
loc = (char_u *)get_locale_val(LC_MESSAGES);
|
||||
loc = get_locale_val(LC_MESSAGES);
|
||||
# endif
|
||||
set_vim_var_string(VV_LANG, loc, -1);
|
||||
|
||||
# ifdef HAVE_GET_LOCALE_VAL
|
||||
loc = (char_u *)get_locale_val(LC_TIME);
|
||||
loc = get_locale_val(LC_TIME);
|
||||
# endif
|
||||
set_vim_var_string(VV_LC_TIME, loc, -1);
|
||||
}
|
||||
|
|
|
@ -7421,10 +7421,10 @@ static int mksession_nl = FALSE; /* use NL only in put_eol() */
|
|||
static void ex_mkrc(exarg_T *eap)
|
||||
{
|
||||
FILE *fd;
|
||||
int failed = FALSE;
|
||||
int view_session = FALSE;
|
||||
int using_vdir = FALSE; /* using 'viewdir'? */
|
||||
char_u *viewFile = NULL;
|
||||
int failed = false;
|
||||
int view_session = false;
|
||||
int using_vdir = false; // using 'viewdir'?
|
||||
char *viewFile = NULL;
|
||||
unsigned *flagp;
|
||||
|
||||
if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview) {
|
||||
|
@ -7435,32 +7435,34 @@ static void ex_mkrc(exarg_T *eap)
|
|||
* short file name when 'acd' is set, that is checked later. */
|
||||
did_lcd = FALSE;
|
||||
|
||||
char_u *fname;
|
||||
/* ":mkview" or ":mkview 9": generate file name with 'viewdir' */
|
||||
char *fname;
|
||||
// ":mkview" or ":mkview 9": generate file name with 'viewdir'
|
||||
if (eap->cmdidx == CMD_mkview
|
||||
&& (*eap->arg == NUL
|
||||
|| (ascii_isdigit(*eap->arg) && eap->arg[1] == NUL))) {
|
||||
eap->forceit = TRUE;
|
||||
fname = (char_u *)get_view_file(*eap->arg);
|
||||
if (fname == NULL)
|
||||
eap->forceit = true;
|
||||
fname = get_view_file(*eap->arg);
|
||||
if (fname == NULL) {
|
||||
return;
|
||||
}
|
||||
viewFile = fname;
|
||||
using_vdir = TRUE;
|
||||
} else if (*eap->arg != NUL)
|
||||
fname = eap->arg;
|
||||
else if (eap->cmdidx == CMD_mkvimrc)
|
||||
fname = (char_u *)VIMRC_FILE;
|
||||
else if (eap->cmdidx == CMD_mksession)
|
||||
fname = (char_u *)SESSION_FILE;
|
||||
else
|
||||
fname = (char_u *)EXRC_FILE;
|
||||
using_vdir = true;
|
||||
} else if (*eap->arg != NUL) {
|
||||
fname = (char *) eap->arg;
|
||||
} else if (eap->cmdidx == CMD_mkvimrc) {
|
||||
fname = VIMRC_FILE;
|
||||
} else if (eap->cmdidx == CMD_mksession) {
|
||||
fname = SESSION_FILE;
|
||||
} else {
|
||||
fname = EXRC_FILE;
|
||||
}
|
||||
|
||||
/* When using 'viewdir' may have to create the directory. */
|
||||
if (using_vdir && !os_isdir(p_vdir)) {
|
||||
vim_mkdir_emsg(p_vdir, 0755);
|
||||
}
|
||||
|
||||
fd = open_exfile(fname, eap->forceit, WRITEBIN);
|
||||
fd = open_exfile((char_u *) fname, eap->forceit, WRITEBIN);
|
||||
if (fd != NULL) {
|
||||
if (eap->cmdidx == CMD_mkview)
|
||||
flagp = &vop_flags;
|
||||
|
@ -7504,8 +7506,9 @@ static void ex_mkrc(exarg_T *eap)
|
|||
|| os_chdir((char *)dirnow) != 0)
|
||||
*dirnow = NUL;
|
||||
if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR)) {
|
||||
if (vim_chdirfile(fname) == OK)
|
||||
shorten_fnames(TRUE);
|
||||
if (vim_chdirfile((char_u *) fname) == OK) {
|
||||
shorten_fnames(true);
|
||||
}
|
||||
} else if (*dirnow != NUL
|
||||
&& (ssop_flags & SSOP_CURDIR) && globaldir != NULL) {
|
||||
if (os_chdir((char *)globaldir) == 0)
|
||||
|
@ -7550,15 +7553,14 @@ static void ex_mkrc(exarg_T *eap)
|
|||
|
||||
failed |= fclose(fd);
|
||||
|
||||
if (failed)
|
||||
if (failed) {
|
||||
EMSG(_(e_write));
|
||||
else if (eap->cmdidx == CMD_mksession) {
|
||||
/* successful session write - set this_session var */
|
||||
char_u *tbuf;
|
||||
|
||||
tbuf = xmalloc(MAXPATHL);
|
||||
if (vim_FullName((char *)fname, (char *)tbuf, MAXPATHL, FALSE) == OK)
|
||||
} else if (eap->cmdidx == CMD_mksession) {
|
||||
// successful session write - set this_session var
|
||||
char *const tbuf = xmalloc(MAXPATHL);
|
||||
if (vim_FullName(fname, tbuf, MAXPATHL, false) == OK) {
|
||||
set_vim_var_string(VV_THIS_SESSION, tbuf, -1);
|
||||
}
|
||||
xfree(tbuf);
|
||||
}
|
||||
#ifdef MKSESSION_NL
|
||||
|
|
|
@ -569,17 +569,19 @@ static void catch_exception(except_T *excp)
|
|||
{
|
||||
excp->caught = caught_stack;
|
||||
caught_stack = excp;
|
||||
set_vim_var_string(VV_EXCEPTION, excp->value, -1);
|
||||
set_vim_var_string(VV_EXCEPTION, (char *) excp->value, -1);
|
||||
if (*excp->throw_name != NUL) {
|
||||
if (excp->throw_lnum != 0)
|
||||
if (excp->throw_lnum != 0) {
|
||||
vim_snprintf((char *)IObuff, IOSIZE, _("%s, line %" PRId64),
|
||||
excp->throw_name, (int64_t)excp->throw_lnum);
|
||||
else
|
||||
excp->throw_name, (int64_t)excp->throw_lnum);
|
||||
} else {
|
||||
vim_snprintf((char *)IObuff, IOSIZE, "%s", excp->throw_name);
|
||||
set_vim_var_string(VV_THROWPOINT, IObuff, -1);
|
||||
} else
|
||||
/* throw_name not set on an exception from a command that was typed. */
|
||||
}
|
||||
set_vim_var_string(VV_THROWPOINT, (char *) IObuff, -1);
|
||||
} else {
|
||||
// throw_name not set on an exception from a command that was typed.
|
||||
set_vim_var_string(VV_THROWPOINT, NULL, -1);
|
||||
}
|
||||
|
||||
if (p_verbose >= 13 || debug_break_level > 0) {
|
||||
int save_msg_silent = msg_silent;
|
||||
|
@ -614,20 +616,22 @@ static void finish_exception(except_T *excp)
|
|||
EMSG(_(e_internal));
|
||||
caught_stack = caught_stack->caught;
|
||||
if (caught_stack != NULL) {
|
||||
set_vim_var_string(VV_EXCEPTION, caught_stack->value, -1);
|
||||
set_vim_var_string(VV_EXCEPTION, (char *) caught_stack->value, -1);
|
||||
if (*caught_stack->throw_name != NUL) {
|
||||
if (caught_stack->throw_lnum != 0)
|
||||
if (caught_stack->throw_lnum != 0) {
|
||||
vim_snprintf((char *)IObuff, IOSIZE,
|
||||
_("%s, line %" PRId64), caught_stack->throw_name,
|
||||
(int64_t)caught_stack->throw_lnum);
|
||||
else
|
||||
_("%s, line %" PRId64), caught_stack->throw_name,
|
||||
(int64_t)caught_stack->throw_lnum);
|
||||
} else {
|
||||
vim_snprintf((char *)IObuff, IOSIZE, "%s",
|
||||
caught_stack->throw_name);
|
||||
set_vim_var_string(VV_THROWPOINT, IObuff, -1);
|
||||
} else
|
||||
/* throw_name not set on an exception from a command that was
|
||||
* typed. */
|
||||
caught_stack->throw_name);
|
||||
}
|
||||
set_vim_var_string(VV_THROWPOINT, (char *) IObuff, -1);
|
||||
} else {
|
||||
// throw_name not set on an exception from a command that was
|
||||
// typed.
|
||||
set_vim_var_string(VV_THROWPOINT, NULL, -1);
|
||||
}
|
||||
} else {
|
||||
set_vim_var_string(VV_EXCEPTION, NULL, -1);
|
||||
set_vim_var_string(VV_THROWPOINT, NULL, -1);
|
||||
|
|
|
@ -2139,9 +2139,10 @@ readfile_charconvert (
|
|||
else {
|
||||
close(*fdp); /* close the input file, ignore errors */
|
||||
*fdp = -1;
|
||||
if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc,
|
||||
fname, tmpname) == FAIL)
|
||||
if (eval_charconvert((char *) fenc, enc_utf8 ? "utf-8" : (char *) p_enc,
|
||||
(char *) fname, (char *) tmpname) == FAIL) {
|
||||
errmsg = (char_u *)_("Conversion with 'charconvert' failed");
|
||||
}
|
||||
if (errmsg == NULL && (*fdp = os_open((char *)tmpname, O_RDONLY, 0)) < 0) {
|
||||
errmsg = (char_u *)_("can't read output of 'charconvert'");
|
||||
}
|
||||
|
@ -3435,9 +3436,9 @@ restore_backup:
|
|||
* with 'charconvert' to (overwrite) the output file.
|
||||
*/
|
||||
if (end != 0) {
|
||||
if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
|
||||
wfname, fname) == FAIL) {
|
||||
write_info.bw_conv_error = TRUE;
|
||||
if (eval_charconvert(enc_utf8 ? "utf-8" : (char *) p_enc, (char *) fenc,
|
||||
(char *) wfname, (char *) fname) == FAIL) {
|
||||
write_info.bw_conv_error = true;
|
||||
end = 0;
|
||||
}
|
||||
}
|
||||
|
@ -4740,7 +4741,6 @@ buf_check_timestamp (
|
|||
{
|
||||
int retval = 0;
|
||||
char_u *path;
|
||||
char_u *tbuf;
|
||||
char *mesg = NULL;
|
||||
char *mesg2 = "";
|
||||
int helpmesg = FALSE;
|
||||
|
@ -4810,19 +4810,17 @@ buf_check_timestamp (
|
|||
else
|
||||
reason = "time";
|
||||
|
||||
/*
|
||||
* Only give the warning if there are no FileChangedShell
|
||||
* autocommands.
|
||||
* Avoid being called recursively by setting "busy".
|
||||
*/
|
||||
busy = TRUE;
|
||||
set_vim_var_string(VV_FCS_REASON, (char_u *)reason, -1);
|
||||
set_vim_var_string(VV_FCS_CHOICE, (char_u *)"", -1);
|
||||
++allbuf_lock;
|
||||
// Only give the warning if there are no FileChangedShell
|
||||
// autocommands.
|
||||
// Avoid being called recursively by setting "busy".
|
||||
busy = true;
|
||||
set_vim_var_string(VV_FCS_REASON, reason, -1);
|
||||
set_vim_var_string(VV_FCS_CHOICE, "", -1);
|
||||
allbuf_lock++;
|
||||
n = apply_autocmds(EVENT_FILECHANGEDSHELL,
|
||||
buf->b_fname, buf->b_fname, FALSE, buf);
|
||||
--allbuf_lock;
|
||||
busy = FALSE;
|
||||
buf->b_fname, buf->b_fname, false, buf);
|
||||
allbuf_lock--;
|
||||
busy = false;
|
||||
if (n) {
|
||||
if (!buf_valid(buf))
|
||||
EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
|
||||
|
@ -4876,35 +4874,39 @@ buf_check_timestamp (
|
|||
|
||||
if (mesg != NULL) {
|
||||
path = home_replace_save(buf, buf->b_fname);
|
||||
if (!helpmesg)
|
||||
if (!helpmesg) {
|
||||
mesg2 = "";
|
||||
tbuf = xmalloc(STRLEN(path) + STRLEN(mesg) + STRLEN(mesg2) + 2);
|
||||
sprintf((char *)tbuf, mesg, path);
|
||||
/* Set warningmsg here, before the unimportant and output-specific
|
||||
* mesg2 has been appended. */
|
||||
}
|
||||
const size_t tbuf_len = STRLEN(path) + STRLEN(mesg) + STRLEN(mesg2) + 2;
|
||||
char *const tbuf = xmalloc(tbuf_len);
|
||||
snprintf(tbuf, tbuf_len, mesg, path);
|
||||
// Set warningmsg here, before the unimportant and output-specific
|
||||
// mesg2 has been appended.
|
||||
set_vim_var_string(VV_WARNINGMSG, tbuf, -1);
|
||||
if (can_reload) {
|
||||
if (*mesg2 != NUL) {
|
||||
STRCAT(tbuf, "\n");
|
||||
STRCAT(tbuf, mesg2);
|
||||
strncat(tbuf, "\n", tbuf_len);
|
||||
strncat(tbuf, mesg2, tbuf_len);
|
||||
}
|
||||
if (do_dialog(VIM_WARNING, (char_u *) _("Warning"), (char_u *) tbuf,
|
||||
(char_u *) _("&OK\n&Load File"), 1, NULL, true) == 2) {
|
||||
reload = true;
|
||||
}
|
||||
if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
|
||||
(char_u *)_("&OK\n&Load File"), 1, NULL, TRUE) == 2)
|
||||
reload = TRUE;
|
||||
} else if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned) {
|
||||
if (*mesg2 != NUL) {
|
||||
STRCAT(tbuf, "; ");
|
||||
STRCAT(tbuf, mesg2);
|
||||
strncat(tbuf, "; ", tbuf_len);
|
||||
strncat(tbuf, mesg2, tbuf_len);
|
||||
}
|
||||
EMSG(tbuf);
|
||||
retval = 2;
|
||||
} else {
|
||||
if (!autocmd_busy) {
|
||||
msg_start();
|
||||
msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
|
||||
if (*mesg2 != NUL)
|
||||
msg_puts_attr((char_u *) tbuf, hl_attr(HLF_E) + MSG_HIST);
|
||||
if (*mesg2 != NUL) {
|
||||
msg_puts_attr((char_u *)mesg2,
|
||||
hl_attr(HLF_W) + MSG_HIST);
|
||||
}
|
||||
msg_clr_eos();
|
||||
(void)msg_end();
|
||||
if (emsg_silent == 0) {
|
||||
|
|
|
@ -1699,14 +1699,14 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume,
|
|||
did_emsg = FALSE;
|
||||
|
||||
if (*wp->w_p_fdt != NUL) {
|
||||
char_u dashes[MAX_LEVEL + 2];
|
||||
char dashes[MAX_LEVEL + 2];
|
||||
win_T *save_curwin;
|
||||
int level;
|
||||
char_u *p;
|
||||
|
||||
/* Set "v:foldstart" and "v:foldend". */
|
||||
set_vim_var_nr(VV_FOLDSTART, lnum);
|
||||
set_vim_var_nr(VV_FOLDEND, lnume);
|
||||
// Set "v:foldstart" and "v:foldend".
|
||||
set_vim_var_nr(VV_FOLDSTART, (varnumber_T) lnum);
|
||||
set_vim_var_nr(VV_FOLDEND, (varnumber_T) lnume);
|
||||
|
||||
/* Set "v:folddashes" to a string of "level" dashes. */
|
||||
/* Set "v:foldlevel" to "level". */
|
||||
|
@ -1716,7 +1716,7 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume,
|
|||
memset(dashes, '-', (size_t)level);
|
||||
dashes[level] = NUL;
|
||||
set_vim_var_string(VV_FOLDDASHES, dashes, -1);
|
||||
set_vim_var_nr(VV_FOLDLEVEL, (long)level);
|
||||
set_vim_var_nr(VV_FOLDLEVEL, (varnumber_T) level);
|
||||
|
||||
/* skip evaluating foldtext on errors */
|
||||
if (!got_fdt_error) {
|
||||
|
@ -2676,7 +2676,7 @@ static void foldlevelExpr(fline_T *flp)
|
|||
win = curwin;
|
||||
curwin = flp->wp;
|
||||
curbuf = flp->wp->w_buffer;
|
||||
set_vim_var_nr(VV_LNUM, lnum);
|
||||
set_vim_var_nr(VV_LNUM, (varnumber_T) lnum);
|
||||
|
||||
flp->start = 0;
|
||||
flp->had_end = flp->end;
|
||||
|
|
|
@ -188,12 +188,23 @@ void ga_concat(garray_T *gap, const char_u *restrict s)
|
|||
return;
|
||||
}
|
||||
|
||||
int len = (int)strlen((char *) s);
|
||||
ga_concat_len(gap, (const char *restrict) s, strlen((char *) s));
|
||||
}
|
||||
|
||||
/// Concatenate a string to a growarray which contains characters
|
||||
///
|
||||
/// @param[out] gap Growarray to modify.
|
||||
/// @param[in] s String to concatenate.
|
||||
/// @param[in] len String length.
|
||||
void ga_concat_len(garray_T *const gap, const char *restrict s,
|
||||
const size_t len)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (len) {
|
||||
ga_grow(gap, len);
|
||||
ga_grow(gap, (int) len);
|
||||
char *data = gap->ga_data;
|
||||
memcpy(data + gap->ga_len, s, (size_t)len);
|
||||
gap->ga_len += len;
|
||||
memcpy(data + gap->ga_len, s, len);
|
||||
gap->ga_len += (int) len;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,17 +4,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
// EXTERN is only defined in main.c. That's where global variables are
|
||||
// actually defined and initialized.
|
||||
#ifndef EXTERN
|
||||
# define EXTERN extern
|
||||
# define INIT(...)
|
||||
#else
|
||||
# ifndef INIT
|
||||
# define INIT(...) __VA_ARGS__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/ex_eval.h"
|
||||
#include "nvim/iconv.h"
|
||||
#include "nvim/mbyte.h"
|
||||
|
|
|
@ -2780,11 +2780,13 @@ void mch_print_end(prt_settings_T *psettings)
|
|||
}
|
||||
prt_message((char_u *)_("Sending to printer..."));
|
||||
|
||||
/* Not printing to a file: use 'printexpr' to print the file. */
|
||||
if (eval_printexpr(prt_ps_file_name, psettings->arguments) == FAIL)
|
||||
// Not printing to a file: use 'printexpr' to print the file.
|
||||
if (eval_printexpr((char *) prt_ps_file_name, (char *) psettings->arguments)
|
||||
== FAIL) {
|
||||
EMSG(_("E365: Failed to print PostScript file"));
|
||||
else
|
||||
} else {
|
||||
prt_message((char_u *)_("Print job sent."));
|
||||
}
|
||||
}
|
||||
|
||||
mch_print_cleanup();
|
||||
|
|
|
@ -529,7 +529,7 @@ int get_expr_indent(void)
|
|||
save_pos = curwin->w_cursor;
|
||||
save_curswant = curwin->w_curswant;
|
||||
save_set_curswant = curwin->w_set_curswant;
|
||||
set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
|
||||
set_vim_var_nr(VV_LNUM, (varnumber_T) curwin->w_cursor.lnum);
|
||||
|
||||
if (use_sandbox) {
|
||||
sandbox++;
|
||||
|
|
|
@ -60,6 +60,7 @@ int main() {
|
|||
#define kv_pop(v) ((v).items[--(v).size])
|
||||
#define kv_size(v) ((v).size)
|
||||
#define kv_max(v) ((v).capacity)
|
||||
#define kv_last(v) kv_A(v, kv_size(v) - 1)
|
||||
|
||||
#define kv_resize(type, v, s) ((v).capacity = (s), (v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity))
|
||||
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
#ifndef NVIM_MACROS_H
|
||||
#define NVIM_MACROS_H
|
||||
|
||||
// EXTERN is only defined in main.c. That's where global variables are
|
||||
// actually defined and initialized.
|
||||
#ifndef EXTERN
|
||||
# define EXTERN extern
|
||||
# define INIT(...)
|
||||
#else
|
||||
# ifndef INIT
|
||||
# define INIT(...) __VA_ARGS__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
#endif
|
||||
|
|
|
@ -238,8 +238,8 @@ int main(int argc, char **argv)
|
|||
check_and_set_isatty(¶ms);
|
||||
|
||||
// Get the name with which Nvim was invoked, with and without path.
|
||||
set_vim_var_string(VV_PROGPATH, (char_u *)argv[0], -1);
|
||||
set_vim_var_string(VV_PROGNAME, path_tail((char_u *)argv[0]), -1);
|
||||
set_vim_var_string(VV_PROGPATH, argv[0], -1);
|
||||
set_vim_var_string(VV_PROGNAME, (char *) path_tail((char_u *) argv[0]), -1);
|
||||
|
||||
event_init();
|
||||
/*
|
||||
|
@ -1141,10 +1141,11 @@ scripterror:
|
|||
/* If there is a "+123" or "-c" command, set v:swapcommand to the first
|
||||
* one. */
|
||||
if (parmp->n_commands > 0) {
|
||||
p = xmalloc(STRLEN(parmp->commands[0]) + 3);
|
||||
sprintf((char *)p, ":%s\r", parmp->commands[0]);
|
||||
set_vim_var_string(VV_SWAPCOMMAND, p, -1);
|
||||
xfree(p);
|
||||
const size_t swcmd_len = STRLEN(parmp->commands[0]) + 3;
|
||||
char *const swcmd = xmalloc(swcmd_len);
|
||||
snprintf(swcmd, swcmd_len, ":%s\r", parmp->commands[0]);
|
||||
set_vim_var_string(VV_SWAPCOMMAND, swcmd, -1);
|
||||
xfree(swcmd);
|
||||
}
|
||||
TIME_MSG("parsing arguments");
|
||||
}
|
||||
|
|
|
@ -3194,7 +3194,7 @@ attention_message (
|
|||
*/
|
||||
static int do_swapexists(buf_T *buf, char_u *fname)
|
||||
{
|
||||
set_vim_var_string(VV_SWAPNAME, fname, -1);
|
||||
set_vim_var_string(VV_SWAPNAME, (char *) fname, -1);
|
||||
set_vim_var_string(VV_SWAPCHOICE, NULL, -1);
|
||||
|
||||
/* Trigger SwapExists autocommands with <afile> set to the file being
|
||||
|
|
|
@ -61,14 +61,8 @@ static int confirm_msg_used = FALSE; /* displaying confirm_msg */
|
|||
static char_u *confirm_msg = NULL; /* ":confirm" message */
|
||||
static char_u *confirm_msg_tail; /* tail of confirm_msg */
|
||||
|
||||
struct msg_hist {
|
||||
struct msg_hist *next;
|
||||
char_u *msg;
|
||||
int attr;
|
||||
};
|
||||
|
||||
static struct msg_hist *first_msg_hist = NULL;
|
||||
static struct msg_hist *last_msg_hist = NULL;
|
||||
MessageHistoryEntry *first_msg_hist = NULL;
|
||||
MessageHistoryEntry *last_msg_hist = NULL;
|
||||
static int msg_hist_len = 0;
|
||||
|
||||
static FILE *verbose_fd = NULL;
|
||||
|
@ -149,10 +143,11 @@ msg_attr_keep (
|
|||
{
|
||||
static int entered = 0;
|
||||
int retval;
|
||||
char_u *buf = NULL;
|
||||
char_u *buf = NULL;
|
||||
|
||||
if (attr == 0)
|
||||
set_vim_var_string(VV_STATUSMSG, s, -1);
|
||||
if (attr == 0) {
|
||||
set_vim_var_string(VV_STATUSMSG, (char *) s, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* It is possible that displaying a messages causes a problem (e.g.,
|
||||
|
@ -503,8 +498,8 @@ int emsg(char_u *s)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* set "v:errmsg", also when using ":silent! cmd" */
|
||||
set_vim_var_string(VV_ERRMSG, s, -1);
|
||||
// set "v:errmsg", also when using ":silent! cmd"
|
||||
set_vim_var_string(VV_ERRMSG, (char *) s, -1);
|
||||
|
||||
/*
|
||||
* When using ":silent! cmd" ignore error messages.
|
||||
|
@ -563,49 +558,23 @@ int emsg(char_u *s)
|
|||
return msg_attr(s, attr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an error message with one "%s" and one string argument.
|
||||
*/
|
||||
int emsg2(char_u *s, char_u *a1)
|
||||
{
|
||||
return emsg3(s, a1, NULL);
|
||||
}
|
||||
|
||||
void emsg_invreg(int name)
|
||||
{
|
||||
EMSG2(_("E354: Invalid register name: '%s'"), transchar(name));
|
||||
}
|
||||
|
||||
/// Print an error message with one or two "%s" and one or two string arguments.
|
||||
int emsg3(char_u *s, char_u *a1, char_u *a2)
|
||||
/// Print an error message with unknown number of arguments
|
||||
bool emsgf(const char *const fmt, ...)
|
||||
{
|
||||
if (emsg_not_now()) {
|
||||
return TRUE; // no error messages at the moment
|
||||
return true;
|
||||
}
|
||||
|
||||
vim_snprintf((char *)IObuff, IOSIZE, (char *)s, a1, a2);
|
||||
return emsg(IObuff);
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vim_vsnprintf((char *) IObuff, IOSIZE, fmt, ap, NULL);
|
||||
va_end(ap);
|
||||
|
||||
/// Print an error message with one "%" PRId64 and one (int64_t) argument.
|
||||
int emsgn(char_u *s, int64_t n)
|
||||
{
|
||||
if (emsg_not_now()) {
|
||||
return TRUE; // no error messages at the moment
|
||||
}
|
||||
|
||||
vim_snprintf((char *)IObuff, IOSIZE, (char *)s, n);
|
||||
return emsg(IObuff);
|
||||
}
|
||||
|
||||
/// Print an error message with one "%" PRIu64 and one (uint64_t) argument.
|
||||
int emsgu(char_u *s, uint64_t n)
|
||||
{
|
||||
if (emsg_not_now()) {
|
||||
return TRUE; // no error messages at the moment
|
||||
}
|
||||
|
||||
vim_snprintf((char *)IObuff, IOSIZE, (char *)s, n);
|
||||
return emsg(IObuff);
|
||||
}
|
||||
|
||||
|
@ -1787,25 +1756,24 @@ static void msg_scroll_up(void)
|
|||
static void inc_msg_scrolled(void)
|
||||
{
|
||||
if (*get_vim_var_str(VV_SCROLLSTART) == NUL) {
|
||||
char_u *p = sourcing_name;
|
||||
char_u *tofree = NULL;
|
||||
int len;
|
||||
char *p = (char *) sourcing_name;
|
||||
char *tofree = NULL;
|
||||
|
||||
/* v:scrollstart is empty, set it to the script/function name and line
|
||||
* number */
|
||||
if (p == NULL)
|
||||
p = (char_u *)_("Unknown");
|
||||
else {
|
||||
len = (int)STRLEN(p) + 40;
|
||||
// v:scrollstart is empty, set it to the script/function name and line
|
||||
// number
|
||||
if (p == NULL) {
|
||||
p = _("Unknown");
|
||||
} else {
|
||||
size_t len = strlen(p) + 40;
|
||||
tofree = xmalloc(len);
|
||||
vim_snprintf((char *)tofree, len, _("%s line %" PRId64),
|
||||
p, (int64_t)sourcing_lnum);
|
||||
vim_snprintf(tofree, len, _("%s line %" PRId64),
|
||||
p, (int64_t) sourcing_lnum);
|
||||
p = tofree;
|
||||
}
|
||||
set_vim_var_string(VV_SCROLLSTART, p, -1);
|
||||
xfree(tofree);
|
||||
}
|
||||
++msg_scrolled;
|
||||
msg_scrolled++;
|
||||
}
|
||||
|
||||
static msgchunk_T *last_msgchunk = NULL; /* last displayed text */
|
||||
|
@ -2572,7 +2540,7 @@ void give_warning(char_u *message, bool hl) FUNC_ATTR_NONNULL_ARG(1)
|
|||
/* Don't want a hit-enter prompt here. */
|
||||
++no_wait_return;
|
||||
|
||||
set_vim_var_string(VV_WARNINGMSG, message, -1);
|
||||
set_vim_var_string(VV_WARNINGMSG, (char *) message, -1);
|
||||
xfree(keep_msg);
|
||||
keep_msg = NULL;
|
||||
if (hl)
|
||||
|
@ -3086,7 +3054,7 @@ int vim_snprintf_add(char *str, size_t str_m, char *fmt, ...)
|
|||
return str_l;
|
||||
}
|
||||
|
||||
int vim_snprintf(char *str, size_t str_m, char *fmt, ...)
|
||||
int vim_snprintf(char *str, size_t str_m, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int str_l;
|
||||
|
@ -3097,11 +3065,12 @@ int vim_snprintf(char *str, size_t str_m, char *fmt, ...)
|
|||
return str_l;
|
||||
}
|
||||
|
||||
int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs)
|
||||
int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
|
||||
typval_T *tvs)
|
||||
{
|
||||
size_t str_l = 0;
|
||||
bool str_avail = str_l < str_m;
|
||||
char *p = fmt;
|
||||
const char *p = fmt;
|
||||
int arg_idx = 1;
|
||||
|
||||
if (!p) {
|
||||
|
@ -3135,7 +3104,7 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs)
|
|||
char tmp[TMP_LEN];
|
||||
|
||||
// string address in case of string argument
|
||||
char *str_arg;
|
||||
const char *str_arg;
|
||||
|
||||
// natural field width of arg without padding and sign
|
||||
size_t str_arg_l;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include "nvim/eval_defs.h" // for typval_T
|
||||
#include "nvim/ex_cmds_defs.h" // for exarg_T
|
||||
|
||||
/*
|
||||
* Types of dialogs passed to do_dialog().
|
||||
|
@ -24,6 +25,56 @@
|
|||
#define VIM_ALL 5
|
||||
#define VIM_DISCARDALL 6
|
||||
|
||||
/// Show plain message
|
||||
#define MSG(s) msg((char_u *)(s))
|
||||
|
||||
/// Show message highlighted according to the attr
|
||||
#define MSG_ATTR(s, attr) msg_attr((char_u *)(s), (attr))
|
||||
|
||||
/// Display error message
|
||||
///
|
||||
/// Sets error flag in process, can be transformed into an exception.
|
||||
#define EMSG(s) emsg((char_u *)(s))
|
||||
|
||||
/// Like #EMSG, but for messages with one "%s" inside
|
||||
#define EMSG2(s, p) emsgf((const char *) (s), (p))
|
||||
|
||||
/// Like #EMSG, but for messages with two "%s" inside
|
||||
#define EMSG3(s, p, q) emsgf((const char *) (s), (p), (q))
|
||||
|
||||
/// Like #EMSG, but for messages with one "%" PRId64 inside
|
||||
#define EMSGN(s, n) emsgf((const char *) (s), (int64_t)(n))
|
||||
|
||||
/// Like #EMSG, but for messages with one "%" PRIu64 inside
|
||||
#define EMSGU(s, n) emsgf((const char *) (s), (uint64_t)(n))
|
||||
|
||||
/// Display message at the recorded position
|
||||
#define MSG_PUTS(s) msg_puts((char_u *)(s))
|
||||
|
||||
/// Display message at the recorded position, highlighted
|
||||
#define MSG_PUTS_ATTR(s, a) msg_puts_attr((char_u *)(s), (a))
|
||||
|
||||
/// Like #MSG_PUTS, but highlight like title
|
||||
#define MSG_PUTS_TITLE(s) msg_puts_title((char_u *)(s))
|
||||
|
||||
/// Like #MSG_PUTS, but if middle part of too long messages it will be replaced
|
||||
#define MSG_PUTS_LONG(s) msg_puts_long_attr((char_u *)(s), 0)
|
||||
|
||||
/// Like #MSG_PUTS_ATTR, but if middle part of long messages will be replaced
|
||||
#define MSG_PUTS_LONG_ATTR(s, a) msg_puts_long_attr((char_u *)(s), (a))
|
||||
|
||||
/// Message history for `:messages`
|
||||
typedef struct msg_hist {
|
||||
struct msg_hist *next; ///< Next message.
|
||||
char_u *msg; ///< Message text.
|
||||
int attr; ///< Message highlighting.
|
||||
} MessageHistoryEntry;
|
||||
|
||||
/// First message
|
||||
extern MessageHistoryEntry *first_msg_hist;
|
||||
/// Last message
|
||||
extern MessageHistoryEntry *last_msg_hist;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "message.h.generated.h"
|
||||
#endif
|
||||
|
|
|
@ -2250,7 +2250,7 @@ change_warning (
|
|||
msg_col = col;
|
||||
msg_source(hl_attr(HLF_W));
|
||||
MSG_PUTS_ATTR(_(w_readonly), hl_attr(HLF_W) | MSG_HIST);
|
||||
set_vim_var_string(VV_WARNINGMSG, (char_u *)_(w_readonly), -1);
|
||||
set_vim_var_string(VV_WARNINGMSG, _(w_readonly), -1);
|
||||
msg_clr_eos();
|
||||
(void)msg_end();
|
||||
if (msg_silent == 0 && !silent_mode) {
|
||||
|
|
|
@ -327,9 +327,10 @@ int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg)
|
|||
}
|
||||
}
|
||||
|
||||
set_vim_var_nr(VV_SHELL_ERROR, (long)retval);
|
||||
if (do_profiling == PROF_YES)
|
||||
set_vim_var_nr(VV_SHELL_ERROR, (varnumber_T) retval);
|
||||
if (do_profiling == PROF_YES) {
|
||||
prof_child_exit(&wait_time);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ static void set_vservername(garray_T *srvs)
|
|||
char *default_server = (srvs->ga_len > 0)
|
||||
? ((SocketWatcher **)srvs->ga_data)[0]->addr
|
||||
: NULL;
|
||||
set_vim_var_string(VV_SEND_SERVER, (char_u *)default_server, -1);
|
||||
set_vim_var_string(VV_SEND_SERVER, default_server, -1);
|
||||
}
|
||||
|
||||
/// Teardown the server module
|
||||
|
|
|
@ -7057,18 +7057,17 @@ static void nv_operator(cmdarg_T *cap)
|
|||
*/
|
||||
static void set_op_var(int optype)
|
||||
{
|
||||
char_u opchars[3];
|
||||
|
||||
if (optype == OP_NOP)
|
||||
if (optype == OP_NOP) {
|
||||
set_vim_var_string(VV_OP, NULL, 0);
|
||||
else {
|
||||
} else {
|
||||
char opchars[3];
|
||||
int opchar0 = get_op_char(optype);
|
||||
assert(opchar0 >= 0 && opchar0 <= UCHAR_MAX);
|
||||
opchars[0] = (char_u)opchar0;
|
||||
opchars[0] = (char) opchar0;
|
||||
|
||||
int opchar1 = get_extra_op_char(optype);
|
||||
assert(opchar1 >= 0 && opchar1 <= UCHAR_MAX);
|
||||
opchars[1] = (char_u)opchar1;
|
||||
opchars[1] = (char) opchar1;
|
||||
|
||||
opchars[2] = NUL;
|
||||
set_vim_var_string(VV_OP, opchars, -1);
|
||||
|
|
|
@ -1448,7 +1448,7 @@ do_set (
|
|||
char_u *oldval = NULL; // previous value if *varp
|
||||
char_u *newval;
|
||||
char_u *origval = NULL;
|
||||
char_u *saved_origval = NULL;
|
||||
char *saved_origval = NULL;
|
||||
unsigned newlen;
|
||||
int comma;
|
||||
int bs;
|
||||
|
@ -1725,7 +1725,7 @@ do_set (
|
|||
if (!starting && origval != NULL) {
|
||||
// origval may be freed by
|
||||
// did_set_string_option(), make a copy.
|
||||
saved_origval = vim_strsave(origval);
|
||||
saved_origval = xstrdup((char *) origval);
|
||||
}
|
||||
|
||||
/* Handle side effects, and set the global value for
|
||||
|
@ -1740,11 +1740,10 @@ do_set (
|
|||
}
|
||||
|
||||
if (saved_origval != NULL) {
|
||||
char_u buf_type[7];
|
||||
vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s",
|
||||
char buf_type[7];
|
||||
vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
|
||||
(opt_flags & OPT_LOCAL) ? "local" : "global");
|
||||
set_vim_var_string(VV_OPTION_NEW,
|
||||
*(char_u **)varp, -1);
|
||||
set_vim_var_string(VV_OPTION_NEW, *(char **) varp, -1);
|
||||
set_vim_var_string(VV_OPTION_OLD, saved_origval, -1);
|
||||
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
|
||||
apply_autocmds(EVENT_OPTIONSET,
|
||||
|
@ -2324,7 +2323,7 @@ set_string_option (
|
|||
char_u *s;
|
||||
char_u **varp;
|
||||
char_u *oldval;
|
||||
char_u *saved_oldval = NULL;
|
||||
char *saved_oldval = NULL;
|
||||
char_u *r = NULL;
|
||||
|
||||
if (options[opt_idx].var == NULL) /* don't set hidden option */
|
||||
|
@ -2340,7 +2339,7 @@ set_string_option (
|
|||
*varp = s;
|
||||
|
||||
if (!starting) {
|
||||
saved_oldval = vim_strsave(oldval);
|
||||
saved_oldval = xstrdup((char *) oldval);
|
||||
}
|
||||
|
||||
if ((r = did_set_string_option(opt_idx, varp, (int)true, oldval, NULL,
|
||||
|
@ -2349,10 +2348,10 @@ set_string_option (
|
|||
|
||||
// call autocommand after handling side effects
|
||||
if (saved_oldval != NULL) {
|
||||
char_u buf_type[7];
|
||||
vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s",
|
||||
char buf_type[7];
|
||||
vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
|
||||
(opt_flags & OPT_LOCAL) ? "local" : "global");
|
||||
set_vim_var_string(VV_OPTION_NEW, *varp, -1);
|
||||
set_vim_var_string(VV_OPTION_NEW, (char *) (*varp), -1);
|
||||
set_vim_var_string(VV_OPTION_OLD, saved_oldval, -1);
|
||||
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
|
||||
apply_autocmds(EVENT_OPTIONSET,
|
||||
|
@ -3800,7 +3799,7 @@ set_bool_option (
|
|||
|
||||
msg_source(hl_attr(HLF_W));
|
||||
MSG_ATTR(_(w_arabic), hl_attr(HLF_W));
|
||||
set_vim_var_string(VV_WARNINGMSG, (char_u *)_(w_arabic), -1);
|
||||
set_vim_var_string(VV_WARNINGMSG, _(w_arabic), -1);
|
||||
}
|
||||
|
||||
/* set 'delcombine' */
|
||||
|
@ -3847,14 +3846,14 @@ set_bool_option (
|
|||
options[opt_idx].flags |= P_WAS_SET;
|
||||
|
||||
if (!starting) {
|
||||
char_u buf_old[2];
|
||||
char_u buf_new[2];
|
||||
char_u buf_type[7];
|
||||
vim_snprintf((char *)buf_old, ARRAY_SIZE(buf_old), "%d",
|
||||
char buf_old[2];
|
||||
char buf_new[2];
|
||||
char buf_type[7];
|
||||
vim_snprintf(buf_old, ARRAY_SIZE(buf_old), "%d",
|
||||
old_value ? true: false);
|
||||
vim_snprintf((char *)buf_new, ARRAY_SIZE(buf_new), "%d",
|
||||
vim_snprintf(buf_new, ARRAY_SIZE(buf_new), "%d",
|
||||
value ? true: false);
|
||||
vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s",
|
||||
vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
|
||||
(opt_flags & OPT_LOCAL) ? "local" : "global");
|
||||
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
|
||||
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
|
||||
|
@ -4237,12 +4236,12 @@ set_num_option (
|
|||
options[opt_idx].flags |= P_WAS_SET;
|
||||
|
||||
if (!starting && errmsg == NULL) {
|
||||
char_u buf_old[NUMBUFLEN];
|
||||
char_u buf_new[NUMBUFLEN];
|
||||
char_u buf_type[7];
|
||||
vim_snprintf((char *)buf_old, ARRAY_SIZE(buf_old), "%ld", old_value);
|
||||
vim_snprintf((char *)buf_new, ARRAY_SIZE(buf_new), "%ld", value);
|
||||
vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s",
|
||||
char buf_old[NUMBUFLEN];
|
||||
char buf_new[NUMBUFLEN];
|
||||
char buf_type[7];
|
||||
vim_snprintf(buf_old, ARRAY_SIZE(buf_old), "%ld", old_value);
|
||||
vim_snprintf(buf_new, ARRAY_SIZE(buf_new), "%ld", value);
|
||||
vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
|
||||
(opt_flags & OPT_LOCAL) ? "local" : "global");
|
||||
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
|
||||
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/types.h"
|
||||
#include "nvim/macros.h" // For EXTERN
|
||||
|
||||
// option_defs.h: definition of global variables for settable options
|
||||
|
||||
|
|
|
@ -1495,13 +1495,12 @@ void simplify_filename(char_u *filename)
|
|||
} while (*p != NUL);
|
||||
}
|
||||
|
||||
static char_u *eval_includeexpr(char_u *ptr, size_t len)
|
||||
static char *eval_includeexpr(const char *const ptr, const size_t len)
|
||||
{
|
||||
assert(len <= INT_MAX);
|
||||
set_vim_var_string(VV_FNAME, ptr, (int)len);
|
||||
char_u *res = eval_to_string_safe(curbuf->b_p_inex, NULL,
|
||||
was_set_insecurely((char_u *)"includeexpr",
|
||||
OPT_LOCAL));
|
||||
set_vim_var_string(VV_FNAME, ptr, (ptrdiff_t) len);
|
||||
char *res = (char *) eval_to_string_safe(
|
||||
curbuf->b_p_inex, NULL, was_set_insecurely((char_u *)"includeexpr",
|
||||
OPT_LOCAL));
|
||||
set_vim_var_string(VV_FNAME, NULL, 0);
|
||||
return res;
|
||||
}
|
||||
|
@ -1523,7 +1522,7 @@ find_file_name_in_path (
|
|||
char_u *tofree = NULL;
|
||||
|
||||
if ((options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
|
||||
tofree = eval_includeexpr(ptr, len);
|
||||
tofree = (char_u *) eval_includeexpr((char *) ptr, len);
|
||||
if (tofree != NULL) {
|
||||
ptr = tofree;
|
||||
len = STRLEN(ptr);
|
||||
|
@ -1540,7 +1539,7 @@ find_file_name_in_path (
|
|||
*/
|
||||
if (file_name == NULL
|
||||
&& !(options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
|
||||
tofree = eval_includeexpr(ptr, len);
|
||||
tofree = (char_u *) eval_includeexpr((char *) ptr, len);
|
||||
if (tofree != NULL) {
|
||||
ptr = tofree;
|
||||
len = STRLEN(ptr);
|
||||
|
|
|
@ -2440,8 +2440,6 @@ int grep_internal(cmdidx_T cmdidx)
|
|||
void ex_make(exarg_T *eap)
|
||||
{
|
||||
char_u *fname;
|
||||
char_u *cmd;
|
||||
size_t len;
|
||||
win_T *wp = NULL;
|
||||
qf_info_T *qi = &ql_info;
|
||||
int res;
|
||||
|
@ -2479,30 +2477,28 @@ void ex_make(exarg_T *eap)
|
|||
return;
|
||||
os_remove((char *)fname); // in case it's not unique
|
||||
|
||||
/*
|
||||
* If 'shellpipe' empty: don't redirect to 'errorfile'.
|
||||
*/
|
||||
len = STRLEN(p_shq) * 2 + STRLEN(eap->arg) + 1;
|
||||
// If 'shellpipe' empty: don't redirect to 'errorfile'.
|
||||
const size_t len = (STRLEN(p_shq) * 2 + STRLEN(eap->arg) + 1
|
||||
+ (*p_sp == NUL
|
||||
? 0
|
||||
: STRLEN(p_sp) + STRLEN(fname) + 3));
|
||||
char *const cmd = xmalloc(len);
|
||||
snprintf(cmd, len, "%s%s%s", (char *)p_shq, (char *)eap->arg,
|
||||
(char *)p_shq);
|
||||
if (*p_sp != NUL) {
|
||||
len += STRLEN(p_sp) + STRLEN(fname) + 3;
|
||||
append_redir(cmd, len, (char *) p_sp, (char *) fname);
|
||||
}
|
||||
// Output a newline if there's something else than the :make command that
|
||||
// was typed (in which case the cursor is in column 0).
|
||||
if (msg_col == 0) {
|
||||
msg_didout = false;
|
||||
}
|
||||
cmd = xmalloc(len);
|
||||
sprintf((char *)cmd, "%s%s%s", (char *)p_shq, (char *)eap->arg,
|
||||
(char *)p_shq);
|
||||
if (*p_sp != NUL)
|
||||
append_redir(cmd, len, p_sp, fname);
|
||||
/*
|
||||
* Output a newline if there's something else than the :make command that
|
||||
* was typed (in which case the cursor is in column 0).
|
||||
*/
|
||||
if (msg_col == 0)
|
||||
msg_didout = FALSE;
|
||||
msg_start();
|
||||
MSG_PUTS(":!");
|
||||
msg_outtrans(cmd); /* show what we are doing */
|
||||
msg_outtrans((char_u *) cmd); // show what we are doing
|
||||
|
||||
/* let the shell know if we are redirecting output or not */
|
||||
do_shell(cmd, *p_sp != NUL ? kShellOptDoOut : 0);
|
||||
// let the shell know if we are redirecting output or not
|
||||
do_shell((char_u *) cmd, *p_sp != NUL ? kShellOptDoOut : 0);
|
||||
|
||||
|
||||
res = qf_init(wp, fname, (eap->cmdidx != CMD_make
|
||||
|
|
130
src/nvim/shada.c
130
src/nvim/shada.c
|
@ -31,7 +31,6 @@
|
|||
#include "nvim/misc2.h"
|
||||
#include "nvim/ex_getln.h"
|
||||
#include "nvim/search.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/regexp.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/version.h"
|
||||
|
@ -39,6 +38,8 @@
|
|||
#include "nvim/fileio.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/quickfix.h"
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/eval/decode.h"
|
||||
#include "nvim/lib/khash.h"
|
||||
#include "nvim/lib/kvec.h"
|
||||
|
||||
|
@ -65,9 +66,6 @@ KHASH_SET_INIT_STR(strset)
|
|||
((char *) copy_option_part((char_u **) src, (char_u *) dest, __VA_ARGS__))
|
||||
#define find_shada_parameter(...) \
|
||||
((const char *) find_shada_parameter(__VA_ARGS__))
|
||||
#define emsg2(a, b) emsg2((char_u *) a, (char_u *) b)
|
||||
#define emsg3(a, b, c) emsg3((char_u *) a, (char_u *) b, (char_u *) c)
|
||||
#define emsgu(a, ...) emsgu((char_u *) a, __VA_ARGS__)
|
||||
#define home_replace_save(a, b) \
|
||||
((char *)home_replace_save(a, (char_u *)b))
|
||||
#define home_replace(a, b, c, d, e) \
|
||||
|
@ -761,7 +759,7 @@ static void close_sd_writer(ShaDaWriteDef *const sd_writer)
|
|||
{
|
||||
const int fd = (int)(intptr_t) sd_writer->cookie;
|
||||
if (os_fsync(fd) < 0) {
|
||||
emsg2(_(SERR "System error while synchronizing ShaDa file: %s"),
|
||||
emsgf(_(SERR "System error while synchronizing ShaDa file: %s"),
|
||||
os_strerror(errno));
|
||||
errno = 0;
|
||||
}
|
||||
|
@ -811,11 +809,11 @@ static ShaDaReadResult sd_reader_skip(ShaDaReadDef *const sd_reader,
|
|||
{
|
||||
if (sd_reader->skip(sd_reader, offset) != OK) {
|
||||
if (sd_reader->error != NULL) {
|
||||
emsg2(_(SERR "System error while skipping in ShaDa file: %s"),
|
||||
emsgf(_(SERR "System error while skipping in ShaDa file: %s"),
|
||||
sd_reader->error);
|
||||
return kSDReadStatusReadError;
|
||||
} else if (sd_reader->eof) {
|
||||
emsgu(_(RCERR "Error while reading ShaDa file: "
|
||||
emsgf(_(RCERR "Error while reading ShaDa file: "
|
||||
"last entry specified that it occupies %" PRIu64 " bytes, "
|
||||
"but file ended earlier"),
|
||||
(uint64_t) offset);
|
||||
|
@ -849,7 +847,7 @@ open_file_start:
|
|||
goto open_file_start;
|
||||
}
|
||||
if (fd != UV_EEXIST) {
|
||||
emsg3(_(SERR "System error while opening ShaDa file %s: %s"),
|
||||
emsgf(_(SERR "System error while opening ShaDa file %s: %s"),
|
||||
fname, os_strerror(fd));
|
||||
}
|
||||
return fd;
|
||||
|
@ -897,7 +895,7 @@ close_file_start:
|
|||
errno = 0;
|
||||
goto close_file_start;
|
||||
} else {
|
||||
emsg2(_(SERR "System error while closing ShaDa file: %s"),
|
||||
emsgf(_(SERR "System error while closing ShaDa file: %s"),
|
||||
strerror(errno));
|
||||
errno = 0;
|
||||
}
|
||||
|
@ -934,7 +932,7 @@ static int msgpack_sd_writer_write(void *data, const char *buf, size_t len)
|
|||
ShaDaWriteDef *const sd_writer = (ShaDaWriteDef *) data;
|
||||
ptrdiff_t written_bytes = sd_writer->write(sd_writer, buf, len);
|
||||
if (written_bytes == -1) {
|
||||
emsg2(_(SERR "System error while writing ShaDa file: %s"),
|
||||
emsgf(_(SERR "System error while writing ShaDa file: %s"),
|
||||
sd_writer->error);
|
||||
return -1;
|
||||
}
|
||||
|
@ -981,7 +979,7 @@ static int shada_read_file(const char *const file, const int flags)
|
|||
|
||||
if (of_ret != 0) {
|
||||
if (of_ret == UV_ENOENT && (flags & kShaDaMissingError)) {
|
||||
emsg3(_(SERR "System error while opening ShaDa file %s for reading: %s"),
|
||||
emsgf(_(SERR "System error while opening ShaDa file %s for reading: %s"),
|
||||
fname, os_strerror(of_ret));
|
||||
}
|
||||
xfree(fname);
|
||||
|
@ -1687,8 +1685,9 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
|
|||
do { \
|
||||
if ((src) != NULL) { \
|
||||
for (listitem_T *li = (src)->lv_first; li != NULL; li = li->li_next) { \
|
||||
if (vim_to_msgpack(spacker, &li->li_tv, \
|
||||
_("additional elements of ShaDa " what)) == FAIL) { \
|
||||
if (encode_vim_to_msgpack(spacker, &li->li_tv, \
|
||||
_("additional elements of ShaDa " what)) \
|
||||
== FAIL) { \
|
||||
goto shada_pack_entry_error; \
|
||||
} \
|
||||
} \
|
||||
|
@ -1706,8 +1705,9 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
|
|||
const size_t key_len = strlen((const char *) hi->hi_key); \
|
||||
msgpack_pack_str(spacker, key_len); \
|
||||
msgpack_pack_str_body(spacker, (const char *) hi->hi_key, key_len); \
|
||||
if (vim_to_msgpack(spacker, &di->di_tv, \
|
||||
_("additional data of ShaDa " what)) == FAIL) { \
|
||||
if (encode_vim_to_msgpack(spacker, &di->di_tv, \
|
||||
_("additional data of ShaDa " what)) \
|
||||
== FAIL) { \
|
||||
goto shada_pack_entry_error; \
|
||||
} \
|
||||
} \
|
||||
|
@ -1757,7 +1757,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
|
|||
char vardesc[256] = "variable g:";
|
||||
memcpy(&vardesc[sizeof("variable g:") - 1], varname.data,
|
||||
varname.size + 1);
|
||||
if (vim_to_msgpack(spacker, &entry.data.global_var.value, vardesc)
|
||||
if (encode_vim_to_msgpack(spacker, &entry.data.global_var.value, vardesc)
|
||||
== FAIL) {
|
||||
ret = kSDWriteIgnError;
|
||||
EMSG2(_(WERR "Failed to write variable %s"),
|
||||
|
@ -2159,7 +2159,7 @@ shada_parse_msgpack_read_next: {}
|
|||
break;
|
||||
}
|
||||
case MSGPACK_UNPACK_PARSE_ERROR: {
|
||||
emsgu(_(RCERR "Failed to parse ShaDa file due to a msgpack parser error "
|
||||
emsgf(_(RCERR "Failed to parse ShaDa file due to a msgpack parser error "
|
||||
"at position %" PRIu64),
|
||||
(uint64_t) initial_fpos);
|
||||
ret = kSDReadStatusNotShaDa;
|
||||
|
@ -2176,7 +2176,7 @@ shada_parse_msgpack_read_next: {}
|
|||
break;
|
||||
}
|
||||
case MSGPACK_UNPACK_CONTINUE: {
|
||||
emsgu(_(RCERR "Failed to parse ShaDa file: incomplete msgpack string "
|
||||
emsgf(_(RCERR "Failed to parse ShaDa file: incomplete msgpack string "
|
||||
"at position %" PRIu64),
|
||||
(uint64_t) initial_fpos);
|
||||
ret = kSDReadStatusNotShaDa;
|
||||
|
@ -2184,7 +2184,7 @@ shada_parse_msgpack_read_next: {}
|
|||
}
|
||||
case MSGPACK_UNPACK_EXTRA_BYTES: {
|
||||
shada_parse_msgpack_extra_bytes:
|
||||
emsgu(_(RCERR "Failed to parse ShaDa file: extra bytes in msgpack string "
|
||||
emsgf(_(RCERR "Failed to parse ShaDa file: extra bytes in msgpack string "
|
||||
"at position %" PRIu64),
|
||||
(uint64_t) initial_fpos);
|
||||
ret = kSDReadStatusNotShaDa;
|
||||
|
@ -3265,11 +3265,11 @@ static ShaDaReadResult fread_len(ShaDaReadDef *const sd_reader,
|
|||
(void) read_bytes;
|
||||
|
||||
if (sd_reader->error != NULL) {
|
||||
emsg2(_(SERR "System error while reading ShaDa file: %s"),
|
||||
emsgf(_(SERR "System error while reading ShaDa file: %s"),
|
||||
sd_reader->error);
|
||||
return kSDReadStatusReadError;
|
||||
} else if (sd_reader->eof) {
|
||||
emsgu(_(RCERR "Error while reading ShaDa file: "
|
||||
emsgf(_(RCERR "Error while reading ShaDa file: "
|
||||
"last entry specified that it occupies %" PRIu64 " bytes, "
|
||||
"but file ended earlier"),
|
||||
(uint64_t) length);
|
||||
|
@ -3304,11 +3304,11 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader,
|
|||
|
||||
if (first_char == EOF) {
|
||||
if (sd_reader->error) {
|
||||
emsg2(_(SERR "System error while reading integer from ShaDa file: %s"),
|
||||
emsgf(_(SERR "System error while reading integer from ShaDa file: %s"),
|
||||
sd_reader->error);
|
||||
return kSDReadStatusReadError;
|
||||
} else if (sd_reader->eof) {
|
||||
emsgu(_(RCERR "Error while reading ShaDa file: "
|
||||
emsgf(_(RCERR "Error while reading ShaDa file: "
|
||||
"expected positive integer at position %" PRIu64
|
||||
", but got nothing"),
|
||||
(uint64_t) fpos);
|
||||
|
@ -3339,7 +3339,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader,
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
emsgu(_(RCERR "Error while reading ShaDa file: "
|
||||
emsgf(_(RCERR "Error while reading ShaDa file: "
|
||||
"expected positive integer at position %" PRIu64),
|
||||
(uint64_t) fpos);
|
||||
return kSDReadStatusNotShaDa;
|
||||
|
@ -3403,18 +3403,18 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv,
|
|||
proc) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
emsgu(_(READERR(entry_name, error_desc)), initial_fpos); \
|
||||
emsgf(_(READERR(entry_name, error_desc)), initial_fpos); \
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga); \
|
||||
} \
|
||||
tgt = proc(obj.via.attr); \
|
||||
} while (0)
|
||||
#define CHECK_KEY_IS_STR(entry_name) \
|
||||
if (unpacked.data.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR) { \
|
||||
emsgu(_(READERR(entry_name, "has key which is not a string")), \
|
||||
emsgf(_(READERR(entry_name, "has key which is not a string")), \
|
||||
initial_fpos); \
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga); \
|
||||
} else if (unpacked.data.via.map.ptr[i].key.via.str.size == 0) { \
|
||||
emsgu(_(READERR(entry_name, "has empty key")), initial_fpos); \
|
||||
emsgf(_(READERR(entry_name, "has empty key")), initial_fpos); \
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga); \
|
||||
}
|
||||
#define CHECKED_KEY(entry_name, name, error_desc, tgt, condition, attr, proc) \
|
||||
|
@ -3477,7 +3477,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv,
|
|||
typval_T adtv; \
|
||||
if (msgpack_to_vim(obj, &adtv) == FAIL \
|
||||
|| adtv.v_type != VAR_DICT) { \
|
||||
emsgu(_(READERR(name, \
|
||||
emsgf(_(READERR(name, \
|
||||
"cannot be converted to a VimL dictionary")), \
|
||||
initial_fpos); \
|
||||
ga_clear(&ad_ga); \
|
||||
|
@ -3502,7 +3502,7 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv,
|
|||
}; \
|
||||
typval_T aetv; \
|
||||
if (msgpack_to_vim(obj, &aetv) == FAIL) { \
|
||||
emsgu(_(READERR(name, "cannot be converted to a VimL list")), \
|
||||
emsgf(_(READERR(name, "cannot be converted to a VimL list")), \
|
||||
initial_fpos); \
|
||||
clear_tv(&aetv); \
|
||||
goto shada_read_next_item_error; \
|
||||
|
@ -3570,7 +3570,7 @@ shada_read_next_item_start:
|
|||
// kSDItemUnknown cannot possibly pass that far because it is -1 and that
|
||||
// will fail in msgpack_read_uint64. But kSDItemMissing may and it will
|
||||
// otherwise be skipped because (1 << 0) will never appear in flags.
|
||||
emsgu(_(RCERR "Error while reading ShaDa file: "
|
||||
emsgf(_(RCERR "Error while reading ShaDa file: "
|
||||
"there is an item at position %" PRIu64 " "
|
||||
"that must not be there: Missing items are "
|
||||
"for internal uses only"),
|
||||
|
@ -3640,14 +3640,14 @@ shada_read_next_item_start:
|
|||
switch ((ShadaEntryType) type_u64) {
|
||||
case kSDItemHeader: {
|
||||
if (!msgpack_rpc_to_dictionary(&(unpacked.data), &(entry->data.header))) {
|
||||
emsgu(_(READERR("header", "is not a dictionary")), initial_fpos);
|
||||
emsgf(_(READERR("header", "is not a dictionary")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSDItemSearchPattern: {
|
||||
if (unpacked.data.type != MSGPACK_OBJECT_MAP) {
|
||||
emsgu(_(READERR("search pattern", "is not a dictionary")),
|
||||
emsgf(_(READERR("search pattern", "is not a dictionary")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
|
@ -3678,7 +3678,7 @@ shada_read_next_item_start:
|
|||
ADDITIONAL_KEY
|
||||
}
|
||||
if (entry->data.search_pattern.pat == NULL) {
|
||||
emsgu(_(READERR("search pattern", "has no pattern")), initial_fpos);
|
||||
emsgf(_(READERR("search pattern", "has no pattern")), initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
SET_ADDITIONAL_DATA(entry->data.search_pattern.additional_data,
|
||||
|
@ -3690,7 +3690,7 @@ shada_read_next_item_start:
|
|||
case kSDItemGlobalMark:
|
||||
case kSDItemLocalMark: {
|
||||
if (unpacked.data.type != MSGPACK_OBJECT_MAP) {
|
||||
emsgu(_(READERR("mark", "is not a dictionary")), initial_fpos);
|
||||
emsgf(_(READERR("mark", "is not a dictionary")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
garray_T ad_ga;
|
||||
|
@ -3699,7 +3699,7 @@ shada_read_next_item_start:
|
|||
CHECK_KEY_IS_STR("mark")
|
||||
if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, KEY_NAME_CHAR)) {
|
||||
if (type_u64 == kSDItemJump || type_u64 == kSDItemChange) {
|
||||
emsgu(_(READERR("mark", "has n key which is only valid for "
|
||||
emsgf(_(READERR("mark", "has n key which is only valid for "
|
||||
"local and global mark entries")), initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
|
@ -3716,15 +3716,15 @@ shada_read_next_item_start:
|
|||
ADDITIONAL_KEY
|
||||
}
|
||||
if (entry->data.filemark.fname == NULL) {
|
||||
emsgu(_(READERR("mark", "is missing file name")), initial_fpos);
|
||||
emsgf(_(READERR("mark", "is missing file name")), initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
if (entry->data.filemark.mark.lnum <= 0) {
|
||||
emsgu(_(READERR("mark", "has invalid line number")), initial_fpos);
|
||||
emsgf(_(READERR("mark", "has invalid line number")), initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
if (entry->data.filemark.mark.col < 0) {
|
||||
emsgu(_(READERR("mark", "has invalid column number")), initial_fpos);
|
||||
emsgf(_(READERR("mark", "has invalid column number")), initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
SET_ADDITIONAL_DATA(entry->data.filemark.additional_data, "mark");
|
||||
|
@ -3732,7 +3732,7 @@ shada_read_next_item_start:
|
|||
}
|
||||
case kSDItemRegister: {
|
||||
if (unpacked.data.type != MSGPACK_OBJECT_MAP) {
|
||||
emsgu(_(READERR("register", "is not a dictionary")), initial_fpos);
|
||||
emsgf(_(READERR("register", "is not a dictionary")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
garray_T ad_ga;
|
||||
|
@ -3742,14 +3742,14 @@ shada_read_next_item_start:
|
|||
if (CHECK_KEY(unpacked.data.via.map.ptr[i].key,
|
||||
REG_KEY_CONTENTS)) {
|
||||
if (unpacked.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) {
|
||||
emsgu(_(READERR("register",
|
||||
emsgf(_(READERR("register",
|
||||
"has " REG_KEY_CONTENTS
|
||||
" key with non-array value")),
|
||||
initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
if (unpacked.data.via.map.ptr[i].val.via.array.size == 0) {
|
||||
emsgu(_(READERR("register",
|
||||
emsgf(_(READERR("register",
|
||||
"has " REG_KEY_CONTENTS " key with empty array")),
|
||||
initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
|
@ -3758,7 +3758,7 @@ shada_read_next_item_start:
|
|||
unpacked.data.via.map.ptr[i].val.via.array;
|
||||
for (size_t i = 0; i < arr.size; i++) {
|
||||
if (arr.ptr[i].type != MSGPACK_OBJECT_BIN) {
|
||||
emsgu(_(READERR("register", "has " REG_KEY_CONTENTS " array "
|
||||
emsgf(_(READERR("register", "has " REG_KEY_CONTENTS " array "
|
||||
"with non-binary value")), initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
|
@ -3778,7 +3778,7 @@ shada_read_next_item_start:
|
|||
ADDITIONAL_KEY
|
||||
}
|
||||
if (entry->data.reg.contents == NULL) {
|
||||
emsgu(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")),
|
||||
emsgf(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")),
|
||||
initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
|
@ -3787,29 +3787,29 @@ shada_read_next_item_start:
|
|||
}
|
||||
case kSDItemHistoryEntry: {
|
||||
if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) {
|
||||
emsgu(_(READERR("history", "is not an array")), initial_fpos);
|
||||
emsgf(_(READERR("history", "is not an array")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.size < 2) {
|
||||
emsgu(_(READERR("history", "does not have enough elements")),
|
||||
emsgf(_(READERR("history", "does not have enough elements")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.ptr[0].type
|
||||
!= MSGPACK_OBJECT_POSITIVE_INTEGER) {
|
||||
emsgu(_(READERR("history", "has wrong history type type")),
|
||||
emsgf(_(READERR("history", "has wrong history type type")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.ptr[1].type
|
||||
!= MSGPACK_OBJECT_BIN) {
|
||||
emsgu(_(READERR("history", "has wrong history string type")),
|
||||
emsgf(_(READERR("history", "has wrong history string type")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (memchr(unpacked.data.via.array.ptr[1].via.bin.ptr, 0,
|
||||
unpacked.data.via.array.ptr[1].via.bin.size) != NULL) {
|
||||
emsgu(_(READERR("history", "contains string with zero byte inside")),
|
||||
emsgf(_(READERR("history", "contains string with zero byte inside")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
|
@ -3819,13 +3819,13 @@ shada_read_next_item_start:
|
|||
entry->data.history_item.histtype == HIST_SEARCH;
|
||||
if (is_hist_search) {
|
||||
if (unpacked.data.via.array.size < 3) {
|
||||
emsgu(_(READERR("search history",
|
||||
emsgf(_(READERR("search history",
|
||||
"does not have separator character")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.ptr[2].type
|
||||
!= MSGPACK_OBJECT_POSITIVE_INTEGER) {
|
||||
emsgu(_(READERR("search history",
|
||||
emsgf(_(READERR("search history",
|
||||
"has wrong history separator type")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
|
@ -3867,22 +3867,16 @@ shada_read_next_item_hist_no_conv:
|
|||
}
|
||||
case kSDItemVariable: {
|
||||
if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) {
|
||||
emsgu(_(READERR("variable", "is not an array")), initial_fpos);
|
||||
emsgf(_(READERR("variable", "is not an array")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.size < 2) {
|
||||
emsgu(_(READERR("variable", "does not have enough elements")),
|
||||
emsgf(_(READERR("variable", "does not have enough elements")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.ptr[0].type != MSGPACK_OBJECT_BIN) {
|
||||
emsgu(_(READERR("variable", "has wrong variable name type")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.ptr[1].type == MSGPACK_OBJECT_NIL
|
||||
|| unpacked.data.via.array.ptr[1].type == MSGPACK_OBJECT_EXT) {
|
||||
emsgu(_(READERR("variable", "has wrong variable value type")),
|
||||
emsgf(_(READERR("variable", "has wrong variable name type")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
|
@ -3891,7 +3885,7 @@ shada_read_next_item_hist_no_conv:
|
|||
unpacked.data.via.array.ptr[0].via.bin.size);
|
||||
if (msgpack_to_vim(unpacked.data.via.array.ptr[1],
|
||||
&(entry->data.global_var.value)) == FAIL) {
|
||||
emsgu(_(READERR("variable", "has value that cannot "
|
||||
emsgf(_(READERR("variable", "has value that cannot "
|
||||
"be converted to the VimL value")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
|
@ -3912,16 +3906,16 @@ shada_read_next_item_hist_no_conv:
|
|||
}
|
||||
case kSDItemSubString: {
|
||||
if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) {
|
||||
emsgu(_(READERR("sub string", "is not an array")), initial_fpos);
|
||||
emsgf(_(READERR("sub string", "is not an array")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.size < 1) {
|
||||
emsgu(_(READERR("sub string", "does not have enough elements")),
|
||||
emsgf(_(READERR("sub string", "does not have enough elements")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.ptr[0].type != MSGPACK_OBJECT_BIN) {
|
||||
emsgu(_(READERR("sub string", "has wrong sub string type")),
|
||||
emsgf(_(READERR("sub string", "has wrong sub string type")),
|
||||
initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
|
@ -3934,7 +3928,7 @@ shada_read_next_item_hist_no_conv:
|
|||
}
|
||||
case kSDItemBufferList: {
|
||||
if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) {
|
||||
emsgu(_(READERR("buffer list", "is not an array")), initial_fpos);
|
||||
emsgf(_(READERR("buffer list", "is not an array")), initial_fpos);
|
||||
goto shada_read_next_item_error;
|
||||
}
|
||||
if (unpacked.data.via.array.size == 0) {
|
||||
|
@ -3951,7 +3945,7 @@ shada_read_next_item_hist_no_conv:
|
|||
{
|
||||
msgpack_unpacked unpacked = unpacked_2;
|
||||
if (unpacked.data.type != MSGPACK_OBJECT_MAP) {
|
||||
emsgu(_(RERR "Error while reading ShaDa file: "
|
||||
emsgf(_(RERR "Error while reading ShaDa file: "
|
||||
"buffer list at position %" PRIu64 " "
|
||||
"contains entry that is not a dictionary"),
|
||||
initial_fpos);
|
||||
|
@ -3976,21 +3970,21 @@ shada_read_next_item_hist_no_conv:
|
|||
}
|
||||
}
|
||||
if (entry->data.buffer_list.buffers[i].pos.lnum <= 0) {
|
||||
emsgu(_(RERR "Error while reading ShaDa file: "
|
||||
emsgf(_(RERR "Error while reading ShaDa file: "
|
||||
"buffer list at position %" PRIu64 " "
|
||||
"contains entry with invalid line number"),
|
||||
initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
if (entry->data.buffer_list.buffers[i].pos.col < 0) {
|
||||
emsgu(_(RERR "Error while reading ShaDa file: "
|
||||
emsgf(_(RERR "Error while reading ShaDa file: "
|
||||
"buffer list at position %" PRIu64 " "
|
||||
"contains entry with invalid column number"),
|
||||
initial_fpos);
|
||||
CLEAR_GA_AND_ERROR_OUT(ad_ga);
|
||||
}
|
||||
if (entry->data.buffer_list.buffers[i].fname == NULL) {
|
||||
emsgu(_(RERR "Error while reading ShaDa file: "
|
||||
emsgf(_(RERR "Error while reading ShaDa file: "
|
||||
"buffer list at position %" PRIu64 " "
|
||||
"contains entry that does not have a file name"),
|
||||
initial_fpos);
|
||||
|
|
|
@ -872,7 +872,7 @@ do_tag (
|
|||
|
||||
/* Let the SwapExists event know what tag we are jumping to. */
|
||||
vim_snprintf((char *)IObuff, IOSIZE, ":ta %s\r", name);
|
||||
set_vim_var_string(VV_SWAPCOMMAND, IObuff, -1);
|
||||
set_vim_var_string(VV_SWAPCOMMAND, (char *) IObuff, -1);
|
||||
|
||||
/*
|
||||
* Jump to the desired match.
|
||||
|
|
|
@ -627,6 +627,7 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
|
|||
api_free_object(dict_set_value(buf->b_vars,
|
||||
cstr_as_string("term_title"),
|
||||
STRING_OBJ(cstr_as_string(val->string)),
|
||||
false,
|
||||
&err));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -78,24 +78,26 @@ static int included_patches[] = {
|
|||
1511,
|
||||
1425,
|
||||
1366,
|
||||
1304,
|
||||
1292,
|
||||
1284,
|
||||
// 1283
|
||||
1282,
|
||||
// 1281
|
||||
// 1280
|
||||
// 1279
|
||||
// 1278
|
||||
// 1279 NA
|
||||
// 1278 NA
|
||||
// 1277
|
||||
// 1276
|
||||
// 1275
|
||||
// 1274
|
||||
// 1273
|
||||
// 1272
|
||||
// 1271
|
||||
1271,
|
||||
// 1270
|
||||
// 1269
|
||||
1269,
|
||||
// 1268
|
||||
// 1267
|
||||
1267,
|
||||
// 1266
|
||||
// 1265
|
||||
// 1264
|
||||
|
@ -119,7 +121,7 @@ static int included_patches[] = {
|
|||
// 1246
|
||||
// 1245
|
||||
// 1244
|
||||
// 1243
|
||||
// 1243 NA
|
||||
// 1242
|
||||
// 1241
|
||||
// 1240
|
||||
|
@ -131,10 +133,10 @@ static int included_patches[] = {
|
|||
// 1234
|
||||
// 1233
|
||||
// 1232
|
||||
// 1231
|
||||
// 1231 NA
|
||||
// 1230
|
||||
// 1229
|
||||
// 1228
|
||||
1228,
|
||||
// 1227
|
||||
// 1226
|
||||
// 1225
|
||||
|
@ -181,32 +183,32 @@ static int included_patches[] = {
|
|||
// 1184 NA
|
||||
// 1183 NA
|
||||
// 1182 NA
|
||||
// 1181,
|
||||
1181,
|
||||
1180,
|
||||
// 1179,
|
||||
// 1178,
|
||||
1178,
|
||||
// 1177 NA
|
||||
// 1176 NA
|
||||
// 1175 NA
|
||||
// 1174 NA
|
||||
// 1173,
|
||||
1173,
|
||||
// 1172 NA
|
||||
// 1171 NA
|
||||
// 1170 NA
|
||||
// 1169 NA
|
||||
// 1168,
|
||||
// 1167,
|
||||
// 1166,
|
||||
1168,
|
||||
1167,
|
||||
1166,
|
||||
// 1165 NA
|
||||
// 1164,
|
||||
// 1163,
|
||||
1164,
|
||||
1163,
|
||||
// 1162 NA
|
||||
// 1161,
|
||||
// 1160,
|
||||
1160,
|
||||
// 1159 NA
|
||||
// 1158 NA
|
||||
// 1157,
|
||||
// 1156,
|
||||
1157,
|
||||
// 1156 NA
|
||||
// 1155 NA
|
||||
// 1154,
|
||||
// 1153,
|
||||
|
|
|
@ -271,26 +271,11 @@ enum {
|
|||
|
||||
# define vim_strpbrk(s, cs) (char_u *)strpbrk((char *)(s), (char *)(cs))
|
||||
|
||||
#define MSG(s) msg((char_u *)(s))
|
||||
#define MSG_ATTR(s, attr) msg_attr((char_u *)(s), (attr))
|
||||
#define EMSG(s) emsg((char_u *)(s))
|
||||
#define EMSG2(s, p) emsg2((char_u *)(s), (char_u *)(p))
|
||||
#define EMSG3(s, p, q) emsg3((char_u *)(s), (char_u *)(p), \
|
||||
(char_u *)(q))
|
||||
#define EMSGN(s, n) emsgn((char_u *)(s), (int64_t)(n))
|
||||
#define EMSGU(s, n) emsgu((char_u *)(s), (uint64_t)(n))
|
||||
#define OUT_STR(s) out_str((char_u *)(s))
|
||||
#define OUT_STR_NF(s) out_str_nf((char_u *)(s))
|
||||
#define MSG_PUTS(s) msg_puts((char_u *)(s))
|
||||
#define MSG_PUTS_ATTR(s, a) msg_puts_attr((char_u *)(s), (a))
|
||||
#define MSG_PUTS_TITLE(s) msg_puts_title((char_u *)(s))
|
||||
#define MSG_PUTS_LONG(s) msg_puts_long_attr((char_u *)(s), 0)
|
||||
#define MSG_PUTS_LONG_ATTR(s, a) msg_puts_long_attr((char_u *)(s), (a))
|
||||
#include "nvim/message.h"
|
||||
|
||||
/* Prefer using emsg3(), because perror() may send the output to the wrong
|
||||
* destination and mess up the screen. */
|
||||
#define PERROR(msg) \
|
||||
(void) emsg3((char_u *) "%s: %s", (char_u *)msg, (char_u *)strerror(errno))
|
||||
// Prefer using emsgf(), because perror() may send the output to the wrong
|
||||
// destination and mess up the screen.
|
||||
#define PERROR(msg) (void) emsgf("%s: %s", msg, strerror(errno))
|
||||
|
||||
#define SHOWCMD_COLS 10 /* columns needed by shown command */
|
||||
#define STL_MAX_ITEM 80 /* max nr of %<flag> in statusline */
|
||||
|
|
|
@ -3,6 +3,7 @@ local helpers = require('test.functional.helpers')
|
|||
local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer
|
||||
local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq
|
||||
local curbufmeths, ok = helpers.curbufmeths, helpers.ok
|
||||
local funcs = helpers.funcs
|
||||
|
||||
describe('buffer_* functions', function()
|
||||
before_each(clear)
|
||||
|
@ -234,11 +235,14 @@ describe('buffer_* functions', function()
|
|||
|
||||
end)
|
||||
|
||||
describe('{get,set}_var', function()
|
||||
describe('{get,set,del}_var', function()
|
||||
it('works', function()
|
||||
curbuf('set_var', 'lua', {1, 2, {['3'] = 1}})
|
||||
eq({1, 2, {['3'] = 1}}, curbuf('get_var', 'lua'))
|
||||
eq({1, 2, {['3'] = 1}}, nvim('eval', 'b:lua'))
|
||||
eq(1, funcs.exists('b:lua'))
|
||||
curbufmeths.del_var('lua')
|
||||
eq(0, funcs.exists('b:lua'))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@ local helpers = require('test.functional.helpers')
|
|||
local clear, nvim, tabpage, curtab, eq, ok =
|
||||
helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq,
|
||||
helpers.ok
|
||||
local wait = helpers.wait
|
||||
local curtabmeths = helpers.curtabmeths
|
||||
local funcs = helpers.funcs
|
||||
|
||||
describe('tabpage_* functions', function()
|
||||
before_each(clear)
|
||||
|
@ -21,11 +24,14 @@ describe('tabpage_* functions', function()
|
|||
end)
|
||||
end)
|
||||
|
||||
describe('{get,set}_var', function()
|
||||
describe('{get,set,del}_var', function()
|
||||
it('works', function()
|
||||
curtab('set_var', 'lua', {1, 2, {['3'] = 1}})
|
||||
eq({1, 2, {['3'] = 1}}, curtab('get_var', 'lua'))
|
||||
eq({1, 2, {['3'] = 1}}, nvim('eval', 't:lua'))
|
||||
eq(1, funcs.exists('t:lua'))
|
||||
curtabmeths.del_var('lua')
|
||||
eq(0, funcs.exists('t:lua'))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ local Screen = require('test.functional.ui.screen')
|
|||
local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq
|
||||
local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed
|
||||
local os_name = helpers.os_name
|
||||
local meths = helpers.meths
|
||||
local funcs = helpers.funcs
|
||||
|
||||
describe('vim_* functions', function()
|
||||
before_each(clear)
|
||||
|
@ -70,11 +72,14 @@ describe('vim_* functions', function()
|
|||
end)
|
||||
end)
|
||||
|
||||
describe('{get,set}_var', function()
|
||||
describe('{get,set,del}_var', function()
|
||||
it('works', function()
|
||||
nvim('set_var', 'lua', {1, 2, {['3'] = 1}})
|
||||
eq({1, 2, {['3'] = 1}}, nvim('get_var', 'lua'))
|
||||
eq({1, 2, {['3'] = 1}}, nvim('eval', 'g:lua'))
|
||||
eq(1, funcs.exists('g:lua'))
|
||||
meths.del_var('lua')
|
||||
eq(0, funcs.exists('g:lua'))
|
||||
end)
|
||||
|
||||
it('set_var returns the old value', function()
|
||||
|
@ -84,6 +89,14 @@ describe('vim_* functions', function()
|
|||
eq(val1, nvim('set_var', 'lua', val2))
|
||||
end)
|
||||
|
||||
it('del_var returns the old value', function()
|
||||
local val1 = {1, 2, {['3'] = 1}}
|
||||
local val2 = {4, 7}
|
||||
eq(NIL, meths.set_var('lua', val1))
|
||||
eq(val1, meths.set_var('lua', val2))
|
||||
eq(val2, meths.del_var('lua'))
|
||||
end)
|
||||
|
||||
it('truncates values with NULs in them', function()
|
||||
nvim('set_var', 'xxx', 'ab\0cd')
|
||||
eq('ab', nvim('get_var', 'xxx'))
|
||||
|
|
|
@ -5,6 +5,8 @@ local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq,
|
|||
helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq,
|
||||
helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval
|
||||
local wait = helpers.wait
|
||||
local curwinmeths = helpers.curwinmeths
|
||||
local funcs = helpers.funcs
|
||||
|
||||
-- check if str is visible at the beginning of some line
|
||||
local function is_visible(str)
|
||||
|
@ -126,11 +128,14 @@ describe('window_* functions', function()
|
|||
end)
|
||||
end)
|
||||
|
||||
describe('{get,set}_var', function()
|
||||
describe('{get,set,del}_var', function()
|
||||
it('works', function()
|
||||
curwin('set_var', 'lua', {1, 2, {['3'] = 1}})
|
||||
eq({1, 2, {['3'] = 1}}, curwin('get_var', 'lua'))
|
||||
eq({1, 2, {['3'] = 1}}, nvim('eval', 'w:lua'))
|
||||
eq(1, funcs.exists('w:lua'))
|
||||
curwinmeths.del_var('lua')
|
||||
eq(0, funcs.exists('w:lua'))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
|
|
@ -0,0 +1,799 @@
|
|||
local helpers = require('test.functional.helpers')
|
||||
local clear = helpers.clear
|
||||
local funcs = helpers.funcs
|
||||
local meths = helpers.meths
|
||||
local eq = helpers.eq
|
||||
local eval = helpers.eval
|
||||
local execute = helpers.execute
|
||||
local exc_exec = helpers.exc_exec
|
||||
local redir_exec = helpers.redir_exec
|
||||
|
||||
describe('json_decode() function', function()
|
||||
local restart = function(cmd)
|
||||
clear(cmd)
|
||||
execute('language C')
|
||||
execute([[
|
||||
function Eq(exp, act)
|
||||
let act = a:act
|
||||
let exp = a:exp
|
||||
if type(exp) != type(act)
|
||||
return 0
|
||||
endif
|
||||
if type(exp) == type({})
|
||||
if sort(keys(exp)) !=# sort(keys(act))
|
||||
return 0
|
||||
endif
|
||||
if sort(keys(exp)) ==# ['_TYPE', '_VAL']
|
||||
let exp_typ = v:msgpack_types[exp._TYPE]
|
||||
let act_typ = act._TYPE
|
||||
if exp_typ isnot act_typ
|
||||
return 0
|
||||
endif
|
||||
return Eq(exp._VAL, act._VAL)
|
||||
else
|
||||
return empty(filter(copy(exp), '!Eq(v:val, act[v:key])'))
|
||||
endif
|
||||
else
|
||||
if type(exp) == type([])
|
||||
if len(exp) != len(act)
|
||||
return 0
|
||||
endif
|
||||
return empty(filter(copy(exp), '!Eq(v:val, act[v:key])'))
|
||||
endif
|
||||
return exp ==# act
|
||||
endif
|
||||
return 1
|
||||
endfunction
|
||||
]])
|
||||
execute([[
|
||||
function EvalEq(exp, act_expr)
|
||||
let act = eval(a:act_expr)
|
||||
if Eq(a:exp, act)
|
||||
return 1
|
||||
else
|
||||
return string(act)
|
||||
endif
|
||||
endfunction
|
||||
]])
|
||||
end
|
||||
before_each(restart)
|
||||
|
||||
local speq = function(expected, actual_expr)
|
||||
eq(1, funcs.EvalEq(expected, actual_expr))
|
||||
end
|
||||
|
||||
it('accepts readfile()-style list', function()
|
||||
eq({Test=1}, funcs.json_decode({
|
||||
'{',
|
||||
'\t"Test": 1',
|
||||
'}',
|
||||
}))
|
||||
end)
|
||||
|
||||
it('accepts strings with newlines', function()
|
||||
eq({Test=1}, funcs.json_decode([[
|
||||
{
|
||||
"Test": 1
|
||||
}
|
||||
]]))
|
||||
end)
|
||||
|
||||
it('parses null, true, false', function()
|
||||
eq(NIL, funcs.json_decode('null'))
|
||||
eq(true, funcs.json_decode('true'))
|
||||
eq(false, funcs.json_decode('false'))
|
||||
end)
|
||||
|
||||
it('fails to parse incomplete null, true, false', function()
|
||||
eq('Vim(call):E474: Expected null: n',
|
||||
exc_exec('call json_decode("n")'))
|
||||
eq('Vim(call):E474: Expected null: nu',
|
||||
exc_exec('call json_decode("nu")'))
|
||||
eq('Vim(call):E474: Expected null: nul',
|
||||
exc_exec('call json_decode("nul")'))
|
||||
eq('Vim(call):E474: Expected null: nul\n\t',
|
||||
exc_exec('call json_decode("nul\\n\\t")'))
|
||||
|
||||
eq('Vim(call):E474: Expected true: t',
|
||||
exc_exec('call json_decode("t")'))
|
||||
eq('Vim(call):E474: Expected true: tr',
|
||||
exc_exec('call json_decode("tr")'))
|
||||
eq('Vim(call):E474: Expected true: tru',
|
||||
exc_exec('call json_decode("tru")'))
|
||||
eq('Vim(call):E474: Expected true: tru\t\n',
|
||||
exc_exec('call json_decode("tru\\t\\n")'))
|
||||
|
||||
eq('Vim(call):E474: Expected false: f',
|
||||
exc_exec('call json_decode("f")'))
|
||||
eq('Vim(call):E474: Expected false: fa',
|
||||
exc_exec('call json_decode("fa")'))
|
||||
eq('Vim(call):E474: Expected false: fal',
|
||||
exc_exec('call json_decode("fal")'))
|
||||
eq('Vim(call):E474: Expected false: fal <',
|
||||
exc_exec('call json_decode(" fal <")'))
|
||||
eq('Vim(call):E474: Expected false: fals',
|
||||
exc_exec('call json_decode("fals")'))
|
||||
end)
|
||||
|
||||
it('parses integer numbers', function()
|
||||
eq(100000, funcs.json_decode('100000'))
|
||||
eq(-100000, funcs.json_decode('-100000'))
|
||||
eq(100000, funcs.json_decode(' 100000 '))
|
||||
eq(-100000, funcs.json_decode(' -100000 '))
|
||||
eq(0, funcs.json_decode('0'))
|
||||
eq(0, funcs.json_decode('-0'))
|
||||
end)
|
||||
|
||||
it('fails to parse +numbers and .number', function()
|
||||
eq('Vim(call):E474: Unidentified byte: +1000',
|
||||
exc_exec('call json_decode("+1000")'))
|
||||
eq('Vim(call):E474: Unidentified byte: .1000',
|
||||
exc_exec('call json_decode(".1000")'))
|
||||
end)
|
||||
|
||||
it('fails to parse numbers with leading zeroes', function()
|
||||
eq('Vim(call):E474: Leading zeroes are not allowed: 00.1',
|
||||
exc_exec('call json_decode("00.1")'))
|
||||
eq('Vim(call):E474: Leading zeroes are not allowed: 01',
|
||||
exc_exec('call json_decode("01")'))
|
||||
eq('Vim(call):E474: Leading zeroes are not allowed: -01',
|
||||
exc_exec('call json_decode("-01")'))
|
||||
eq('Vim(call):E474: Leading zeroes are not allowed: -001.0',
|
||||
exc_exec('call json_decode("-001.0")'))
|
||||
end)
|
||||
|
||||
it('fails to parse incomplete numbers', function()
|
||||
eq('Vim(call):E474: Missing number after minus sign: -.1',
|
||||
exc_exec('call json_decode("-.1")'))
|
||||
eq('Vim(call):E474: Missing number after minus sign: -',
|
||||
exc_exec('call json_decode("-")'))
|
||||
eq('Vim(call):E474: Missing number after decimal dot: -1.',
|
||||
exc_exec('call json_decode("-1.")'))
|
||||
eq('Vim(call):E474: Missing number after decimal dot: 0.',
|
||||
exc_exec('call json_decode("0.")'))
|
||||
eq('Vim(call):E474: Missing exponent: 0.0e',
|
||||
exc_exec('call json_decode("0.0e")'))
|
||||
eq('Vim(call):E474: Missing exponent: 0.0e+',
|
||||
exc_exec('call json_decode("0.0e+")'))
|
||||
eq('Vim(call):E474: Missing exponent: 0.0e-',
|
||||
exc_exec('call json_decode("0.0e-")'))
|
||||
eq('Vim(call):E474: Missing exponent: 0.0e-',
|
||||
exc_exec('call json_decode("0.0e-")'))
|
||||
eq('Vim(call):E474: Missing number after decimal dot: 1.e5',
|
||||
exc_exec('call json_decode("1.e5")'))
|
||||
eq('Vim(call):E474: Missing number after decimal dot: 1.e+5',
|
||||
exc_exec('call json_decode("1.e+5")'))
|
||||
eq('Vim(call):E474: Missing number after decimal dot: 1.e+',
|
||||
exc_exec('call json_decode("1.e+")'))
|
||||
end)
|
||||
|
||||
it('parses floating-point numbers', function()
|
||||
eq('100000.0', eval('string(json_decode("100000.0"))'))
|
||||
eq(100000.5, funcs.json_decode('100000.5'))
|
||||
eq(-100000.5, funcs.json_decode('-100000.5'))
|
||||
eq(-100000.5e50, funcs.json_decode('-100000.5e50'))
|
||||
eq(100000.5e50, funcs.json_decode('100000.5e50'))
|
||||
eq(100000.5e50, funcs.json_decode('100000.5e+50'))
|
||||
eq(-100000.5e-50, funcs.json_decode('-100000.5e-50'))
|
||||
eq(100000.5e-50, funcs.json_decode('100000.5e-50'))
|
||||
eq(100000e-50, funcs.json_decode('100000e-50'))
|
||||
eq(0.5, funcs.json_decode('0.5'))
|
||||
eq(0.005, funcs.json_decode('0.005'))
|
||||
eq(0.005, funcs.json_decode('0.00500'))
|
||||
eq(0.5, funcs.json_decode('0.00500e+002'))
|
||||
eq(0.00005, funcs.json_decode('0.00500e-002'))
|
||||
|
||||
eq(-0.0, funcs.json_decode('-0.0'))
|
||||
eq(-0.0, funcs.json_decode('-0.0e0'))
|
||||
eq(-0.0, funcs.json_decode('-0.0e+0'))
|
||||
eq(-0.0, funcs.json_decode('-0.0e-0'))
|
||||
eq(-0.0, funcs.json_decode('-0e-0'))
|
||||
eq(-0.0, funcs.json_decode('-0e-2'))
|
||||
eq(-0.0, funcs.json_decode('-0e+2'))
|
||||
|
||||
eq(0.0, funcs.json_decode('0.0'))
|
||||
eq(0.0, funcs.json_decode('0.0e0'))
|
||||
eq(0.0, funcs.json_decode('0.0e+0'))
|
||||
eq(0.0, funcs.json_decode('0.0e-0'))
|
||||
eq(0.0, funcs.json_decode('0e-0'))
|
||||
eq(0.0, funcs.json_decode('0e-2'))
|
||||
eq(0.0, funcs.json_decode('0e+2'))
|
||||
end)
|
||||
|
||||
it('fails to parse numbers with spaces inside', function()
|
||||
eq('Vim(call):E474: Missing number after minus sign: - 1000',
|
||||
exc_exec('call json_decode("- 1000")'))
|
||||
eq('Vim(call):E474: Missing number after decimal dot: 0. ',
|
||||
exc_exec('call json_decode("0. ")'))
|
||||
eq('Vim(call):E474: Missing number after decimal dot: 0. 0',
|
||||
exc_exec('call json_decode("0. 0")'))
|
||||
eq('Vim(call):E474: Missing exponent: 0.0e 1',
|
||||
exc_exec('call json_decode("0.0e 1")'))
|
||||
eq('Vim(call):E474: Missing exponent: 0.0e+ 1',
|
||||
exc_exec('call json_decode("0.0e+ 1")'))
|
||||
eq('Vim(call):E474: Missing exponent: 0.0e- 1',
|
||||
exc_exec('call json_decode("0.0e- 1")'))
|
||||
end)
|
||||
|
||||
it('fails to parse "," and ":"', function()
|
||||
eq('Vim(call):E474: Comma not inside container: , ',
|
||||
exc_exec('call json_decode(" , ")'))
|
||||
eq('Vim(call):E474: Colon not inside container: : ',
|
||||
exc_exec('call json_decode(" : ")'))
|
||||
end)
|
||||
|
||||
it('parses empty containers', function()
|
||||
eq({}, funcs.json_decode('[]'))
|
||||
eq('[]', eval('string(json_decode("[]"))'))
|
||||
end)
|
||||
|
||||
it('fails to parse "[" and "{"', function()
|
||||
eq('Vim(call):E474: Unexpected end of input: {',
|
||||
exc_exec('call json_decode("{")'))
|
||||
eq('Vim(call):E474: Unexpected end of input: [',
|
||||
exc_exec('call json_decode("[")'))
|
||||
end)
|
||||
|
||||
it('fails to parse "}" and "]"', function()
|
||||
eq('Vim(call):E474: No container to close: ]',
|
||||
exc_exec('call json_decode("]")'))
|
||||
eq('Vim(call):E474: No container to close: }',
|
||||
exc_exec('call json_decode("}")'))
|
||||
end)
|
||||
|
||||
it('fails to parse containers which are closed by different brackets',
|
||||
function()
|
||||
eq('Vim(call):E474: Closing dictionary with square bracket: ]',
|
||||
exc_exec('call json_decode("{]")'))
|
||||
eq('Vim(call):E474: Closing list with curly bracket: }',
|
||||
exc_exec('call json_decode("[}")'))
|
||||
end)
|
||||
|
||||
it('fails to parse concat inside container', function()
|
||||
eq('Vim(call):E474: Expected comma before list item: []]',
|
||||
exc_exec('call json_decode("[[][]]")'))
|
||||
eq('Vim(call):E474: Expected comma before list item: {}]',
|
||||
exc_exec('call json_decode("[{}{}]")'))
|
||||
eq('Vim(call):E474: Expected comma before list item: ]',
|
||||
exc_exec('call json_decode("[1 2]")'))
|
||||
eq('Vim(call):E474: Expected comma before dictionary key: ": 4}',
|
||||
exc_exec('call json_decode("{\\"1\\": 2 \\"3\\": 4}")'))
|
||||
eq('Vim(call):E474: Expected colon before dictionary value: , "3" 4}',
|
||||
exc_exec('call json_decode("{\\"1\\" 2, \\"3\\" 4}")'))
|
||||
end)
|
||||
|
||||
it('fails to parse containers with leading comma or colon', function()
|
||||
eq('Vim(call):E474: Leading comma: ,}',
|
||||
exc_exec('call json_decode("{,}")'))
|
||||
eq('Vim(call):E474: Leading comma: ,]',
|
||||
exc_exec('call json_decode("[,]")'))
|
||||
eq('Vim(call):E474: Using colon not in dictionary: :]',
|
||||
exc_exec('call json_decode("[:]")'))
|
||||
eq('Vim(call):E474: Unexpected colon: :}',
|
||||
exc_exec('call json_decode("{:}")'))
|
||||
end)
|
||||
|
||||
it('fails to parse containers with trailing comma', function()
|
||||
eq('Vim(call):E474: Trailing comma: ]',
|
||||
exc_exec('call json_decode("[1,]")'))
|
||||
eq('Vim(call):E474: Trailing comma: }',
|
||||
exc_exec('call json_decode("{\\"1\\": 2,}")'))
|
||||
end)
|
||||
|
||||
it('fails to parse dictionaries with missing value', function()
|
||||
eq('Vim(call):E474: Expected value after colon: }',
|
||||
exc_exec('call json_decode("{\\"1\\":}")'))
|
||||
eq('Vim(call):E474: Expected value: }',
|
||||
exc_exec('call json_decode("{\\"1\\"}")'))
|
||||
end)
|
||||
|
||||
it('fails to parse containers with two commas or colons', function()
|
||||
eq('Vim(call):E474: Duplicate comma: , "2": 2}',
|
||||
exc_exec('call json_decode("{\\"1\\": 1,, \\"2\\": 2}")'))
|
||||
eq('Vim(call):E474: Duplicate comma: , "2", 2]',
|
||||
exc_exec('call json_decode("[\\"1\\", 1,, \\"2\\", 2]")'))
|
||||
eq('Vim(call):E474: Duplicate colon: : 2}',
|
||||
exc_exec('call json_decode("{\\"1\\": 1, \\"2\\":: 2}")'))
|
||||
eq('Vim(call):E474: Comma after colon: , 2}',
|
||||
exc_exec('call json_decode("{\\"1\\": 1, \\"2\\":, 2}")'))
|
||||
eq('Vim(call):E474: Unexpected colon: : "2": 2}',
|
||||
exc_exec('call json_decode("{\\"1\\": 1,: \\"2\\": 2}")'))
|
||||
eq('Vim(call):E474: Unexpected colon: :, "2": 2}',
|
||||
exc_exec('call json_decode("{\\"1\\": 1:, \\"2\\": 2}")'))
|
||||
end)
|
||||
|
||||
it('fails to parse concat of two values', function()
|
||||
eq('Vim(call):E474: Trailing characters: []',
|
||||
exc_exec('call json_decode("{}[]")'))
|
||||
end)
|
||||
|
||||
it('parses containers', function()
|
||||
eq({1}, funcs.json_decode('[1]'))
|
||||
eq({NIL, 1}, funcs.json_decode('[null, 1]'))
|
||||
eq({['1']=2}, funcs.json_decode('{"1": 2}'))
|
||||
eq({['1']=2, ['3']={{['4']={['5']={{}, 1}}}}},
|
||||
funcs.json_decode('{"1": 2, "3": [{"4": {"5": [[], 1]}}]}'))
|
||||
end)
|
||||
|
||||
it('fails to parse incomplete strings', function()
|
||||
eq('Vim(call):E474: Expected string end: \t"',
|
||||
exc_exec('call json_decode("\\t\\"")'))
|
||||
eq('Vim(call):E474: Expected string end: \t"abc',
|
||||
exc_exec('call json_decode("\\t\\"abc")'))
|
||||
eq('Vim(call):E474: Unfinished escape sequence: \t"abc\\',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\")'))
|
||||
eq('Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\u")'))
|
||||
eq('Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u0',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\u0")'))
|
||||
eq('Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u00',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\u00")'))
|
||||
eq('Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u000',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\u000")'))
|
||||
eq('Vim(call):E474: Expected four hex digits after \\u: \\u" ',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\u\\" ")'))
|
||||
eq('Vim(call):E474: Expected four hex digits after \\u: \\u0" ',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\u0\\" ")'))
|
||||
eq('Vim(call):E474: Expected four hex digits after \\u: \\u00" ',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\u00\\" ")'))
|
||||
eq('Vim(call):E474: Expected four hex digits after \\u: \\u000" ',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\u000\\" ")'))
|
||||
eq('Vim(call):E474: Expected string end: \t"abc\\u0000',
|
||||
exc_exec('call json_decode("\\t\\"abc\\\\u0000")'))
|
||||
end)
|
||||
|
||||
it('fails to parse unknown escape sequnces', function()
|
||||
eq('Vim(call):E474: Unknown escape sequence: \\a"',
|
||||
exc_exec('call json_decode("\\t\\"\\\\a\\"")'))
|
||||
end)
|
||||
|
||||
it('parses strings properly', function()
|
||||
eq('\n', funcs.json_decode('"\\n"'))
|
||||
eq('', funcs.json_decode('""'))
|
||||
eq('\\/"\t\b\n\r\f', funcs.json_decode([["\\\/\"\t\b\n\r\f"]]))
|
||||
eq('/a', funcs.json_decode([["\/a"]]))
|
||||
-- Unicode characters: 2-byte, 3-byte, 4-byte
|
||||
eq({
|
||||
'«',
|
||||
'ફ',
|
||||
'\240\144\128\128',
|
||||
}, funcs.json_decode({
|
||||
'[',
|
||||
'"«",',
|
||||
'"ફ",',
|
||||
'"\240\144\128\128"',
|
||||
']',
|
||||
}))
|
||||
end)
|
||||
|
||||
it('fails on strings with invalid bytes', function()
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \255"',
|
||||
exc_exec('call json_decode("\\t\\"\\xFF\\"")'))
|
||||
eq('Vim(call):E474: ASCII control characters cannot be present inside string: ',
|
||||
exc_exec('call json_decode(["\\"\\n\\""])'))
|
||||
-- 0xC2 starts 2-byte unicode character
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \194"',
|
||||
exc_exec('call json_decode("\\t\\"\\xC2\\"")'))
|
||||
-- 0xE0 0xAA starts 3-byte unicode character
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \224"',
|
||||
exc_exec('call json_decode("\\t\\"\\xE0\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \224\170"',
|
||||
exc_exec('call json_decode("\\t\\"\\xE0\\xAA\\"")'))
|
||||
-- 0xF0 0x90 0x80 starts 4-byte unicode character
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \240"',
|
||||
exc_exec('call json_decode("\\t\\"\\xF0\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \240\144"',
|
||||
exc_exec('call json_decode("\\t\\"\\xF0\\x90\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \240\144\128"',
|
||||
exc_exec('call json_decode("\\t\\"\\xF0\\x90\\x80\\"")'))
|
||||
-- 0xF9 0x80 0x80 0x80 starts 5-byte unicode character
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \249"',
|
||||
exc_exec('call json_decode("\\t\\"\\xF9\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \249\128"',
|
||||
exc_exec('call json_decode("\\t\\"\\xF9\\x80\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \249\128\128"',
|
||||
exc_exec('call json_decode("\\t\\"\\xF9\\x80\\x80\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \249\128\128\128"',
|
||||
exc_exec('call json_decode("\\t\\"\\xF9\\x80\\x80\\x80\\"")'))
|
||||
-- 0xFC 0x90 0x80 0x80 0x80 starts 6-byte unicode character
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \252"',
|
||||
exc_exec('call json_decode("\\t\\"\\xFC\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \252\144"',
|
||||
exc_exec('call json_decode("\\t\\"\\xFC\\x90\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \252\144\128"',
|
||||
exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \252\144\128\128"',
|
||||
exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\x80\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 strings allowed: \252\144\128\128\128"',
|
||||
exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\x80\\x80\\"")'))
|
||||
-- Specification does not allow unquoted characters above 0x10FFFF
|
||||
eq('Vim(call):E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \249\128\128\128\128"',
|
||||
exc_exec('call json_decode("\\t\\"\\xF9\\x80\\x80\\x80\\x80\\"")'))
|
||||
eq('Vim(call):E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"',
|
||||
exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\x80\\x80\\x80\\"")'))
|
||||
-- '"\249\128\128\128\128"',
|
||||
-- '"\252\144\128\128\128\128"',
|
||||
end)
|
||||
|
||||
it('parses surrogate pairs properly', function()
|
||||
eq('\240\144\128\128', funcs.json_decode('"\\uD800\\uDC00"'))
|
||||
eq('\237\160\128a\237\176\128', funcs.json_decode('"\\uD800a\\uDC00"'))
|
||||
eq('\237\160\128\t\237\176\128', funcs.json_decode('"\\uD800\\t\\uDC00"'))
|
||||
|
||||
eq('\237\160\128', funcs.json_decode('"\\uD800"'))
|
||||
eq('\237\160\128a', funcs.json_decode('"\\uD800a"'))
|
||||
eq('\237\160\128\t', funcs.json_decode('"\\uD800\\t"'))
|
||||
|
||||
eq('\237\176\128', funcs.json_decode('"\\uDC00"'))
|
||||
eq('\237\176\128a', funcs.json_decode('"\\uDC00a"'))
|
||||
eq('\237\176\128\t', funcs.json_decode('"\\uDC00\\t"'))
|
||||
|
||||
eq('\237\176\128', funcs.json_decode('"\\uDC00"'))
|
||||
eq('a\237\176\128', funcs.json_decode('"a\\uDC00"'))
|
||||
eq('\t\237\176\128', funcs.json_decode('"\\t\\uDC00"'))
|
||||
|
||||
eq('\237\160\128¬', funcs.json_decode('"\\uD800\\u00AC"'))
|
||||
|
||||
eq('\237\160\128\237\160\128', funcs.json_decode('"\\uD800\\uD800"'))
|
||||
end)
|
||||
|
||||
local sp_decode_eq = function(expected, json)
|
||||
meths.set_var('__json', json)
|
||||
speq(expected, 'json_decode(g:__json)')
|
||||
execute('unlet! g:__json')
|
||||
end
|
||||
|
||||
it('parses strings with NUL properly', function()
|
||||
sp_decode_eq({_TYPE='string', _VAL={'\n'}}, '"\\u0000"')
|
||||
sp_decode_eq({_TYPE='string', _VAL={'\n', '\n'}}, '"\\u0000\\n\\u0000"')
|
||||
sp_decode_eq({_TYPE='string', _VAL={'\n«\n'}}, '"\\u0000\\u00AB\\u0000"')
|
||||
end)
|
||||
|
||||
it('parses dictionaries with duplicate keys to special maps', function()
|
||||
sp_decode_eq({_TYPE='map', _VAL={{'a', 1}, {'a', 2}}},
|
||||
'{"a": 1, "a": 2}')
|
||||
sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'a', 2}}},
|
||||
'{"b": 3, "a": 1, "a": 2}')
|
||||
sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}}},
|
||||
'{"b": 3, "a": 1, "c": 4, "a": 2}')
|
||||
sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}},
|
||||
'{"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}')
|
||||
sp_decode_eq({{_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}}},
|
||||
'[{"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}]')
|
||||
sp_decode_eq({{d={_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}}}},
|
||||
'[{"d": {"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}}]')
|
||||
sp_decode_eq({1, {d={_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}}}},
|
||||
'[1, {"d": {"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}}]')
|
||||
sp_decode_eq({1, {a={}, d={_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}}}},
|
||||
'[1, {"a": [], "d": {"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}}]')
|
||||
end)
|
||||
|
||||
it('parses dictionaries with empty keys to special maps', function()
|
||||
sp_decode_eq({_TYPE='map', _VAL={{'', 4}}},
|
||||
'{"": 4}')
|
||||
sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'d', 2}, {'', 4}}},
|
||||
'{"b": 3, "a": 1, "c": 4, "d": 2, "": 4}')
|
||||
sp_decode_eq({_TYPE='map', _VAL={{'', 3}, {'a', 1}, {'c', 4}, {'d', 2}, {'', 4}}},
|
||||
'{"": 3, "a": 1, "c": 4, "d": 2, "": 4}')
|
||||
sp_decode_eq({{_TYPE='map', _VAL={{'', 3}, {'a', 1}, {'c', 4}, {'d', 2}, {'', 4}}}},
|
||||
'[{"": 3, "a": 1, "c": 4, "d": 2, "": 4}]')
|
||||
end)
|
||||
|
||||
it('parses dictionaries with keys with NUL bytes to special maps', function()
|
||||
sp_decode_eq({_TYPE='map', _VAL={{{_TYPE='string', _VAL={'a\n', 'b'}}, 4}}},
|
||||
'{"a\\u0000\\nb": 4}')
|
||||
sp_decode_eq({_TYPE='map', _VAL={{{_TYPE='string', _VAL={'a\n', 'b', ''}}, 4}}},
|
||||
'{"a\\u0000\\nb\\n": 4}')
|
||||
sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'d', 2}, {{_TYPE='string', _VAL={'\n'}}, 4}}},
|
||||
'{"b": 3, "a": 1, "c": 4, "d": 2, "\\u0000": 4}')
|
||||
end)
|
||||
|
||||
it('converts strings to latin1 when &encoding is latin1', function()
|
||||
restart('set encoding=latin1')
|
||||
eq('\171', funcs.json_decode('"\\u00AB"'))
|
||||
sp_decode_eq({_TYPE='string', _VAL={'\n\171\n'}}, '"\\u0000\\u00AB\\u0000"')
|
||||
end)
|
||||
|
||||
it('fails to convert string to latin1 if it is impossible', function()
|
||||
restart('set encoding=latin1')
|
||||
eq('Vim(call):E474: Failed to convert string "ꯍ" from UTF-8',
|
||||
exc_exec('call json_decode(\'"\\uABCD"\')'))
|
||||
end)
|
||||
|
||||
it('parses U+00C3 correctly', function()
|
||||
eq('\195\131', funcs.json_decode('"\195\131"'))
|
||||
end)
|
||||
|
||||
it('fails to parse empty string', function()
|
||||
eq('Vim(call):E474: Attempt to decode a blank string',
|
||||
exc_exec('call json_decode("")'))
|
||||
eq('Vim(call):E474: Attempt to decode a blank string',
|
||||
exc_exec('call json_decode([])'))
|
||||
eq('Vim(call):E474: Attempt to decode a blank string',
|
||||
exc_exec('call json_decode([""])'))
|
||||
eq('Vim(call):E474: Attempt to decode a blank string',
|
||||
exc_exec('call json_decode(" ")'))
|
||||
eq('Vim(call):E474: Attempt to decode a blank string',
|
||||
exc_exec('call json_decode("\\t")'))
|
||||
eq('Vim(call):E474: Attempt to decode a blank string',
|
||||
exc_exec('call json_decode("\\n")'))
|
||||
eq('Vim(call):E474: Attempt to decode a blank string',
|
||||
exc_exec('call json_decode(" \\t\\n \\n\\t\\t \\n\\t\\n \\n \\t\\n\\t ")'))
|
||||
end)
|
||||
|
||||
it('accepts all spaces in every position where space may be put', function()
|
||||
local s = ' \t\n\r \t\r\n \n\t\r \n\r\t \r\t\n \r\n\t\t \n\r\t \r\n\t\n \r\t\n\r \t\r \n\t\r\n \n \t\r\n \r\t\n\t \r\n\t\r \n\r \t\n\r\t \r \t\n\r \n\t\r\t \n\r\t\n \r\n \t\r\n\t'
|
||||
local str = ('%s{%s"key"%s:%s[%s"val"%s,%s"val2"%s]%s,%s"key2"%s:%s1%s}%s'):gsub('%%s', s)
|
||||
eq({key={'val', 'val2'}, key2=1}, funcs.json_decode(str))
|
||||
end)
|
||||
|
||||
it('always treats input as UTF-8', function()
|
||||
-- When &encoding is latin1 string "«" is U+00C2 U+00AB U+00C2: «Â. So if
|
||||
-- '"«"' was parsed as latin1 json_decode would return three characters, and
|
||||
-- only one U+00AB when this string is parsed as latin1.
|
||||
restart('set encoding=latin1')
|
||||
eq(('%c'):format(0xAB), funcs.json_decode('"«"'))
|
||||
end)
|
||||
|
||||
it('does not overflow when writing error message about decoding ["", ""]',
|
||||
function()
|
||||
eq('\nE474: Attempt to decode a blank string'
|
||||
.. '\nE474: Failed to parse \n',
|
||||
redir_exec('call json_decode(["", ""])'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('json_encode() function', function()
|
||||
before_each(function()
|
||||
clear()
|
||||
execute('language C')
|
||||
end)
|
||||
|
||||
it('dumps strings', function()
|
||||
eq('"Test"', funcs.json_encode('Test'))
|
||||
eq('""', funcs.json_encode(''))
|
||||
eq('"\\t"', funcs.json_encode('\t'))
|
||||
eq('"\\n"', funcs.json_encode('\n'))
|
||||
eq('"\\u001B"', funcs.json_encode('\27'))
|
||||
eq('"þÿþ"', funcs.json_encode('þÿþ'))
|
||||
end)
|
||||
|
||||
it('dumps numbers', function()
|
||||
eq('0', funcs.json_encode(0))
|
||||
eq('10', funcs.json_encode(10))
|
||||
eq('-10', funcs.json_encode(-10))
|
||||
end)
|
||||
|
||||
it('dumps floats', function()
|
||||
eq('0.0', eval('json_encode(0.0)'))
|
||||
eq('10.5', funcs.json_encode(10.5))
|
||||
eq('-10.5', funcs.json_encode(-10.5))
|
||||
eq('-1.0e-5', funcs.json_encode(-1e-5))
|
||||
eq('1.0e50', eval('json_encode(1.0e50)'))
|
||||
end)
|
||||
|
||||
it('fails to dump NaN and infinite values', function()
|
||||
eq('Vim(call):E474: Unable to represent NaN value in JSON',
|
||||
exc_exec('call json_encode(str2float("nan"))'))
|
||||
eq('Vim(call):E474: Unable to represent infinity in JSON',
|
||||
exc_exec('call json_encode(str2float("inf"))'))
|
||||
eq('Vim(call):E474: Unable to represent infinity in JSON',
|
||||
exc_exec('call json_encode(-str2float("inf"))'))
|
||||
end)
|
||||
|
||||
it('dumps lists', function()
|
||||
eq('[]', funcs.json_encode({}))
|
||||
eq('[[]]', funcs.json_encode({{}}))
|
||||
eq('[[], []]', funcs.json_encode({{}, {}}))
|
||||
end)
|
||||
|
||||
it('dumps dictionaries', function()
|
||||
eq('{}', eval('json_encode({})'))
|
||||
eq('{"d": []}', funcs.json_encode({d={}}))
|
||||
eq('{"d": [], "e": []}', funcs.json_encode({d={}, e={}}))
|
||||
end)
|
||||
|
||||
it('cannot dump generic mapping with generic mapping keys and values',
|
||||
function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
|
||||
execute('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
|
||||
execute('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
|
||||
execute('call add(todump._VAL, [todumpv1, todumpv2])')
|
||||
eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('cannot dump generic mapping with ext key', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}')
|
||||
eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('cannot dump generic mapping with array key', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}')
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}')
|
||||
eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('cannot dump generic mapping with UINT64_MAX key', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.integer}')
|
||||
execute('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]')
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}')
|
||||
eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('cannot dump generic mapping with floating-point key', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.float, "_VAL": 0.125}')
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}')
|
||||
eq('Vim(call):E474: Invalid key in special dictionary', exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump generic mapping with STR special key and NUL', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.string, "_VAL": ["\\n"]}')
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}')
|
||||
eq('{"\\u0000": 1}', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump generic mapping with BIN special key and NUL', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.binary, "_VAL": ["\\n"]}')
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[todump, 1]]}')
|
||||
eq('{"\\u0000": 1}', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump STR special mapping with NUL and NL', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.string, "_VAL": ["\\n", ""]}')
|
||||
eq('"\\u0000\\n"', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump BIN special mapping with NUL and NL', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.binary, "_VAL": ["\\n", ""]}')
|
||||
eq('"\\u0000\\n"', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('cannot dump special ext mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
|
||||
eq('Vim(call):E474: Unable to convert EXT string to JSON', exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump special array mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}')
|
||||
eq('[5, [""]]', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump special UINT64_MAX mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.integer}')
|
||||
execute('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]')
|
||||
eq('18446744073709551615', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump special INT64_MIN mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.integer}')
|
||||
execute('let todump._VAL = [-1, 2, 0, 0]')
|
||||
eq('-9223372036854775808', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump special BOOLEAN true mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}')
|
||||
eq('true', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump special BOOLEAN false mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}')
|
||||
eq('false', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump special NIL mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}')
|
||||
eq('null', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('fails to dump a function reference', function()
|
||||
eq('Vim(call):E474: Error while dumping encode_tv2json() argument, itself: attempt to dump function reference',
|
||||
exc_exec('call json_encode(function("tr"))'))
|
||||
end)
|
||||
|
||||
it('fails to dump a function reference in a list', function()
|
||||
eq('Vim(call):E474: Error while dumping encode_tv2json() argument, index 0: attempt to dump function reference',
|
||||
exc_exec('call json_encode([function("tr")])'))
|
||||
end)
|
||||
|
||||
it('fails to dump a recursive list', function()
|
||||
execute('let todump = [[[]]]')
|
||||
execute('call add(todump[0][0], todump)')
|
||||
eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
|
||||
exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('fails to dump a recursive dict', function()
|
||||
execute('let todump = {"d": {"d": {}}}')
|
||||
execute('call extend(todump.d.d, {"d": todump})')
|
||||
eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
|
||||
exc_exec('call json_encode([todump])'))
|
||||
end)
|
||||
|
||||
it('can dump dict with two same dicts inside', function()
|
||||
execute('let inter = {}')
|
||||
execute('let todump = {"a": inter, "b": inter}')
|
||||
eq('{"a": {}, "b": {}}', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('can dump list with two same lists inside', function()
|
||||
execute('let inter = []')
|
||||
execute('let todump = [inter, inter]')
|
||||
eq('[[], []]', eval('json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('fails to dump a recursive list in a special dict', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
|
||||
execute('call add(todump._VAL, todump)')
|
||||
eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
|
||||
exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('fails to dump a recursive (val) map in a special dict', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
|
||||
execute('call add(todump._VAL, ["", todump])')
|
||||
eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
|
||||
exc_exec('call json_encode([todump])'))
|
||||
end)
|
||||
|
||||
it('fails to dump a recursive (val) map in a special dict, _VAL reference', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [["", []]]}')
|
||||
execute('call add(todump._VAL[0][1], todump._VAL)')
|
||||
eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
|
||||
exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('fails to dump a recursive (val) special list in a special dict',
|
||||
function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
|
||||
execute('call add(todump._VAL, ["", todump._VAL])')
|
||||
eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
|
||||
exc_exec('call json_encode(todump)'))
|
||||
end)
|
||||
|
||||
it('fails when called with no arguments', function()
|
||||
eq('Vim(call):E119: Not enough arguments for function: json_encode',
|
||||
exc_exec('call json_encode()'))
|
||||
end)
|
||||
|
||||
it('fails when called with two arguments', function()
|
||||
eq('Vim(call):E118: Too many arguments for function: json_encode',
|
||||
exc_exec('call json_encode(["", ""], 1)'))
|
||||
end)
|
||||
|
||||
it('converts strings from latin1 when &encoding is latin1', function()
|
||||
clear('set encoding=latin1')
|
||||
eq('"\\u00AB"', funcs.json_encode('\171'))
|
||||
eq('"\\u0000\\u00AB\\u0000"', eval('json_encode({"_TYPE": v:msgpack_types.string, "_VAL": ["\\n\171\\n"]})'))
|
||||
end)
|
||||
|
||||
it('ignores improper values in &isprint', function()
|
||||
meths.set_option('isprint', '1')
|
||||
eq(1, eval('"\1" =~# "\\\\p"'))
|
||||
eq('"\\u0001"', funcs.json_encode('\1'))
|
||||
end)
|
||||
|
||||
it('fails when using surrogate character in a UTF-8 string', function()
|
||||
eq('Vim(call):E474: UTF-8 string contains code point which belongs to a surrogate pair: \237\160\128',
|
||||
exc_exec('call json_encode("\237\160\128")'))
|
||||
eq('Vim(call):E474: UTF-8 string contains code point which belongs to a surrogate pair: \237\175\191',
|
||||
exc_exec('call json_encode("\237\175\191")'))
|
||||
end)
|
||||
|
||||
it('dumps control characters as expected', function()
|
||||
eq([["\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000B\f\r\u000E\u000F\u0010\u0011\u0012\u0013"]],
|
||||
eval('json_encode({"_TYPE": v:msgpack_types.string, "_VAL": ["\n\1\2\3\4\5\6\7\8\9", "\11\12\13\14\15\16\17\18\19"]})'))
|
||||
end)
|
||||
|
||||
it('can dump NULL string', function()
|
||||
eq('""', eval('json_encode($XXX_UNEXISTENT_VAR_XXX)'))
|
||||
end)
|
||||
|
||||
it('can dump NULL list', function()
|
||||
eq('[]', eval('json_encode(v:_null_list)'))
|
||||
end)
|
||||
|
||||
it('can dump NULL dictionary', function()
|
||||
eq('{}', eval('json_encode(v:_null_dict)'))
|
||||
end)
|
||||
end)
|
|
@ -1,5 +1,6 @@
|
|||
local helpers = require('test.functional.helpers')
|
||||
local clear = helpers.clear
|
||||
local funcs = helpers.funcs
|
||||
local eval, eq = helpers.eval, helpers.eq
|
||||
local execute = helpers.execute
|
||||
local nvim = helpers.nvim
|
||||
|
@ -382,30 +383,32 @@ describe('msgpack*() functions', function()
|
|||
eq({"\n"}, eval('parsed'))
|
||||
eq(1, eval('dumped ==# dumped2'))
|
||||
end)
|
||||
|
||||
it('dump and restore special mapping with floating-point value', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.float, "_VAL": 0.125}')
|
||||
eq({0.125}, eval('msgpackparse(msgpackdump([todump]))'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('msgpackparse() function', function()
|
||||
before_each(clear)
|
||||
|
||||
it('restores nil as special dict', function()
|
||||
it('restores nil as v:null', function()
|
||||
execute('let dumped = ["\\xC0"]')
|
||||
execute('let parsed = msgpackparse(dumped)')
|
||||
eq({{_TYPE={}, _VAL=0}}, eval('parsed'))
|
||||
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.nil'))
|
||||
eq('[v:null]', eval('string(parsed)'))
|
||||
end)
|
||||
|
||||
it('restores boolean false as zero', function()
|
||||
it('restores boolean false as v:false', function()
|
||||
execute('let dumped = ["\\xC2"]')
|
||||
execute('let parsed = msgpackparse(dumped)')
|
||||
eq({{_TYPE={}, _VAL=0}}, eval('parsed'))
|
||||
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.boolean'))
|
||||
eq({false}, eval('parsed'))
|
||||
end)
|
||||
|
||||
it('restores boolean true as one', function()
|
||||
it('restores boolean true as v:true', function()
|
||||
execute('let dumped = ["\\xC3"]')
|
||||
execute('let parsed = msgpackparse(dumped)')
|
||||
eq({{_TYPE={}, _VAL=1}}, eval('parsed'))
|
||||
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.boolean'))
|
||||
eq({true}, eval('parsed'))
|
||||
end)
|
||||
|
||||
it('restores FIXSTR as special dict', function()
|
||||
|
@ -512,33 +515,55 @@ describe('msgpackdump() function', function()
|
|||
eq({'\129\128\128'}, eval('msgpackdump([todump])'))
|
||||
end)
|
||||
|
||||
it('can dump generic mapping with ext', function()
|
||||
it('can dump v:true', function()
|
||||
eq({'\195'}, funcs.msgpackdump({true}))
|
||||
end)
|
||||
|
||||
it('can dump v:false', function()
|
||||
eq({'\194'}, funcs.msgpackdump({false}))
|
||||
end)
|
||||
|
||||
it('can v:null', function()
|
||||
execute('let todump = v:null')
|
||||
end)
|
||||
|
||||
it('can dump special bool mapping (true)', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}')
|
||||
eq({'\195'}, eval('msgpackdump([todump])'))
|
||||
end)
|
||||
|
||||
it('can dump special bool mapping (false)', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}')
|
||||
eq({'\194'}, eval('msgpackdump([todump])'))
|
||||
end)
|
||||
|
||||
it('can dump special nil mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}')
|
||||
eq({'\192'}, eval('msgpackdump([todump])'))
|
||||
end)
|
||||
|
||||
it('can dump special ext mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
|
||||
eq({'\212\005', ''}, eval('msgpackdump([todump])'))
|
||||
end)
|
||||
|
||||
it('can dump generic mapping with array', function()
|
||||
it('can dump special array mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}')
|
||||
eq({'\146\005\145\196\n'}, eval('msgpackdump([todump])'))
|
||||
end)
|
||||
|
||||
it('can dump generic mapping with UINT64_MAX', function()
|
||||
it('can dump special UINT64_MAX mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.integer}')
|
||||
execute('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]')
|
||||
eq({'\207\255\255\255\255\255\255\255\255'}, eval('msgpackdump([todump])'))
|
||||
end)
|
||||
|
||||
it('can dump generic mapping with INT64_MIN', function()
|
||||
it('can dump special INT64_MIN mapping', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.integer}')
|
||||
execute('let todump._VAL = [-1, 2, 0, 0]')
|
||||
eq({'\211\128\n\n\n\n\n\n\n'}, eval('msgpackdump([todump])'))
|
||||
end)
|
||||
|
||||
it('dump and restore generic mapping with floating-point value', function()
|
||||
execute('let todump = {"_TYPE": v:msgpack_types.float, "_VAL": 0.125}')
|
||||
eq({0.125}, eval('msgpackparse(msgpackdump([todump]))'))
|
||||
end)
|
||||
|
||||
it('fails to dump a function reference', function()
|
||||
execute('let Todump = function("tr")')
|
||||
eq('Vim(call):E951: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference',
|
||||
|
@ -654,4 +679,25 @@ describe('msgpackdump() function', function()
|
|||
eq('Vim(call):E686: Argument of msgpackdump() must be a List',
|
||||
exc_exec('call msgpackdump(0.0)'))
|
||||
end)
|
||||
|
||||
it('fails to dump special value', function()
|
||||
for _, val in ipairs({'v:true', 'v:false', 'v:null'}) do
|
||||
eq('Vim(call):E686: Argument of msgpackdump() must be a List',
|
||||
exc_exec('call msgpackdump(' .. val .. ')'))
|
||||
end
|
||||
end)
|
||||
|
||||
it('can dump NULL string', function()
|
||||
eq({'\196\n'}, eval('msgpackdump([$XXX_UNEXISTENT_VAR_XXX])'))
|
||||
eq({'\196\n'}, eval('msgpackdump([{"_TYPE": v:msgpack_types.binary, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}])'))
|
||||
eq({'\160'}, eval('msgpackdump([{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}])'))
|
||||
end)
|
||||
|
||||
it('can dump NULL list', function()
|
||||
eq({'\144'}, eval('msgpackdump([v:_null_list])'))
|
||||
end)
|
||||
|
||||
it('can dump NULL dictionary', function()
|
||||
eq({'\128'}, eval('msgpackdump([v:_null_dict])'))
|
||||
end)
|
||||
end)
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
local helpers = require('test.functional.helpers')
|
||||
local exc_exec = helpers.exc_exec
|
||||
local execute = helpers.execute
|
||||
local meths = helpers.meths
|
||||
local funcs = helpers.funcs
|
||||
local meths = helpers.meths
|
||||
local clear = helpers.clear
|
||||
local eval = helpers.eval
|
||||
local eq = helpers.eq
|
||||
|
||||
describe('Special values', function()
|
||||
before_each(clear)
|
||||
|
||||
it('do not cause error when freed', function()
|
||||
execute([[
|
||||
function Test()
|
||||
try
|
||||
return v:true
|
||||
finally
|
||||
return 'something else'
|
||||
endtry
|
||||
endfunction
|
||||
]])
|
||||
eq(0, exc_exec('call Test()'))
|
||||
end)
|
||||
|
||||
it('work with empty()', function()
|
||||
eq(0, funcs.empty(true))
|
||||
eq(1, funcs.empty(false))
|
||||
eq(1, funcs.empty(NIL))
|
||||
end)
|
||||
|
||||
it('can be stringified and eval’ed back', function()
|
||||
eq(true, funcs.eval(funcs.string(true)))
|
||||
eq(false, funcs.eval(funcs.string(false)))
|
||||
eq(NIL, funcs.eval(funcs.string(NIL)))
|
||||
end)
|
||||
|
||||
it('work with is/isnot properly', function()
|
||||
eq(1, eval('v:null is v:null'))
|
||||
eq(0, eval('v:null is v:true'))
|
||||
eq(0, eval('v:null is v:false'))
|
||||
eq(1, eval('v:true is v:true'))
|
||||
eq(0, eval('v:true is v:false'))
|
||||
eq(1, eval('v:false is v:false'))
|
||||
|
||||
eq(0, eval('v:null is 0'))
|
||||
eq(0, eval('v:true is 0'))
|
||||
eq(0, eval('v:false is 0'))
|
||||
|
||||
eq(0, eval('v:null is 1'))
|
||||
eq(0, eval('v:true is 1'))
|
||||
eq(0, eval('v:false is 1'))
|
||||
|
||||
eq(0, eval('v:null is ""'))
|
||||
eq(0, eval('v:true is ""'))
|
||||
eq(0, eval('v:false is ""'))
|
||||
|
||||
eq(0, eval('v:null is "null"'))
|
||||
eq(0, eval('v:true is "true"'))
|
||||
eq(0, eval('v:false is "false"'))
|
||||
|
||||
eq(0, eval('v:null is []'))
|
||||
eq(0, eval('v:true is []'))
|
||||
eq(0, eval('v:false is []'))
|
||||
|
||||
eq(0, eval('v:null isnot v:null'))
|
||||
eq(1, eval('v:null isnot v:true'))
|
||||
eq(1, eval('v:null isnot v:false'))
|
||||
eq(0, eval('v:true isnot v:true'))
|
||||
eq(1, eval('v:true isnot v:false'))
|
||||
eq(0, eval('v:false isnot v:false'))
|
||||
|
||||
eq(1, eval('v:null isnot 0'))
|
||||
eq(1, eval('v:true isnot 0'))
|
||||
eq(1, eval('v:false isnot 0'))
|
||||
|
||||
eq(1, eval('v:null isnot 1'))
|
||||
eq(1, eval('v:true isnot 1'))
|
||||
eq(1, eval('v:false isnot 1'))
|
||||
|
||||
eq(1, eval('v:null isnot ""'))
|
||||
eq(1, eval('v:true isnot ""'))
|
||||
eq(1, eval('v:false isnot ""'))
|
||||
|
||||
eq(1, eval('v:null isnot "null"'))
|
||||
eq(1, eval('v:true isnot "true"'))
|
||||
eq(1, eval('v:false isnot "false"'))
|
||||
|
||||
eq(1, eval('v:null isnot []'))
|
||||
eq(1, eval('v:true isnot []'))
|
||||
eq(1, eval('v:false isnot []'))
|
||||
end)
|
||||
|
||||
it('work with +/-/* properly', function()
|
||||
eq(1, eval('0 + v:true'))
|
||||
eq(0, eval('0 + v:null'))
|
||||
eq(0, eval('0 + v:false'))
|
||||
|
||||
eq(-1, eval('0 - v:true'))
|
||||
eq( 0, eval('0 - v:null'))
|
||||
eq( 0, eval('0 - v:false'))
|
||||
|
||||
eq(1, eval('1 * v:true'))
|
||||
eq(0, eval('1 * v:null'))
|
||||
eq(0, eval('1 * v:false'))
|
||||
end)
|
||||
|
||||
it('does not work with +=/-=/.=', function()
|
||||
meths.set_var('true', true)
|
||||
meths.set_var('false', false)
|
||||
execute('let null = v:null')
|
||||
|
||||
eq('Vim(let):E734: Wrong variable type for +=', exc_exec('let true += 1'))
|
||||
eq('Vim(let):E734: Wrong variable type for +=', exc_exec('let false += 1'))
|
||||
eq('Vim(let):E734: Wrong variable type for +=', exc_exec('let null += 1'))
|
||||
|
||||
eq('Vim(let):E734: Wrong variable type for -=', exc_exec('let true -= 1'))
|
||||
eq('Vim(let):E734: Wrong variable type for -=', exc_exec('let false -= 1'))
|
||||
eq('Vim(let):E734: Wrong variable type for -=', exc_exec('let null -= 1'))
|
||||
|
||||
eq('Vim(let):E734: Wrong variable type for .=', exc_exec('let true .= 1'))
|
||||
eq('Vim(let):E734: Wrong variable type for .=', exc_exec('let false .= 1'))
|
||||
eq('Vim(let):E734: Wrong variable type for .=', exc_exec('let null .= 1'))
|
||||
end)
|
||||
|
||||
it('work with . (concat) properly', function()
|
||||
eq("true", eval('"" . v:true'))
|
||||
eq("null", eval('"" . v:null'))
|
||||
eq("false", eval('"" . v:false'))
|
||||
end)
|
||||
|
||||
it('work with type()', function()
|
||||
eq(6, funcs.type(true))
|
||||
eq(6, funcs.type(false))
|
||||
eq(7, funcs.type(NIL))
|
||||
end)
|
||||
|
||||
it('work with copy() and deepcopy()', function()
|
||||
eq(true, funcs.deepcopy(true))
|
||||
eq(false, funcs.deepcopy(false))
|
||||
eq(NIL, funcs.deepcopy(NIL))
|
||||
|
||||
eq(true, funcs.copy(true))
|
||||
eq(false, funcs.copy(false))
|
||||
eq(NIL, funcs.copy(NIL))
|
||||
end)
|
||||
|
||||
it('fails in index', function()
|
||||
eq('Vim(echo):E909: Cannot index a special variable', exc_exec('echo v:true[0]'))
|
||||
eq('Vim(echo):E909: Cannot index a special variable', exc_exec('echo v:false[0]'))
|
||||
eq('Vim(echo):E909: Cannot index a special variable', exc_exec('echo v:null[0]'))
|
||||
end)
|
||||
|
||||
it('is accepted by assert_true and assert_false', function()
|
||||
funcs.assert_false(false)
|
||||
funcs.assert_false(true)
|
||||
funcs.assert_false(NIL)
|
||||
|
||||
funcs.assert_true(false)
|
||||
funcs.assert_true(true)
|
||||
funcs.assert_true(NIL)
|
||||
|
||||
eq({
|
||||
'Expected False but got v:true',
|
||||
'Expected False but got v:null',
|
||||
'Expected True but got v:false',
|
||||
'Expected True but got v:null',
|
||||
}, meths.get_vvar('errors'))
|
||||
end)
|
||||
end)
|
|
@ -28,6 +28,15 @@ describe('string() function', function()
|
|||
eq('0.0', eval('string(0.0)'))
|
||||
end)
|
||||
|
||||
it('dumps special v: values', function()
|
||||
eq('v:true', eval('string(v:true)'))
|
||||
eq('v:false', eval('string(v:false)'))
|
||||
eq('v:null', eval('string(v:null)'))
|
||||
eq('v:true', funcs.string(true))
|
||||
eq('v:false', funcs.string(false))
|
||||
eq('v:null', funcs.string(NIL))
|
||||
end)
|
||||
|
||||
it('dumps values with at most six digits after the decimal point',
|
||||
function()
|
||||
eq('1.234568e-20', funcs.string(1.23456789123456789123456789e-020))
|
||||
|
@ -78,6 +87,18 @@ describe('string() function', function()
|
|||
eq('\'\'\'b\'\'\'\'d\'', funcs.string('\'b\'\'d'))
|
||||
eq('\'a\'\'b\'\'c\'\'d\'', funcs.string('a\'b\'c\'d'))
|
||||
end)
|
||||
|
||||
it('dumps NULL strings', function()
|
||||
eq('\'\'', eval('string($XXX_UNEXISTENT_VAR_XXX)'))
|
||||
end)
|
||||
|
||||
it('dumps NULL lists', function()
|
||||
eq('[]', eval('string(v:_null_list)'))
|
||||
end)
|
||||
|
||||
it('dumps NULL dictionaries', function()
|
||||
eq('{}', eval('string(v:_null_dict)'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('used to represent funcrefs', function()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
local helpers = require('test.functional.helpers')
|
||||
local meths = helpers.meths
|
||||
local eq, nvim_eval, nvim_command, exc_exec =
|
||||
helpers.eq, helpers.eval, helpers.command, helpers.exc_exec
|
||||
local ok = helpers.ok
|
||||
|
@ -409,6 +410,12 @@ describe('In autoload/msgpack.vim', function()
|
|||
string_eq('nan', '(1.0/0.0-1.0/0.0)')
|
||||
string_eq('nan', '-(1.0/0.0-1.0/0.0)')
|
||||
end)
|
||||
|
||||
it('works for special v: values like v:true', function()
|
||||
string_eq('TRUE', 'v:true')
|
||||
string_eq('FALSE', 'v:false')
|
||||
string_eq('NIL', 'v:null')
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('function msgpack#deepcopy', function()
|
||||
|
@ -523,6 +530,20 @@ describe('In autoload/msgpack.vim', function()
|
|||
eq(2.0, nvim_eval('flt2'))
|
||||
eq('abc', nvim_eval('bin2'))
|
||||
end)
|
||||
|
||||
it('works for special v: values like v:true', function()
|
||||
meths.set_var('true', true)
|
||||
meths.set_var('false', false)
|
||||
meths.set_var('nil', NIL)
|
||||
|
||||
nvim_command('let true2 = msgpack#deepcopy(true)')
|
||||
nvim_command('let false2 = msgpack#deepcopy(false)')
|
||||
nvim_command('let nil2 = msgpack#deepcopy(nil)')
|
||||
|
||||
eq(true, meths.get_var('true'))
|
||||
eq(false, meths.get_var('false'))
|
||||
eq(NIL, meths.get_var('nil'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('function msgpack#eval', function()
|
||||
|
|
|
@ -22,12 +22,17 @@ describe('ShaDa support code', function()
|
|||
eq('foo', meths.get_var('STRVAR'))
|
||||
end)
|
||||
|
||||
local autotest = function(tname, varname, varval)
|
||||
local autotest = function(tname, varname, varval, val_is_expr)
|
||||
it('is able to dump and read back ' .. tname .. ' variable automatically',
|
||||
function()
|
||||
set_additional_cmd('set shada+=!')
|
||||
reset()
|
||||
meths.set_var(varname, varval)
|
||||
if val_is_expr then
|
||||
nvim_command('let g:' .. varname .. ' = ' .. varval)
|
||||
varval = meths.get_var(varname)
|
||||
else
|
||||
meths.set_var(varname, varval)
|
||||
end
|
||||
-- Exit during `reset` is not a regular exit: it does not write shada
|
||||
-- automatically
|
||||
nvim_command('qall')
|
||||
|
@ -41,6 +46,10 @@ describe('ShaDa support code', function()
|
|||
autotest('float', 'FLTVAR', 42.5)
|
||||
autotest('dictionary', 'DCTVAR', {a=10})
|
||||
autotest('list', 'LSTVAR', {{a=10}, {b=10.5}, {c='str'}})
|
||||
autotest('true', 'TRUEVAR', true)
|
||||
autotest('false', 'FALSEVAR', false)
|
||||
autotest('null', 'NULLVAR', 'v:null', true)
|
||||
autotest('ext', 'EXTVAR', '{"_TYPE": v:msgpack_types.ext, "_VAL": [2, ["", ""]]}', true)
|
||||
|
||||
it('does not read back variables without `!` in &shada', function()
|
||||
meths.set_var('STRVAR', 'foo')
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
local helpers = require('test.unit.helpers')
|
||||
|
||||
local cimport = helpers.cimport
|
||||
local to_cstr = helpers.to_cstr
|
||||
local eq = helpers.eq
|
||||
local neq = helpers.neq
|
||||
local ffi = helpers.ffi
|
||||
|
||||
local decode = cimport('./src/nvim/eval/decode.h', './src/nvim/eval_defs.h',
|
||||
'./src/nvim/globals.h', './src/nvim/memory.h',
|
||||
'./src/nvim/message.h')
|
||||
|
||||
describe('json_decode_string()', function()
|
||||
local saved_p_enc = nil
|
||||
|
||||
before_each(function()
|
||||
saved_p_enc = decode.p_enc
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
decode.emsg_silent = 0
|
||||
decode.p_enc = saved_p_enc
|
||||
while decode.delete_first_msg() == 1 do
|
||||
-- Delete all messages
|
||||
end
|
||||
end)
|
||||
|
||||
local char = function(c)
|
||||
return ffi.gc(decode.xmemdup(c, 1), decode.xfree)
|
||||
end
|
||||
|
||||
it('does not overflow when running with `n…`, `t…`, `f…`', function()
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
decode.emsg_silent = 1
|
||||
-- This will not crash, but if `len` argument will be ignored it will parse
|
||||
-- `null` as `null` and if not it will parse `null` as `n`.
|
||||
eq(0, decode.json_decode_string('null', 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('true', 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('false', 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('null', 2, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('true', 2, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('false', 2, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('null', 3, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('true', 3, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('false', 3, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('false', 4, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
end)
|
||||
|
||||
it('does not overflow and crash when running with `n`, `t`, `f`', function()
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
decode.emsg_silent = 1
|
||||
eq(0, decode.json_decode_string(char('n'), 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string(char('t'), 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string(char('f'), 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
end)
|
||||
|
||||
it('does not overflow when running with `"…`', function()
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
decode.emsg_silent = 1
|
||||
eq(0, decode.json_decode_string('"t"', 2, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
eq(0, decode.json_decode_string('""', 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
end)
|
||||
|
||||
local check_failure = function(s, len, msg)
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
eq(0, decode.json_decode_string(s, len, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
neq(nil, decode.last_msg_hist)
|
||||
eq(msg, ffi.string(decode.last_msg_hist.msg))
|
||||
end
|
||||
|
||||
it('does not overflow in error messages', function()
|
||||
check_failure(']test', 1, 'E474: No container to close: ]')
|
||||
check_failure('[}test', 2, 'E474: Closing list with curly bracket: }')
|
||||
check_failure('{]test', 2,
|
||||
'E474: Closing dictionary with square bracket: ]')
|
||||
check_failure('[1,]test', 4, 'E474: Trailing comma: ]')
|
||||
check_failure('{"1":}test', 6, 'E474: Expected value after colon: }')
|
||||
check_failure('{"1"}test', 5, 'E474: Expected value: }')
|
||||
check_failure(',test', 1, 'E474: Comma not inside container: ,')
|
||||
check_failure('[1,,1]test', 6, 'E474: Duplicate comma: ,1]')
|
||||
check_failure('{"1":,}test', 7, 'E474: Comma after colon: ,}')
|
||||
check_failure('{"1",}test', 6, 'E474: Using comma in place of colon: ,}')
|
||||
check_failure('{,}test', 3, 'E474: Leading comma: ,}')
|
||||
check_failure('[,]test', 3, 'E474: Leading comma: ,]')
|
||||
check_failure(':test', 1, 'E474: Colon not inside container: :')
|
||||
check_failure('[:]test', 3, 'E474: Using colon not in dictionary: :]')
|
||||
check_failure('{:}test', 3, 'E474: Unexpected colon: :}')
|
||||
check_failure('{"1"::1}test', 8, 'E474: Duplicate colon: :1}')
|
||||
check_failure('ntest', 1, 'E474: Expected null: n')
|
||||
check_failure('ttest', 1, 'E474: Expected true: t')
|
||||
check_failure('ftest', 1, 'E474: Expected false: f')
|
||||
check_failure('"\\test', 2, 'E474: Unfinished escape sequence: "\\')
|
||||
check_failure('"\\u"test', 4,
|
||||
'E474: Unfinished unicode escape sequence: "\\u"')
|
||||
check_failure('"\\uXXXX"est', 8,
|
||||
'E474: Expected four hex digits after \\u: \\uXXXX"')
|
||||
check_failure('"\\?"test', 4, 'E474: Unknown escape sequence: \\?"')
|
||||
check_failure(
|
||||
'"\t"test', 3,
|
||||
'E474: ASCII control characters cannot be present inside string: \t"')
|
||||
check_failure('"\194"test', 3, 'E474: Only UTF-8 strings allowed: \194"')
|
||||
check_failure('"\252\144\128\128\128\128"test', 8, 'E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"')
|
||||
check_failure('"test', 1, 'E474: Expected string end: "')
|
||||
decode.p_enc = to_cstr('latin1')
|
||||
check_failure('"\\uABCD"test', 8,
|
||||
'E474: Failed to convert string "ꯍ" from UTF-8')
|
||||
decode.p_enc = saved_p_enc
|
||||
check_failure('-test', 1, 'E474: Missing number after minus sign: -')
|
||||
check_failure('-1.test', 3, 'E474: Missing number after decimal dot: -1.')
|
||||
check_failure('-1.0etest', 5, 'E474: Missing exponent: -1.0e')
|
||||
check_failure('?test', 1, 'E474: Unidentified byte: ?')
|
||||
check_failure('1?test', 2, 'E474: Trailing characters: ?')
|
||||
check_failure('[1test', 2, 'E474: Unexpected end of input: [1')
|
||||
end)
|
||||
|
||||
it('does not overflow with `-`', function()
|
||||
check_failure('-0', 1, 'E474: Missing number after minus sign: -')
|
||||
end)
|
||||
|
||||
it('does not overflow and crash when running with `"`', function()
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
decode.emsg_silent = 1
|
||||
eq(0, decode.json_decode_string(char('"'), 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
end)
|
||||
end)
|
|
@ -0,0 +1,100 @@
|
|||
local helpers = require('test.unit.helpers')
|
||||
local eval_helpers = require('test.unit.eval.helpers')
|
||||
|
||||
local cimport = helpers.cimport
|
||||
local to_cstr = helpers.to_cstr
|
||||
local eq = helpers.eq
|
||||
|
||||
local list = eval_helpers.list
|
||||
local lst2tbl = eval_helpers.lst2tbl
|
||||
local type_key = eval_helpers.type_key
|
||||
local list_type = eval_helpers.list_type
|
||||
local null_string = eval_helpers.null_string
|
||||
|
||||
local encode = cimport('./src/nvim/eval/encode.h')
|
||||
|
||||
describe('encode_list_write()', function()
|
||||
local encode_list_write = function(l, s)
|
||||
return encode.encode_list_write(l, to_cstr(s), #s)
|
||||
end
|
||||
|
||||
it('writes empty string', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, ''))
|
||||
eq({[type_key]=list_type}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes ASCII string literal with printable characters', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, 'abc'))
|
||||
eq({[type_key]=list_type, 'abc'}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes string starting with NL', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\nabc'))
|
||||
eq({[type_key]=list_type, null_string, 'abc'}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes string starting with NL twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\nabc'))
|
||||
eq({[type_key]=list_type, null_string, 'abc'}, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\nabc'))
|
||||
eq({[type_key]=list_type, null_string, 'abc', 'abc'}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes string ending with NL', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, 'abc\n'))
|
||||
eq({[type_key]=list_type, 'abc', null_string}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes string ending with NL twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, 'abc\n'))
|
||||
eq({[type_key]=list_type, 'abc', null_string}, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, 'abc\n'))
|
||||
eq({[type_key]=list_type, 'abc', 'abc', null_string}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes string starting, ending and containing NL twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\na\nb\n'))
|
||||
eq({[type_key]=list_type, null_string, 'a', 'b', null_string}, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\na\nb\n'))
|
||||
eq({[type_key]=list_type, null_string, 'a', 'b', null_string, 'a', 'b', null_string}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes string starting, ending and containing NUL with NL between twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\0\n\0\n\0'))
|
||||
eq({[type_key]=list_type, '\n', '\n', '\n'}, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\0\n\0\n\0'))
|
||||
eq({[type_key]=list_type, '\n', '\n', '\n\n', '\n', '\n'}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes string starting, ending and containing NL with NUL between twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\n\0\n\0\n'))
|
||||
eq({[type_key]=list_type, null_string, '\n', '\n', null_string}, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\n\0\n\0\n'))
|
||||
eq({[type_key]=list_type, null_string, '\n', '\n', null_string, '\n', '\n', null_string}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes string containing a single NL twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\n'))
|
||||
eq({[type_key]=list_type, null_string, null_string}, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\n'))
|
||||
eq({[type_key]=list_type, null_string, null_string, null_string}, lst2tbl(l))
|
||||
end)
|
||||
|
||||
it('writes string containing a few NLs twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\n\n\n'))
|
||||
eq({[type_key]=list_type, null_string, null_string, null_string, null_string}, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\n\n\n'))
|
||||
eq({[type_key]=list_type, null_string, null_string, null_string, null_string, null_string, null_string, null_string}, lst2tbl(l))
|
||||
end)
|
||||
end)
|
|
@ -0,0 +1,72 @@
|
|||
local helpers = require('test.unit.helpers')
|
||||
|
||||
local cimport = helpers.cimport
|
||||
local to_cstr = helpers.to_cstr
|
||||
local ffi = helpers.ffi
|
||||
local eq = helpers.eq
|
||||
|
||||
local eval = cimport('./src/nvim/eval.h', './src/nvim/eval_defs.h')
|
||||
|
||||
local null_string = {[true]='NULL string'}
|
||||
local null_list = {[true]='NULL list'}
|
||||
local type_key = {[true]='type key'}
|
||||
local list_type = {[true]='list type'}
|
||||
|
||||
local list = function(...)
|
||||
local ret = ffi.gc(eval.list_alloc(), eval.list_unref)
|
||||
eq(0, ret.lv_refcount)
|
||||
ret.lv_refcount = 1
|
||||
for i = 1, select('#', ...) do
|
||||
local val = select(i, ...)
|
||||
local typ = type(val)
|
||||
if typ == 'string' then
|
||||
eval.list_append_string(ret, to_cstr(val))
|
||||
elseif typ == 'table' and val == null_string then
|
||||
eval.list_append_string(ret, nil)
|
||||
elseif typ == 'table' and val == null_list then
|
||||
eval.list_append_list(ret, nil)
|
||||
elseif typ == 'table' and val[type_key] == list_type then
|
||||
local itemlist = ffi.gc(list(table.unpack(val)), nil)
|
||||
eq(1, itemlist.lv_refcount)
|
||||
itemlist.lv_refcount = 0
|
||||
eval.list_append_list(ret, itemlist)
|
||||
else
|
||||
assert(false, 'Not implemented yet')
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local lst2tbl = function(l)
|
||||
local ret = {[type_key]=list_type}
|
||||
if l == nil then
|
||||
return ret
|
||||
end
|
||||
local li = l.lv_first
|
||||
-- (listitem_T *) NULL is equal to nil, but yet it is not false.
|
||||
while li ~= nil do
|
||||
local typ = li.li_tv.v_type
|
||||
if typ == eval.VAR_STRING then
|
||||
str = li.li_tv.vval.v_string
|
||||
if str == nil then
|
||||
ret[#ret + 1] = null_string
|
||||
else
|
||||
ret[#ret + 1] = ffi.string(str)
|
||||
end
|
||||
else
|
||||
assert(false, 'Not implemented yet')
|
||||
end
|
||||
li = li.li_next
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
return {
|
||||
null_string=null_string,
|
||||
null_list=null_list,
|
||||
list_type=list_type,
|
||||
type_key=type_key,
|
||||
|
||||
list=list,
|
||||
lst2tbl=lst2tbl,
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
local helpers = require('test.unit.helpers')
|
||||
|
||||
local cimport = helpers.cimport
|
||||
local to_cstr = helpers.to_cstr
|
||||
local ffi = helpers.ffi
|
||||
local eq = helpers.eq
|
||||
|
||||
local eval = cimport('./src/nvim/eval.h', './src/nvim/memory.h')
|
||||
|
||||
local eval_expr = function(expr)
|
||||
return ffi.gc(eval.eval_expr(to_cstr(expr), nil), function(tv)
|
||||
eval.clear_tv(tv)
|
||||
eval.xfree(tv)
|
||||
end)
|
||||
end
|
||||
|
||||
describe('NULL typval_T', function()
|
||||
it('is produced by $XXX_UNEXISTENT_VAR_XXX', function()
|
||||
-- Required for various tests which need to check whether typval_T with NULL
|
||||
-- string works correctly. This test checks that unexistent environment
|
||||
-- variable produces NULL string, not that some specific environment
|
||||
-- variable does not exist. Last bit is left for the test writers.
|
||||
local unexistent_env = 'XXX_UNEXISTENT_VAR_XXX'
|
||||
while os.getenv(unexistent_env) ~= nil do
|
||||
unexistent_env = unexistent_env .. '_XXX'
|
||||
end
|
||||
local rettv = eval_expr('$' .. unexistent_env)
|
||||
eq(eval.VAR_STRING, rettv.v_type)
|
||||
eq(nil, rettv.vval.v_string)
|
||||
end)
|
||||
|
||||
it('is produced by v:_null_list', function()
|
||||
local rettv = eval_expr('v:_null_list')
|
||||
eq(eval.VAR_LIST, rettv.v_type)
|
||||
eq(nil, rettv.vval.v_list)
|
||||
end)
|
||||
|
||||
it('is produced by v:_null_dict', function()
|
||||
local rettv = eval_expr('v:_null_dict')
|
||||
eq(eval.VAR_DICT, rettv.v_type)
|
||||
eq(nil, rettv.vval.v_dict)
|
||||
end)
|
||||
end)
|
|
@ -28,8 +28,10 @@ local function filter_complex_blocks(body)
|
|||
local result = {}
|
||||
|
||||
for line in body:gmatch("[^\r\n]+") do
|
||||
if not (string.find(line, "(^)", 1, true) ~= nil or
|
||||
string.find(line, "_ISwupper", 1, true)) then
|
||||
if not (string.find(line, "(^)", 1, true) ~= nil
|
||||
or string.find(line, "_ISwupper", 1, true)
|
||||
or string.find(line, "msgpack_zone_push_finalizer")
|
||||
or string.find(line, "msgpack_unpacker_reserve_buffer")) then
|
||||
result[#result + 1] = line
|
||||
end
|
||||
end
|
||||
|
@ -103,6 +105,11 @@ local function cimport(...)
|
|||
-- request a sorted version of the new lines (same relative order as the
|
||||
-- original preprocessed file) and feed that to the LuaJIT ffi
|
||||
local new_lines = new_cdefs:to_table()
|
||||
if os.getenv('NVIM_TEST_PRINT_CDEF') == '1' then
|
||||
for lnum, line in ipairs(new_lines) do
|
||||
print(lnum, line)
|
||||
end
|
||||
end
|
||||
ffi.cdef(table.concat(new_lines, "\n"))
|
||||
|
||||
return libnvim
|
||||
|
|
Loading…
Reference in New Issue