mirror of
https://github.com/neovim/neovim.git
synced 2025-09-08 04:18:18 +00:00
eval: Add special variables v:false, v:null, v:none
This commit is contained in:
@@ -1418,6 +1418,13 @@ v:exception The value of the exception most recently caught and not
|
|||||||
:endtry
|
:endtry
|
||||||
< Output: "caught oops".
|
< Output: "caught oops".
|
||||||
|
|
||||||
|
*v:false* *false-variable*
|
||||||
|
v:false Special value used to put "false" in JSON and msgpack. See
|
||||||
|
|jsonencode()|. 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* *fcs_reason-variable*
|
||||||
v:fcs_reason The reason why the |FileChangedShell| event was triggered.
|
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
|
Can be used in an autocommand to decide what to do and/or what
|
||||||
@@ -1557,6 +1564,20 @@ v:msgpack_types Dictionary containing msgpack types used by |msgpackparse()|
|
|||||||
(not editable) empty lists. To check whether some list is one
|
(not editable) empty lists. To check whether some list is one
|
||||||
of msgpack types, use |is| operator.
|
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 |jsonencode()|. 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:none* *none-variable*
|
||||||
|
v:none Special value used to put an empty item in JSON. See
|
||||||
|
|jsonencode()|. This value is converted to "none" 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* *oldfiles-variable*
|
||||||
v:oldfiles List of file names that is loaded from the |shada| file on
|
v:oldfiles List of file names that is loaded from the |shada| file on
|
||||||
startup. These are the files that Vim remembers marks for.
|
startup. These are the files that Vim remembers marks for.
|
||||||
@@ -1722,6 +1743,13 @@ v:throwpoint The point where the exception most recently caught and not
|
|||||||
:endtry
|
:endtry
|
||||||
< Output: "Exception from test.vim, line 2"
|
< Output: "Exception from test.vim, line 2"
|
||||||
|
|
||||||
|
*v:true* *true-variable*
|
||||||
|
v:true Special value used to put "true" in JSON and msgpack. See
|
||||||
|
|jsonencode()|. 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* *val-variable*
|
||||||
v:val Value of the current item of a |List| or |Dictionary|. Only
|
v:val Value of the current item of a |List| or |Dictionary|. Only
|
||||||
valid while evaluating the expression used with |map()| and
|
valid while evaluating the expression used with |map()| and
|
||||||
@@ -4832,8 +4860,8 @@ msgpackdump({list}) {Nvim} *msgpackdump()*
|
|||||||
(dictionary with zero items is represented by 0x80 byte in
|
(dictionary with zero items is represented by 0x80 byte in
|
||||||
messagepack).
|
messagepack).
|
||||||
|
|
||||||
Limitations: *E951* *E952*
|
Limitations: *E951* *E952* *E953*
|
||||||
1. |Funcref|s cannot be dumped.
|
1. |Funcref|s and |v:none| cannot be dumped.
|
||||||
2. Containers that reference themselves cannot be dumped.
|
2. Containers that reference themselves cannot be dumped.
|
||||||
3. Dictionary keys are always dumped as STR strings.
|
3. Dictionary keys are always dumped as STR strings.
|
||||||
4. Other strings are always dumped as BIN strings.
|
4. Other strings are always dumped as BIN strings.
|
||||||
|
@@ -651,6 +651,22 @@ static Object vim_to_object_rec(typval_T *obj, PMap(ptr_t) *lookup)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (obj->v_type) {
|
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:
|
||||||
|
case kSpecialVarNone: {
|
||||||
|
rv.type = kObjectTypeNil;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case VAR_STRING:
|
case VAR_STRING:
|
||||||
rv.type = kObjectTypeString;
|
rv.type = kObjectTypeString;
|
||||||
rv.data.string = cstr_to_string((char *) obj->vval.v_string);
|
rv.data.string = cstr_to_string((char *) obj->vval.v_string);
|
||||||
@@ -730,6 +746,10 @@ static Object vim_to_object_rec(typval_T *obj, PMap(ptr_t) *lookup)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VAR_UNKNOWN:
|
||||||
|
case VAR_FUNC:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@@ -8,10 +8,12 @@
|
|||||||
|
|
||||||
#include <msgpack.h>
|
#include <msgpack.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "nvim/encode.h"
|
#include "nvim/encode.h"
|
||||||
#include "nvim/buffer_defs.h" // vimconv_T
|
#include "nvim/buffer_defs.h" // vimconv_T
|
||||||
#include "nvim/eval.h"
|
#include "nvim/eval.h"
|
||||||
|
#include "nvim/eval_defs.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
@@ -53,6 +55,13 @@ typedef struct {
|
|||||||
/// Stack used to convert VimL values to messagepack.
|
/// Stack used to convert VimL values to messagepack.
|
||||||
typedef kvec_t(MPConvStackVal) MPConvStack;
|
typedef kvec_t(MPConvStackVal) MPConvStack;
|
||||||
|
|
||||||
|
const char *const encode_special_var_names[] = {
|
||||||
|
[kSpecialVarNull] = "null",
|
||||||
|
[kSpecialVarNone] = "none",
|
||||||
|
[kSpecialVarTrue] = "true",
|
||||||
|
[kSpecialVarFalse] = "false",
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "encode.c.generated.h"
|
# include "encode.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -355,7 +364,7 @@ static int name##_convert_one_value(firstargtype firstargname, \
|
|||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
case kSpecialVarNone: { \
|
case kSpecialVarNone: { \
|
||||||
CONV_NONE(); \
|
CONV_NONE_VAL(); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
@@ -558,8 +567,7 @@ scope int encode_vim_to_##name(firstargtype firstargname, typval_T *const tv, \
|
|||||||
const char *const objname) \
|
const char *const objname) \
|
||||||
FUNC_ATTR_WARN_UNUSED_RESULT \
|
FUNC_ATTR_WARN_UNUSED_RESULT \
|
||||||
{ \
|
{ \
|
||||||
current_copyID += COPYID_INC; \
|
const int copyID = get_copyID(); \
|
||||||
const int copyID = current_copyID; \
|
|
||||||
MPConvStack mpstack; \
|
MPConvStack mpstack; \
|
||||||
kv_init(mpstack); \
|
kv_init(mpstack); \
|
||||||
if (name##_convert_one_value(firstargname, &mpstack, tv, copyID, objname) \
|
if (name##_convert_one_value(firstargname, &mpstack, tv, copyID, objname) \
|
||||||
@@ -717,13 +725,13 @@ encode_vim_to_##name##_error_ret: \
|
|||||||
ga_concat(gap, "{}")
|
ga_concat(gap, "{}")
|
||||||
|
|
||||||
#define CONV_NIL() \
|
#define CONV_NIL() \
|
||||||
ga_append(gap, "v:null")
|
ga_concat(gap, "v:null")
|
||||||
|
|
||||||
#define CONV_BOOL(num) \
|
#define CONV_BOOL(num) \
|
||||||
ga_append(gap, ((num)? "v:true": "v:false"))
|
ga_concat(gap, ((num)? "v:true": "v:false"))
|
||||||
|
|
||||||
#define CONV_NONE() \
|
#define CONV_NONE_VAL() \
|
||||||
ga_append(gap, "v:none")
|
ga_concat(gap, "v:none")
|
||||||
|
|
||||||
#define CONV_UNSIGNED_NUMBER(num)
|
#define CONV_UNSIGNED_NUMBER(num)
|
||||||
|
|
||||||
@@ -1069,8 +1077,8 @@ static inline bool check_json_key(const typval_T *const tv)
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#undef CONV_NONE
|
#undef CONV_NONE_VAL
|
||||||
#define CONV_NONE()
|
#define CONV_NONE_VAL()
|
||||||
|
|
||||||
DEFINE_VIML_CONV_FUNCTIONS(static, json, garray_T *const, gap)
|
DEFINE_VIML_CONV_FUNCTIONS(static, json, garray_T *const, gap)
|
||||||
|
|
||||||
@@ -1085,7 +1093,7 @@ DEFINE_VIML_CONV_FUNCTIONS(static, json, garray_T *const, gap)
|
|||||||
#undef CONV_EMPTY_DICT
|
#undef CONV_EMPTY_DICT
|
||||||
#undef CONV_NIL
|
#undef CONV_NIL
|
||||||
#undef CONV_BOOL
|
#undef CONV_BOOL
|
||||||
#undef CONV_NONE
|
#undef CONV_NONE_VAL
|
||||||
#undef CONV_UNSIGNED_NUMBER
|
#undef CONV_UNSIGNED_NUMBER
|
||||||
#undef CONV_DICT_START
|
#undef CONV_DICT_START
|
||||||
#undef CONV_DICT_END
|
#undef CONV_DICT_END
|
||||||
@@ -1221,7 +1229,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)
|
|||||||
#define CONV_NIL() \
|
#define CONV_NIL() \
|
||||||
msgpack_pack_nil(packer)
|
msgpack_pack_nil(packer)
|
||||||
|
|
||||||
#define CONV_NONE() \
|
#define CONV_NONE_VAL() \
|
||||||
return conv_error(_("E953: Attempt to convert v:none in %s, %s"), \
|
return conv_error(_("E953: Attempt to convert v:none in %s, %s"), \
|
||||||
mpstack, objname)
|
mpstack, objname)
|
||||||
|
|
||||||
@@ -1272,6 +1280,7 @@ DEFINE_VIML_CONV_FUNCTIONS(, msgpack, msgpack_packer *const, packer)
|
|||||||
#undef CONV_EMPTY_DICT
|
#undef CONV_EMPTY_DICT
|
||||||
#undef CONV_NIL
|
#undef CONV_NIL
|
||||||
#undef CONV_BOOL
|
#undef CONV_BOOL
|
||||||
|
#undef CONV_NONE_VAL
|
||||||
#undef CONV_UNSIGNED_NUMBER
|
#undef CONV_UNSIGNED_NUMBER
|
||||||
#undef CONV_DICT_START
|
#undef CONV_DICT_START
|
||||||
#undef CONV_DICT_END
|
#undef CONV_DICT_END
|
||||||
|
@@ -51,6 +51,9 @@ static inline ListReaderState encode_init_lrstate(const list_T *const list)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Array mapping values from SpecialVarValue enum to names
|
||||||
|
extern const char *const encode_special_var_names[];
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "encode.h.generated.h"
|
# include "encode.h.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
163
src/nvim/eval.c
163
src/nvim/eval.c
@@ -178,8 +178,6 @@ static dictitem_T globvars_var; /* variable used for g: */
|
|||||||
*/
|
*/
|
||||||
static hashtab_T compat_hashtab;
|
static hashtab_T compat_hashtab;
|
||||||
|
|
||||||
int current_copyID = 0;
|
|
||||||
|
|
||||||
hashtab_T func_hashtab;
|
hashtab_T func_hashtab;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -366,11 +364,16 @@ static struct vimvar {
|
|||||||
{ VV_NAME("errors", VAR_LIST), 0 },
|
{ VV_NAME("errors", VAR_LIST), 0 },
|
||||||
{ VV_NAME("msgpack_types", VAR_DICT), VV_RO },
|
{ VV_NAME("msgpack_types", VAR_DICT), VV_RO },
|
||||||
{ VV_NAME("event", VAR_DICT), VV_RO },
|
{ VV_NAME("event", VAR_DICT), VV_RO },
|
||||||
|
{ VV_NAME("false", VAR_SPECIAL), VV_RO },
|
||||||
|
{ VV_NAME("true", VAR_SPECIAL), VV_RO },
|
||||||
|
{ VV_NAME("null", VAR_SPECIAL), VV_RO },
|
||||||
|
{ VV_NAME("none", VAR_SPECIAL), VV_RO },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* shorthand */
|
/* shorthand */
|
||||||
#define vv_type vv_di.di_tv.v_type
|
#define vv_type vv_di.di_tv.v_type
|
||||||
#define vv_nr vv_di.di_tv.vval.v_number
|
#define vv_nr vv_di.di_tv.vval.v_number
|
||||||
|
#define vv_special vv_di.di_tv.vval.v_special
|
||||||
#define vv_float vv_di.di_tv.vval.v_float
|
#define vv_float vv_di.di_tv.vval.v_float
|
||||||
#define vv_str vv_di.di_tv.vval.v_string
|
#define vv_str vv_di.di_tv.vval.v_string
|
||||||
#define vv_list vv_di.di_tv.vval.v_list
|
#define vv_list vv_di.di_tv.vval.v_list
|
||||||
@@ -506,7 +509,13 @@ void eval_init(void)
|
|||||||
set_vim_var_list(VV_ERRORS, list_alloc());
|
set_vim_var_list(VV_ERRORS, list_alloc());
|
||||||
set_vim_var_nr(VV_SEARCHFORWARD, 1L);
|
set_vim_var_nr(VV_SEARCHFORWARD, 1L);
|
||||||
set_vim_var_nr(VV_HLSEARCH, 1L);
|
set_vim_var_nr(VV_HLSEARCH, 1L);
|
||||||
set_reg_var(0); /* default for v:register is not 0 but '"' */
|
|
||||||
|
set_vim_var_special(VV_FALSE, kSpecialVarFalse);
|
||||||
|
set_vim_var_special(VV_TRUE, kSpecialVarTrue);
|
||||||
|
set_vim_var_special(VV_NONE, kSpecialVarNone);
|
||||||
|
set_vim_var_special(VV_NULL, kSpecialVarNull);
|
||||||
|
|
||||||
|
set_reg_var(0); // default for v:register is not 0 but '"'
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(EXITFREE)
|
#if defined(EXITFREE)
|
||||||
@@ -2368,11 +2377,12 @@ static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
|
|||||||
char_u numbuf[NUMBUFLEN];
|
char_u numbuf[NUMBUFLEN];
|
||||||
char_u *s;
|
char_u *s;
|
||||||
|
|
||||||
/* Can't do anything with a Funcref or a Dict on the right. */
|
// Can't do anything with a Funcref, a Dict or special value on the right.
|
||||||
if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) {
|
if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) {
|
||||||
switch (tv1->v_type) {
|
switch (tv1->v_type) {
|
||||||
case VAR_DICT:
|
case VAR_DICT:
|
||||||
case VAR_FUNC:
|
case VAR_FUNC:
|
||||||
|
case VAR_SPECIAL:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VAR_LIST:
|
case VAR_LIST:
|
||||||
@@ -2440,6 +2450,9 @@ static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
|
|||||||
tv1->vval.v_float -= f;
|
tv1->vval.v_float -= f;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
|
case VAR_UNKNOWN:
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3077,6 +3090,15 @@ static void item_lock(typval_T *tv, int deep, int lock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case VAR_NUMBER:
|
||||||
|
case VAR_FLOAT:
|
||||||
|
case VAR_STRING:
|
||||||
|
case VAR_FUNC:
|
||||||
|
case VAR_SPECIAL:
|
||||||
|
break;
|
||||||
|
case VAR_UNKNOWN:
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
--recurse;
|
--recurse;
|
||||||
}
|
}
|
||||||
@@ -4306,6 +4328,11 @@ eval_index (
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
EMSG(_(e_float_as_string));
|
EMSG(_(e_float_as_string));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
} else if (rettv->v_type == VAR_SPECIAL) {
|
||||||
|
if (verbose) {
|
||||||
|
EMSG(_("E15: Cannot index a special value"));
|
||||||
|
}
|
||||||
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_tv(&var1);
|
init_tv(&var1);
|
||||||
@@ -4496,6 +4523,11 @@ eval_index (
|
|||||||
*rettv = var1;
|
*rettv = var1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case VAR_FUNC:
|
||||||
|
case VAR_FLOAT:
|
||||||
|
case VAR_UNKNOWN:
|
||||||
|
case VAR_SPECIAL:
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5040,6 +5072,12 @@ tv_equal (
|
|||||||
s1 = get_tv_string_buf(tv1, buf1);
|
s1 = get_tv_string_buf(tv1, buf1);
|
||||||
s2 = get_tv_string_buf(tv2, buf2);
|
s2 = get_tv_string_buf(tv2, buf2);
|
||||||
return (ic ? mb_stricmp(s1, s2) : STRCMP(s1, s2)) == 0;
|
return (ic ? mb_stricmp(s1, s2) : STRCMP(s1, s2)) == 0;
|
||||||
|
|
||||||
|
case VAR_SPECIAL:
|
||||||
|
return tv1->vval.v_special == tv2->vval.v_special;
|
||||||
|
|
||||||
|
case VAR_UNKNOWN:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSG2(_(e_intern2), "tv_equal()");
|
EMSG2(_(e_intern2), "tv_equal()");
|
||||||
@@ -5505,6 +5543,22 @@ static int list_join(garray_T *const gap, list_T *const l,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get next (unique) copy ID
|
||||||
|
///
|
||||||
|
/// Used for traversing nested structures e.g. when serializing them or garbage
|
||||||
|
/// collecting.
|
||||||
|
int get_copyID(void)
|
||||||
|
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||||
|
{
|
||||||
|
// CopyID for recursively traversing lists and dicts
|
||||||
|
//
|
||||||
|
// This value is needed to avoid endless recursiveness. Last bit is used for
|
||||||
|
// previous_funccal and normally ignored when comparing.
|
||||||
|
static int current_copyID = 0;
|
||||||
|
current_copyID += COPYID_INC;
|
||||||
|
return current_copyID;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Garbage collection for lists and dictionaries.
|
* Garbage collection for lists and dictionaries.
|
||||||
*
|
*
|
||||||
@@ -5540,8 +5594,7 @@ bool garbage_collect(void)
|
|||||||
|
|
||||||
// We advance by two because we add one for items referenced through
|
// We advance by two because we add one for items referenced through
|
||||||
// previous_funccal.
|
// previous_funccal.
|
||||||
current_copyID += COPYID_INC;
|
const int copyID = get_copyID();
|
||||||
int copyID = current_copyID;
|
|
||||||
|
|
||||||
// 1. Go through all accessible variables and mark all lists and dicts
|
// 1. Go through all accessible variables and mark all lists and dicts
|
||||||
// with copyID.
|
// with copyID.
|
||||||
@@ -5886,6 +5939,15 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case VAR_FUNC:
|
||||||
|
case VAR_UNKNOWN:
|
||||||
|
case VAR_SPECIAL:
|
||||||
|
case VAR_FLOAT:
|
||||||
|
case VAR_NUMBER:
|
||||||
|
case VAR_STRING: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return abort;
|
return abort;
|
||||||
}
|
}
|
||||||
@@ -8260,9 +8322,8 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv)
|
|||||||
if (noref < 0 || noref > 1)
|
if (noref < 0 || noref > 1)
|
||||||
EMSG(_(e_invarg));
|
EMSG(_(e_invarg));
|
||||||
else {
|
else {
|
||||||
current_copyID += COPYID_INC;
|
|
||||||
var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0
|
var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0
|
||||||
? current_copyID
|
? get_copyID()
|
||||||
: 0));
|
: 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8477,7 +8538,7 @@ static void f_empty(typval_T *argvars, typval_T *rettv)
|
|||||||
case VAR_SPECIAL:
|
case VAR_SPECIAL:
|
||||||
n = argvars[0].vval.v_special != kSpecialVarTrue;
|
n = argvars[0].vval.v_special != kSpecialVarTrue;
|
||||||
break;
|
break;
|
||||||
default:
|
case VAR_UNKNOWN:
|
||||||
EMSG2(_(e_intern2), "f_empty()");
|
EMSG2(_(e_intern2), "f_empty()");
|
||||||
n = 0;
|
n = 0;
|
||||||
}
|
}
|
||||||
@@ -16392,7 +16453,22 @@ static void f_type(typval_T *argvars, typval_T *rettv)
|
|||||||
case VAR_LIST: n = 3; break;
|
case VAR_LIST: n = 3; break;
|
||||||
case VAR_DICT: n = 4; break;
|
case VAR_DICT: n = 4; break;
|
||||||
case VAR_FLOAT: n = 5; break;
|
case VAR_FLOAT: n = 5; break;
|
||||||
default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
|
case VAR_SPECIAL: {
|
||||||
|
switch (argvars[0].vval.v_special) {
|
||||||
|
case kSpecialVarTrue:
|
||||||
|
case kSpecialVarFalse: {
|
||||||
|
n = 6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kSpecialVarNone:
|
||||||
|
case kSpecialVarNull: {
|
||||||
|
n = 7;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VAR_UNKNOWN: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
|
||||||
}
|
}
|
||||||
rettv->vval.v_number = n;
|
rettv->vval.v_number = n;
|
||||||
}
|
}
|
||||||
@@ -17226,6 +17302,12 @@ void set_vim_var_nr(int idx, long val)
|
|||||||
vimvars[idx].vv_nr = val;
|
vimvars[idx].vv_nr = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set special v: variable to "val"
|
||||||
|
void set_vim_var_special(const int idx, const SpecialVarValue val)
|
||||||
|
{
|
||||||
|
vimvars[idx].vv_special = val;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get number v: variable value.
|
* Get number v: variable value.
|
||||||
*/
|
*/
|
||||||
@@ -17574,7 +17656,7 @@ handle_subscript (
|
|||||||
void free_tv(typval_T *varp)
|
void free_tv(typval_T *varp)
|
||||||
{
|
{
|
||||||
if (varp != NULL) {
|
if (varp != NULL) {
|
||||||
switch ((VarType) varp->v_type) {
|
switch (varp->v_type) {
|
||||||
case VAR_FUNC:
|
case VAR_FUNC:
|
||||||
func_unref(varp->vval.v_string);
|
func_unref(varp->vval.v_string);
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
@@ -17592,9 +17674,6 @@ void free_tv(typval_T *varp)
|
|||||||
case VAR_FLOAT:
|
case VAR_FLOAT:
|
||||||
case VAR_UNKNOWN:
|
case VAR_UNKNOWN:
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
EMSG2(_(e_intern2), "free_tv()");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
xfree(varp);
|
xfree(varp);
|
||||||
}
|
}
|
||||||
@@ -17632,10 +17711,11 @@ void clear_tv(typval_T *varp)
|
|||||||
case VAR_FLOAT:
|
case VAR_FLOAT:
|
||||||
varp->vval.v_float = 0.0;
|
varp->vval.v_float = 0.0;
|
||||||
break;
|
break;
|
||||||
|
case VAR_SPECIAL:
|
||||||
|
varp->vval.v_special = kSpecialVarFalse;
|
||||||
|
break;
|
||||||
case VAR_UNKNOWN:
|
case VAR_UNKNOWN:
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
EMSG2(_(e_intern2), "clear_tv()");
|
|
||||||
}
|
}
|
||||||
varp->v_lock = 0;
|
varp->v_lock = 0;
|
||||||
}
|
}
|
||||||
@@ -17690,7 +17770,19 @@ long get_tv_number_chk(typval_T *varp, int *denote)
|
|||||||
case VAR_DICT:
|
case VAR_DICT:
|
||||||
EMSG(_("E728: Using a Dictionary as a Number"));
|
EMSG(_("E728: Using a Dictionary as a Number"));
|
||||||
break;
|
break;
|
||||||
default:
|
case VAR_SPECIAL:
|
||||||
|
switch (varp->vval.v_special) {
|
||||||
|
case kSpecialVarTrue: {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
case kSpecialVarFalse:
|
||||||
|
case kSpecialVarNone:
|
||||||
|
case kSpecialVarNull: {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VAR_UNKNOWN:
|
||||||
EMSG2(_(e_intern2), "get_tv_number()");
|
EMSG2(_(e_intern2), "get_tv_number()");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -17796,7 +17888,10 @@ static char_u *get_tv_string_buf_chk(const typval_T *varp, char_u *buf)
|
|||||||
if (varp->vval.v_string != NULL)
|
if (varp->vval.v_string != NULL)
|
||||||
return varp->vval.v_string;
|
return varp->vval.v_string;
|
||||||
return (char_u *)"";
|
return (char_u *)"";
|
||||||
default:
|
case VAR_SPECIAL:
|
||||||
|
STRCPY(buf, encode_special_var_names[varp->vval.v_special]);
|
||||||
|
return buf;
|
||||||
|
case VAR_UNKNOWN:
|
||||||
EMSG2(_(e_intern2), "get_tv_string_buf()");
|
EMSG2(_(e_intern2), "get_tv_string_buf()");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -18345,40 +18440,32 @@ void copy_tv(typval_T *from, typval_T *to)
|
|||||||
{
|
{
|
||||||
to->v_type = from->v_type;
|
to->v_type = from->v_type;
|
||||||
to->v_lock = 0;
|
to->v_lock = 0;
|
||||||
|
memmove(&to->vval, &from->vval, sizeof(to->vval));
|
||||||
switch (from->v_type) {
|
switch (from->v_type) {
|
||||||
case VAR_NUMBER:
|
case VAR_NUMBER:
|
||||||
to->vval.v_number = from->vval.v_number;
|
|
||||||
break;
|
|
||||||
case VAR_FLOAT:
|
case VAR_FLOAT:
|
||||||
to->vval.v_float = from->vval.v_float;
|
case VAR_SPECIAL:
|
||||||
break;
|
break;
|
||||||
case VAR_STRING:
|
case VAR_STRING:
|
||||||
case VAR_FUNC:
|
case VAR_FUNC:
|
||||||
if (from->vval.v_string == NULL)
|
if (from->vval.v_string != NULL) {
|
||||||
to->vval.v_string = NULL;
|
|
||||||
else {
|
|
||||||
to->vval.v_string = vim_strsave(from->vval.v_string);
|
to->vval.v_string = vim_strsave(from->vval.v_string);
|
||||||
if (from->v_type == VAR_FUNC)
|
if (from->v_type == VAR_FUNC) {
|
||||||
func_ref(to->vval.v_string);
|
func_ref(to->vval.v_string);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case VAR_LIST:
|
case VAR_LIST:
|
||||||
if (from->vval.v_list == NULL)
|
if (from->vval.v_list != NULL) {
|
||||||
to->vval.v_list = NULL;
|
to->vval.v_list->lv_refcount++;
|
||||||
else {
|
|
||||||
to->vval.v_list = from->vval.v_list;
|
|
||||||
++to->vval.v_list->lv_refcount;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VAR_DICT:
|
case VAR_DICT:
|
||||||
if (from->vval.v_dict == NULL)
|
if (from->vval.v_dict != NULL) {
|
||||||
to->vval.v_dict = NULL;
|
to->vval.v_dict->dv_refcount++;
|
||||||
else {
|
|
||||||
to->vval.v_dict = from->vval.v_dict;
|
|
||||||
++to->vval.v_dict->dv_refcount;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
case VAR_UNKNOWN:
|
||||||
EMSG2(_(e_intern2), "copy_tv()");
|
EMSG2(_(e_intern2), "copy_tv()");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -18420,6 +18507,7 @@ int var_item_copy(const vimconv_T *const conv,
|
|||||||
case VAR_NUMBER:
|
case VAR_NUMBER:
|
||||||
case VAR_FLOAT:
|
case VAR_FLOAT:
|
||||||
case VAR_FUNC:
|
case VAR_FUNC:
|
||||||
|
case VAR_SPECIAL:
|
||||||
copy_tv(from, to);
|
copy_tv(from, to);
|
||||||
break;
|
break;
|
||||||
case VAR_STRING:
|
case VAR_STRING:
|
||||||
@@ -18466,7 +18554,7 @@ int var_item_copy(const vimconv_T *const conv,
|
|||||||
if (to->vval.v_dict == NULL)
|
if (to->vval.v_dict == NULL)
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
break;
|
break;
|
||||||
default:
|
case VAR_UNKNOWN:
|
||||||
EMSG2(_(e_intern2), "var_item_copy()");
|
EMSG2(_(e_intern2), "var_item_copy()");
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
}
|
}
|
||||||
@@ -21705,4 +21793,3 @@ static bool is_watched(dict_T *d)
|
|||||||
{
|
{
|
||||||
return d && !QUEUE_EMPTY(&d->watchers);
|
return d && !QUEUE_EMPTY(&d->watchers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,12 +15,6 @@
|
|||||||
// All user-defined functions are found in this hashtable.
|
// All user-defined functions are found in this hashtable.
|
||||||
extern hashtab_T func_hashtab;
|
extern hashtab_T func_hashtab;
|
||||||
|
|
||||||
/// CopyID for recursively traversing lists and dicts
|
|
||||||
///
|
|
||||||
/// This value is needed to avoid endless recursiveness. Last bit is used for
|
|
||||||
/// previous_funccal and normally ignored when comparing.
|
|
||||||
extern int current_copyID;
|
|
||||||
|
|
||||||
// Structure to hold info for a user function.
|
// Structure to hold info for a user function.
|
||||||
typedef struct ufunc ufunc_T;
|
typedef struct ufunc ufunc_T;
|
||||||
|
|
||||||
@@ -127,7 +121,11 @@ enum {
|
|||||||
VV_ERRORS,
|
VV_ERRORS,
|
||||||
VV_MSGPACK_TYPES,
|
VV_MSGPACK_TYPES,
|
||||||
VV_EVENT,
|
VV_EVENT,
|
||||||
VV_LEN, // number of v: vars
|
VV_FALSE,
|
||||||
|
VV_TRUE,
|
||||||
|
VV_NULL,
|
||||||
|
VV_NONE,
|
||||||
|
VV_LEN, ///< Number of v: variables
|
||||||
};
|
};
|
||||||
|
|
||||||
/// All recognized msgpack types
|
/// All recognized msgpack types
|
||||||
|
@@ -18,12 +18,32 @@ typedef struct dictvar_S dict_T;
|
|||||||
|
|
||||||
/// Special variable values
|
/// Special variable values
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kSpecialVarNull, ///< v:null
|
|
||||||
kSpecialVarNone, ///< v:none
|
|
||||||
kSpecialVarFalse, ///< v:false
|
kSpecialVarFalse, ///< v:false
|
||||||
kSpecialVarTrue, ///< v:true
|
kSpecialVarTrue, ///< v:true
|
||||||
|
kSpecialVarNone, ///< v:none
|
||||||
|
kSpecialVarNull, ///< v:null
|
||||||
} SpecialVarValue;
|
} SpecialVarValue;
|
||||||
|
|
||||||
|
/// 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, none), .v_special
|
||||||
|
///< is used.
|
||||||
|
} VarType;
|
||||||
|
|
||||||
/// Structure that holds an internal variable value
|
/// Structure that holds an internal variable value
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VarType v_type; ///< Variable type.
|
VarType v_type; ///< Variable type.
|
||||||
@@ -38,34 +58,11 @@ typedef struct {
|
|||||||
} vval; ///< Actual value.
|
} vval; ///< Actual value.
|
||||||
} typval_T;
|
} typval_T;
|
||||||
|
|
||||||
/// VimL variable types, for use in typval_T.v_type
|
|
||||||
///
|
|
||||||
/// @warning Numbers are part of the user API (returned by type()), so they must
|
|
||||||
/// not be changed.
|
|
||||||
typedef enum {
|
|
||||||
VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
|
|
||||||
VAR_NUMBER = 1, ///< Number, .v_number is used.
|
|
||||||
VAR_STRING = 2, ///< String, .v_string is used.
|
|
||||||
VAR_FUNC = 3, ///< Function referene, .v_string is used for function name.
|
|
||||||
VAR_LIST = 4, ///< List, .v_list is used.
|
|
||||||
VAR_DICT = 5, ///< Dictionary, .v_dict is used.
|
|
||||||
VAR_FLOAT = 6, ///< Floating-point value, .v_float is used.
|
|
||||||
VAR_SPECIAL = 7, ///< Special value (true, false, null, none), .v_special
|
|
||||||
///< is used.
|
|
||||||
} VarType;
|
|
||||||
|
|
||||||
/* Values for "dv_scope". */
|
/* Values for "dv_scope". */
|
||||||
#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */
|
#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */
|
||||||
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
|
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
|
||||||
allowed to mask existing functions */
|
allowed to mask existing functions */
|
||||||
|
|
||||||
/// 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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure to hold an item of a list: an internal variable without a name.
|
* Structure to hold an item of a list: an internal variable without a name.
|
||||||
*/
|
*/
|
||||||
|
@@ -195,18 +195,18 @@ static int included_patches[] = {
|
|||||||
// 1170 NA
|
// 1170 NA
|
||||||
// 1169 NA
|
// 1169 NA
|
||||||
1168,
|
1168,
|
||||||
// 1167,
|
1167,
|
||||||
// 1166,
|
1166,
|
||||||
// 1165 NA
|
// 1165 NA
|
||||||
// 1164,
|
1164,
|
||||||
// 1163,
|
1163,
|
||||||
// 1162 NA
|
// 1162 NA
|
||||||
// 1161,
|
// 1161,
|
||||||
// 1160,
|
1160,
|
||||||
// 1159 NA
|
// 1159 NA
|
||||||
// 1158 NA
|
// 1158 NA
|
||||||
// 1157,
|
1157,
|
||||||
// 1156,
|
// 1156 NA
|
||||||
// 1155 NA
|
// 1155 NA
|
||||||
// 1154,
|
// 1154,
|
||||||
// 1153,
|
// 1153,
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
local helpers = require('test.functional.helpers')
|
local helpers = require('test.functional.helpers')
|
||||||
local clear = helpers.clear
|
local clear = helpers.clear
|
||||||
|
local funcs = helpers.funcs
|
||||||
local eval, eq = helpers.eval, helpers.eq
|
local eval, eq = helpers.eval, helpers.eq
|
||||||
local execute = helpers.execute
|
local execute = helpers.execute
|
||||||
local nvim = helpers.nvim
|
local nvim = helpers.nvim
|
||||||
@@ -517,6 +518,19 @@ describe('msgpackdump() function', function()
|
|||||||
eq({'\129\128\128'}, eval('msgpackdump([todump])'))
|
eq({'\129\128\128'}, eval('msgpackdump([todump])'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
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')
|
||||||
|
eq({'\192'}, eval('msgpackdump([todump])'))
|
||||||
|
end)
|
||||||
|
|
||||||
it('can dump special ext mapping', function()
|
it('can dump special ext mapping', function()
|
||||||
execute('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
|
execute('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
|
||||||
eq({'\212\005', ''}, eval('msgpackdump([todump])'))
|
eq({'\212\005', ''}, eval('msgpackdump([todump])'))
|
||||||
@@ -620,6 +634,11 @@ describe('msgpackdump() function', function()
|
|||||||
exc_exec('call msgpackdump([todump])'))
|
exc_exec('call msgpackdump([todump])'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('fails to dump v:none', function()
|
||||||
|
eq('Vim(call):E953: Attempt to convert v:none in msgpackdump() argument, index 0, itself',
|
||||||
|
exc_exec('call msgpackdump([v:none])'))
|
||||||
|
end)
|
||||||
|
|
||||||
it('fails when called with no arguments', function()
|
it('fails when called with no arguments', function()
|
||||||
eq('Vim(call):E119: Not enough arguments for function: msgpackdump',
|
eq('Vim(call):E119: Not enough arguments for function: msgpackdump',
|
||||||
exc_exec('call msgpackdump()'))
|
exc_exec('call msgpackdump()'))
|
||||||
@@ -654,4 +673,11 @@ describe('msgpackdump() function', function()
|
|||||||
eq('Vim(call):E686: Argument of msgpackdump() must be a List',
|
eq('Vim(call):E686: Argument of msgpackdump() must be a List',
|
||||||
exc_exec('call msgpackdump(0.0)'))
|
exc_exec('call msgpackdump(0.0)'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('fails to dump special value', function()
|
||||||
|
for _, val in ipairs({'v:true', 'v:false', 'v:null', 'v:none'}) do
|
||||||
|
eq('Vim(call):E686: Argument of msgpackdump() must be a List',
|
||||||
|
exc_exec('call msgpackdump(' .. val .. ')'))
|
||||||
|
end
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
@@ -1,8 +1,12 @@
|
|||||||
local helpers = require('test.functional.helpers')
|
local helpers = require('test.functional.helpers')
|
||||||
|
local exc_exec = helpers.exc_exec
|
||||||
local execute = helpers.execute
|
local execute = helpers.execute
|
||||||
|
local meths = helpers.meths
|
||||||
local funcs = helpers.funcs
|
local funcs = helpers.funcs
|
||||||
|
local meths = helpers.meths
|
||||||
local clear = helpers.clear
|
local clear = helpers.clear
|
||||||
local eval = helpers.eval
|
local eval = helpers.eval
|
||||||
|
local eq = helpers.eq
|
||||||
|
|
||||||
describe('Special values', function()
|
describe('Special values', function()
|
||||||
before_each(clear)
|
before_each(clear)
|
||||||
@@ -17,20 +21,166 @@ describe('Special values', function()
|
|||||||
endtry
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
]])
|
]])
|
||||||
eq(true, funcs.Test())
|
eq(0, exc_exec('call Test()'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('work with empty()', function()
|
it('work with empty()', function()
|
||||||
eq(0, funcs.empty(true))
|
eq(0, funcs.empty(true))
|
||||||
eq(1, funcs.empty(false))
|
eq(1, funcs.empty(false))
|
||||||
eq(1, funcs.empty(nil))
|
eq(1, eval('empty(v:null)'))
|
||||||
eq(1, eval('empty(v:none)'))
|
eq(1, eval('empty(v:none)'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('can be stringified and eval’ed back', function()
|
it('can be stringified and eval’ed back', function()
|
||||||
eq(true, funcs.eval(funcs.string(true)))
|
eq(true, funcs.eval(funcs.string(true)))
|
||||||
eq(false, funcs.eval(funcs.string(false)))
|
eq(false, funcs.eval(funcs.string(false)))
|
||||||
eq(nil, funcs.eval(funcs.string(nil)))
|
eq(nil, eval('eval(string(v:null))'))
|
||||||
eq(1, eval('eval(string(v:none)) is# v:none'))
|
eq(1, eval('eval(string(v:none)) is# v:none'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('work with is/isnot properly', function()
|
||||||
|
eq(1, eval('v:none is v:none'))
|
||||||
|
eq(0, eval('v:none is v:null'))
|
||||||
|
eq(0, eval('v:none is v:true'))
|
||||||
|
eq(0, eval('v:none is v:false'))
|
||||||
|
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:none is 0'))
|
||||||
|
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:none is 1'))
|
||||||
|
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:none is ""'))
|
||||||
|
eq(0, eval('v:null is ""'))
|
||||||
|
eq(0, eval('v:true is ""'))
|
||||||
|
eq(0, eval('v:false is ""'))
|
||||||
|
|
||||||
|
eq(0, eval('v:none is "none"'))
|
||||||
|
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:none is []'))
|
||||||
|
eq(0, eval('v:null is []'))
|
||||||
|
eq(0, eval('v:true is []'))
|
||||||
|
eq(0, eval('v:false is []'))
|
||||||
|
|
||||||
|
eq(0, eval('v:none isnot v:none'))
|
||||||
|
eq(1, eval('v:none isnot v:null'))
|
||||||
|
eq(1, eval('v:none isnot v:true'))
|
||||||
|
eq(1, eval('v:none isnot v:false'))
|
||||||
|
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:none isnot 0'))
|
||||||
|
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:none isnot 1'))
|
||||||
|
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:none isnot ""'))
|
||||||
|
eq(1, eval('v:null isnot ""'))
|
||||||
|
eq(1, eval('v:true isnot ""'))
|
||||||
|
eq(1, eval('v:false isnot ""'))
|
||||||
|
|
||||||
|
eq(1, eval('v:none isnot "none"'))
|
||||||
|
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:none isnot []'))
|
||||||
|
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:none'))
|
||||||
|
eq(0, eval('0 + v:null'))
|
||||||
|
eq(0, eval('0 + v:false'))
|
||||||
|
|
||||||
|
eq(-1, eval('0 - v:true'))
|
||||||
|
eq( 0, eval('0 - v:none'))
|
||||||
|
eq( 0, eval('0 - v:null'))
|
||||||
|
eq( 0, eval('0 - v:false'))
|
||||||
|
|
||||||
|
eq(1, eval('1 * v:true'))
|
||||||
|
eq(0, eval('1 * v:none'))
|
||||||
|
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 none = v:none')
|
||||||
|
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 none += 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 none -= 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 none .= 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("none", eval('"" . v:none'))
|
||||||
|
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, eval('type(v:null)'))
|
||||||
|
eq(7, eval('type(v:none)'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('work with copy() and deepcopy()', function()
|
||||||
|
eq(true, funcs.deepcopy(true))
|
||||||
|
eq(false, funcs.deepcopy(false))
|
||||||
|
eq(nil, eval('deepcopy(v:null)'))
|
||||||
|
eq(nil, eval('deepcopy(v:none)'))
|
||||||
|
|
||||||
|
eq(true, funcs.copy(true))
|
||||||
|
eq(false, funcs.copy(false))
|
||||||
|
eq(nil, eval('copy(v:null)'))
|
||||||
|
eq(nil, eval('copy(v:none)'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('fails in index', function()
|
||||||
|
eq('Vim(echo):E15: Cannot index a special value', exc_exec('echo v:true[0]'))
|
||||||
|
eq('Vim(echo):E15: Cannot index a special value', exc_exec('echo v:false[0]'))
|
||||||
|
eq('Vim(echo):E15: Cannot index a special value', exc_exec('echo v:none[0]'))
|
||||||
|
eq('Vim(echo):E15: Cannot index a special value', exc_exec('echo v:null[0]'))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
@@ -28,6 +28,13 @@ describe('string() function', function()
|
|||||||
eq('0.0', eval('string(0.0)'))
|
eq('0.0', eval('string(0.0)'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('dumps special v: values', function()
|
||||||
|
eq('v:true', eval('string(v:true)'))
|
||||||
|
eq('v:false', eval('string(v:false)'))
|
||||||
|
eq('v:none', eval('string(v:none)'))
|
||||||
|
eq('v:null', eval('string(v:null)'))
|
||||||
|
end)
|
||||||
|
|
||||||
it('dumps values with at most six digits after the decimal point',
|
it('dumps values with at most six digits after the decimal point',
|
||||||
function()
|
function()
|
||||||
eq('1.234568e-20', funcs.string(1.23456789123456789123456789e-020))
|
eq('1.234568e-20', funcs.string(1.23456789123456789123456789e-020))
|
||||||
|
Reference in New Issue
Block a user