mirror of
https://github.com/neovim/neovim.git
synced 2025-09-15 07:48:18 +00:00
eval: Move get_tv_lnum and get_tv_float to eval/typval.h
Additionally - Rename former tv_get_float to tv_get_float_chk due to name conflict (former get_tv_float is better suited for being tv_get_float). - Add E907 error to get_tv_float() and test that it is being raised when appropriate.
This commit is contained in:
265
src/nvim/eval.c
265
src/nvim/eval.c
@@ -6498,7 +6498,7 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
float_T (*function)(float_T) = (float_T (*)(float_T))fptr;
|
||||
|
||||
rettv->v_type = VAR_FLOAT;
|
||||
if (tv_get_float(argvars, &f)) {
|
||||
if (tv_get_float_chk(argvars, &f)) {
|
||||
rettv->vval.v_float = function(f);
|
||||
} else {
|
||||
rettv->vval.v_float = 0.0;
|
||||
@@ -6610,7 +6610,7 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
u_sync(TRUE);
|
||||
}
|
||||
|
||||
lnum = get_tv_lnum(argvars);
|
||||
lnum = tv_get_lnum(argvars);
|
||||
if (lnum >= 0
|
||||
&& lnum <= curbuf->b_ml.ml_line_count
|
||||
&& u_save(lnum, lnum + 1) == OK) {
|
||||
@@ -6957,7 +6957,7 @@ static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
float_T fy;
|
||||
|
||||
rettv->v_type = VAR_FLOAT;
|
||||
if (tv_get_float(argvars, &fx) && tv_get_float(&argvars[1], &fy)) {
|
||||
if (tv_get_float_chk(argvars, &fx) && tv_get_float_chk(&argvars[1], &fy)) {
|
||||
rettv->vval.v_float = atan2(fx, fy);
|
||||
} else {
|
||||
rettv->vval.v_float = 0.0;
|
||||
@@ -7333,7 +7333,7 @@ static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
linenr_T lnum;
|
||||
|
||||
pos = curwin->w_cursor;
|
||||
lnum = get_tv_lnum(argvars);
|
||||
lnum = tv_get_lnum(argvars);
|
||||
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) {
|
||||
curwin->w_cursor.lnum = lnum;
|
||||
rettv->vval.v_number = get_c_indent();
|
||||
@@ -7613,7 +7613,7 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
set_curswant = false;
|
||||
}
|
||||
} else {
|
||||
line = get_tv_lnum(argvars);
|
||||
line = tv_get_lnum(argvars);
|
||||
col = get_tv_number_chk(&argvars[1], NULL);
|
||||
if (argvars[2].v_type != VAR_UNKNOWN) {
|
||||
coladd = get_tv_number_chk(&argvars[2], NULL);
|
||||
@@ -7808,7 +7808,7 @@ static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
|
||||
rettv->vval.v_number = diff_check_fill(curwin, tv_get_lnum(argvars));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -7816,7 +7816,7 @@ static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
linenr_T lnum = get_tv_lnum(argvars);
|
||||
linenr_T lnum = tv_get_lnum(argvars);
|
||||
static linenr_T prev_lnum = 0;
|
||||
static int changedtick = 0;
|
||||
static int fnum = 0;
|
||||
@@ -8557,7 +8557,7 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
float_T f;
|
||||
|
||||
if (tv_get_float(argvars, &f)) {
|
||||
if (tv_get_float_chk(argvars, &f)) {
|
||||
if (f < VARNUMBER_MIN) {
|
||||
rettv->vval.v_number = VARNUMBER_MIN;
|
||||
} else if (f > VARNUMBER_MAX) {
|
||||
@@ -8577,7 +8577,7 @@ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
float_T fy;
|
||||
|
||||
rettv->v_type = VAR_FLOAT;
|
||||
if (tv_get_float(argvars, &fx) && tv_get_float(&argvars[1], &fy)) {
|
||||
if (tv_get_float_chk(argvars, &fx) && tv_get_float_chk(&argvars[1], &fy)) {
|
||||
rettv->vval.v_float = fmod(fx, fy);
|
||||
} else {
|
||||
rettv->vval.v_float = 0.0;
|
||||
@@ -8629,16 +8629,16 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end)
|
||||
{
|
||||
linenr_T lnum;
|
||||
linenr_T first, last;
|
||||
|
||||
lnum = get_tv_lnum(argvars);
|
||||
const linenr_T lnum = tv_get_lnum(argvars);
|
||||
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) {
|
||||
if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL)) {
|
||||
if (end)
|
||||
linenr_T first;
|
||||
linenr_T last;
|
||||
if (hasFoldingWin(curwin, lnum, &first, &last, false, NULL)) {
|
||||
if (end) {
|
||||
rettv->vval.v_number = (varnumber_T)last;
|
||||
else
|
||||
} else {
|
||||
rettv->vval.v_number = (varnumber_T)first;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -8666,11 +8666,10 @@ static void f_foldclosedend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
linenr_T lnum;
|
||||
|
||||
lnum = get_tv_lnum(argvars);
|
||||
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
|
||||
const linenr_T lnum = tv_get_lnum(argvars);
|
||||
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) {
|
||||
rettv->vval.v_number = foldLevel(lnum);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -8734,7 +8733,6 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
linenr_T lnum;
|
||||
char_u *text;
|
||||
char_u buf[51];
|
||||
foldinfo_T foldinfo;
|
||||
@@ -8742,10 +8740,11 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = NULL;
|
||||
lnum = get_tv_lnum(argvars);
|
||||
/* treat illegal types and illegal string values for {lnum} the same */
|
||||
if (lnum < 0)
|
||||
linenr_T lnum = tv_get_lnum(argvars);
|
||||
// Treat illegal types and illegal string values for {lnum} the same.
|
||||
if (lnum < 0) {
|
||||
lnum = 0;
|
||||
}
|
||||
fold_count = foldedCount(curwin, lnum, &foldinfo);
|
||||
if (fold_count > 0) {
|
||||
text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
|
||||
@@ -9782,17 +9781,16 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
linenr_T lnum;
|
||||
linenr_T end;
|
||||
int retlist;
|
||||
bool retlist;
|
||||
|
||||
lnum = get_tv_lnum(argvars);
|
||||
const linenr_T lnum = tv_get_lnum(argvars);
|
||||
if (argvars[1].v_type == VAR_UNKNOWN) {
|
||||
end = 0;
|
||||
retlist = FALSE;
|
||||
retlist = false;
|
||||
} else {
|
||||
end = get_tv_lnum(&argvars[1]);
|
||||
retlist = TRUE;
|
||||
end = tv_get_lnum(&argvars[1]);
|
||||
retlist = true;
|
||||
}
|
||||
|
||||
get_buffer_lines(curbuf, lnum, end, retlist, rettv);
|
||||
@@ -10920,13 +10918,12 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
linenr_T lnum;
|
||||
|
||||
lnum = get_tv_lnum(argvars);
|
||||
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
|
||||
const linenr_T lnum = tv_get_lnum(argvars);
|
||||
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) {
|
||||
rettv->vval.v_number = get_indent_lnum(lnum);
|
||||
else
|
||||
} else {
|
||||
rettv->vval.v_number = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -11975,15 +11972,15 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
linenr_T lnum;
|
||||
|
||||
lnum = get_tv_lnum(argvars);
|
||||
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
|
||||
const linenr_T lnum = tv_get_lnum(argvars);
|
||||
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) {
|
||||
rettv->vval.v_number = -1;
|
||||
else
|
||||
} else {
|
||||
rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
|
||||
if (rettv->vval.v_number >= 0)
|
||||
++rettv->vval.v_number;
|
||||
}
|
||||
if (rettv->vval.v_number >= 0) {
|
||||
rettv->vval.v_number++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -11991,17 +11988,15 @@ static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
pos_T pos;
|
||||
linenr_T lnum;
|
||||
|
||||
pos = curwin->w_cursor;
|
||||
lnum = get_tv_lnum(argvars);
|
||||
const pos_T pos = curwin->w_cursor;
|
||||
const linenr_T lnum = tv_get_lnum(argvars);
|
||||
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) {
|
||||
curwin->w_cursor.lnum = lnum;
|
||||
rettv->vval.v_number = get_lisp_indent();
|
||||
curwin->w_cursor = pos;
|
||||
} else
|
||||
} else {
|
||||
rettv->vval.v_number = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -12746,14 +12741,15 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
linenr_T lnum;
|
||||
|
||||
for (lnum = get_tv_lnum(argvars);; ++lnum) {
|
||||
for (lnum = tv_get_lnum(argvars);; lnum++) {
|
||||
if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count) {
|
||||
lnum = 0;
|
||||
break;
|
||||
}
|
||||
if (*skipwhite(ml_get(lnum)) != NUL)
|
||||
if (*skipwhite(ml_get(lnum)) != NUL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rettv->vval.v_number = lnum;
|
||||
}
|
||||
|
||||
@@ -12812,7 +12808,7 @@ static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
float_T fy;
|
||||
|
||||
rettv->v_type = VAR_FLOAT;
|
||||
if (tv_get_float(argvars, &fx) && tv_get_float(&argvars[1], &fy)) {
|
||||
if (tv_get_float_chk(argvars, &fx) && tv_get_float_chk(&argvars[1], &fy)) {
|
||||
rettv->vval.v_float = pow(fx, fy);
|
||||
} else {
|
||||
rettv->vval.v_float = 0.0;
|
||||
@@ -12824,14 +12820,14 @@ static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
linenr_T lnum;
|
||||
|
||||
lnum = get_tv_lnum(argvars);
|
||||
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
|
||||
linenr_T lnum = tv_get_lnum(argvars);
|
||||
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) {
|
||||
lnum = 0;
|
||||
else
|
||||
while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
|
||||
--lnum;
|
||||
} else {
|
||||
while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) {
|
||||
lnum--;
|
||||
}
|
||||
}
|
||||
rettv->vval.v_number = lnum;
|
||||
}
|
||||
|
||||
@@ -14428,14 +14424,13 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
linenr_T lnum;
|
||||
char_u *line = NULL;
|
||||
list_T *l = NULL;
|
||||
listitem_T *li = NULL;
|
||||
long added = 0;
|
||||
linenr_T lcount = curbuf->b_ml.ml_line_count;
|
||||
|
||||
lnum = get_tv_lnum(&argvars[0]);
|
||||
linenr_T lnum = tv_get_lnum(&argvars[0]);
|
||||
if (argvars[1].v_type == VAR_LIST) {
|
||||
l = argvars[1].vval.v_list;
|
||||
li = l->lv_first;
|
||||
@@ -15017,8 +15012,8 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero)
|
||||
}
|
||||
|
||||
if (sortinfo->item_compare_float) {
|
||||
float_T v1 = get_tv_float(tv1);
|
||||
float_T v2 = get_tv_float(tv2);
|
||||
const float_T v1 = tv_get_float(tv1);
|
||||
const float_T v2 = tv_get_float(tv2);
|
||||
|
||||
return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
|
||||
}
|
||||
@@ -15977,19 +15972,18 @@ static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
/// "synID(lnum, col, trans)" function
|
||||
static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
int id = 0;
|
||||
long lnum;
|
||||
long col;
|
||||
int trans;
|
||||
// -1 on type error (both)
|
||||
const linenr_T lnum = tv_get_lnum(argvars);
|
||||
const colnr_T col = (colnr_T)get_tv_number(&argvars[1]) - 1;
|
||||
|
||||
bool transerr = false;
|
||||
const int trans = get_tv_number_chk(&argvars[2], &transerr);
|
||||
|
||||
lnum = get_tv_lnum(argvars); /* -1 on type error */
|
||||
col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
|
||||
trans = get_tv_number_chk(&argvars[2], &transerr);
|
||||
|
||||
int id = 0;
|
||||
if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
|
||||
&& col >= 0 && col < (long)STRLEN(ml_get(lnum)))
|
||||
id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL, FALSE);
|
||||
&& col >= 0 && (size_t)col < STRLEN(ml_get(lnum))) {
|
||||
id = syn_get_id(curwin, lnum, col, trans, NULL, false);
|
||||
}
|
||||
|
||||
rettv->vval.v_number = id;
|
||||
}
|
||||
@@ -16090,8 +16084,6 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
long lnum;
|
||||
long col;
|
||||
int syntax_flags = 0;
|
||||
int cchar;
|
||||
int matchid = 0;
|
||||
@@ -16100,15 +16092,16 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
rettv->v_type = VAR_LIST;
|
||||
rettv->vval.v_list = NULL;
|
||||
|
||||
lnum = get_tv_lnum(argvars); /* -1 on type error */
|
||||
col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
|
||||
// -1 on type error (both)
|
||||
const linenr_T lnum = tv_get_lnum(argvars);
|
||||
const colnr_T col = (colnr_T)get_tv_number(&argvars[1]) - 1;
|
||||
|
||||
memset(str, NUL, sizeof(str));
|
||||
|
||||
tv_list_alloc_ret(rettv);
|
||||
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0
|
||||
&& col <= (long)STRLEN(ml_get(lnum)) && curwin->w_p_cole > 0) {
|
||||
(void)syn_get_id(curwin, lnum, col, FALSE, NULL, FALSE);
|
||||
&& (size_t)col <= STRLEN(ml_get(lnum)) && curwin->w_p_cole > 0) {
|
||||
(void)syn_get_id(curwin, lnum, col, false, NULL, false);
|
||||
syntax_flags = get_syntax_info(&matchid);
|
||||
|
||||
// get the conceal character
|
||||
@@ -16137,21 +16130,19 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
*/
|
||||
static void f_synstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
long lnum;
|
||||
long col;
|
||||
|
||||
rettv->v_type = VAR_LIST;
|
||||
rettv->vval.v_list = NULL;
|
||||
|
||||
lnum = get_tv_lnum(argvars); /* -1 on type error */
|
||||
col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
|
||||
// -1 on type error (both)
|
||||
const linenr_T lnum = tv_get_lnum(argvars);
|
||||
const colnr_T col = (colnr_T)get_tv_number(&argvars[1]) - 1;
|
||||
|
||||
if (lnum >= 1
|
||||
&& lnum <= curbuf->b_ml.ml_line_count
|
||||
&& col >= 0
|
||||
&& col <= (long)STRLEN(ml_get(lnum))) {
|
||||
&& (size_t)col <= STRLEN(ml_get(lnum))) {
|
||||
tv_list_alloc_ret(rettv);
|
||||
(void)syn_get_id(curwin, lnum, (colnr_T)col, false, NULL, true);
|
||||
(void)syn_get_id(curwin, lnum, col, false, NULL, true);
|
||||
|
||||
int id;
|
||||
int i = 0;
|
||||
@@ -17457,31 +17448,35 @@ static void f_xor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Translate a String variable into a position.
|
||||
* Returns NULL when there is an error.
|
||||
*/
|
||||
static pos_T *
|
||||
var2fpos (
|
||||
typval_T *varp,
|
||||
int dollar_lnum, /* TRUE when $ is last line */
|
||||
int *fnum /* set to fnum for '0, 'A, etc. */
|
||||
)
|
||||
/// Translate a VimL object into a position
|
||||
///
|
||||
/// Accepts VAR_LIST and VAR_STRING objects. Does not give an error for invalid
|
||||
/// type.
|
||||
///
|
||||
/// @param[in] tv Object to translate.
|
||||
/// @param[in] dollar_lnum True when "$" is last line.
|
||||
/// @param[out] ret_fnum Set to fnum for marks.
|
||||
///
|
||||
/// @return Pointer to position or NULL in case of error (e.g. invalid type).
|
||||
pos_T *var2fpos(const typval_T *const tv, const int dollar_lnum,
|
||||
int *const ret_fnum)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
char_u *name;
|
||||
static pos_T pos;
|
||||
pos_T *pp;
|
||||
|
||||
/* Argument can be [lnum, col, coladd]. */
|
||||
if (varp->v_type == VAR_LIST) {
|
||||
// Argument can be [lnum, col, coladd].
|
||||
if (tv->v_type == VAR_LIST) {
|
||||
list_T *l;
|
||||
int len;
|
||||
bool error = false;
|
||||
listitem_T *li;
|
||||
|
||||
l = varp->vval.v_list;
|
||||
if (l == NULL)
|
||||
l = tv->vval.v_list;
|
||||
if (l == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get the line number.
|
||||
pos.lnum = tv_list_find_nr(l, 0L, &error);
|
||||
@@ -17521,20 +17516,24 @@ var2fpos (
|
||||
return &pos;
|
||||
}
|
||||
|
||||
name = get_tv_string_chk(varp);
|
||||
if (name == NULL)
|
||||
name = get_tv_string_chk(tv);
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
if (name[0] == '.') /* cursor */
|
||||
return &curwin->w_cursor;
|
||||
if (name[0] == 'v' && name[1] == NUL) { /* Visual start */
|
||||
if (VIsual_active)
|
||||
return &VIsual;
|
||||
}
|
||||
if (name[0] == '.') { // Cursor.
|
||||
return &curwin->w_cursor;
|
||||
}
|
||||
if (name[0] == '\'') { /* mark */
|
||||
pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum);
|
||||
if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
|
||||
if (name[0] == 'v' && name[1] == NUL) { // Visual start.
|
||||
if (VIsual_active) {
|
||||
return &VIsual;
|
||||
}
|
||||
return &curwin->w_cursor;
|
||||
}
|
||||
if (name[0] == '\'') { // Mark.
|
||||
pp = getmark_buf_fnum(curbuf, name[1], false, ret_fnum);
|
||||
if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
return pp;
|
||||
}
|
||||
|
||||
@@ -18465,54 +18464,6 @@ varnumber_T get_tv_number_chk(const typval_T *const varp, bool *const denote)
|
||||
return n;
|
||||
}
|
||||
|
||||
static float_T get_tv_float(typval_T *varp)
|
||||
{
|
||||
switch (varp->v_type) {
|
||||
case VAR_NUMBER:
|
||||
return (float_T)(varp->vval.v_number);
|
||||
case VAR_FLOAT:
|
||||
return varp->vval.v_float;
|
||||
break;
|
||||
case VAR_FUNC:
|
||||
case VAR_PARTIAL:
|
||||
EMSG(_("E891: Using a Funcref as a Float"));
|
||||
break;
|
||||
case VAR_STRING:
|
||||
EMSG(_("E892: Using a String as a Float"));
|
||||
break;
|
||||
case VAR_LIST:
|
||||
EMSG(_("E893: Using a List as a Float"));
|
||||
break;
|
||||
case VAR_DICT:
|
||||
EMSG(_("E894: Using a Dictionary as a Float"));
|
||||
break;
|
||||
default:
|
||||
EMSG2(_(e_intern2), "get_tv_float()");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the lnum from the first argument.
|
||||
* Also accepts ".", "$", etc., but that only works for the current buffer.
|
||||
* Returns -1 on error.
|
||||
*/
|
||||
static linenr_T get_tv_lnum(typval_T *argvars)
|
||||
{
|
||||
typval_T rettv;
|
||||
linenr_T lnum;
|
||||
|
||||
lnum = get_tv_number_chk(&argvars[0], NULL);
|
||||
if (lnum == 0) { /* no valid number, try using line() */
|
||||
rettv.v_type = VAR_NUMBER;
|
||||
f_line(argvars, &rettv, NULL);
|
||||
lnum = rettv.vval.v_number;
|
||||
tv_clear(&rettv);
|
||||
}
|
||||
return lnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the lnum from the first argument.
|
||||
* Also accepts "$", then "buf" is used.
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include "nvim/hashtab.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/pos.h"
|
||||
// TODO(ZyX-I): Move line_breakcheck out of misc1
|
||||
#include "nvim/misc1.h" // For line_breakcheck
|
||||
|
||||
@@ -1730,11 +1731,11 @@ static inline void _nothing_conv_dict_end(typval_T *const tv,
|
||||
|
||||
/// Free memory for a variable value and set the value to NULL or 0
|
||||
///
|
||||
/// @param[in,out] varp Value to free.
|
||||
void tv_clear(typval_T *varp)
|
||||
/// @param[in,out] tv Value to free.
|
||||
void tv_clear(typval_T *tv)
|
||||
{
|
||||
if (varp != NULL && varp->v_type != VAR_UNKNOWN) {
|
||||
const int evn_ret = encode_vim_to_nothing(varp, varp, "tv_clear argument");
|
||||
if (tv != NULL && tv->v_type != VAR_UNKNOWN) {
|
||||
const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear argument");
|
||||
(void)evn_ret;
|
||||
assert(evn_ret == OK);
|
||||
}
|
||||
@@ -2017,7 +2018,72 @@ bool tv_check_str_or_nr(const typval_T *const tv)
|
||||
|
||||
//{{{2 Get
|
||||
|
||||
/// Get the string value of a variable
|
||||
/// Get the line number from VimL object
|
||||
///
|
||||
/// @param[in] tv Object to get value from. Is expected to be a number or
|
||||
/// a special string like ".", "$", … (works with current buffer
|
||||
/// only).
|
||||
///
|
||||
/// @return Line number or -1 or 0.
|
||||
linenr_T tv_get_lnum(const typval_T *const tv)
|
||||
{
|
||||
linenr_T lnum = get_tv_number_chk(tv, NULL);
|
||||
if (lnum == 0) { // No valid number, try using same function as line() does.
|
||||
int fnum;
|
||||
pos_T *const fp = var2fpos(tv, true, &fnum);
|
||||
if (fp != NULL) {
|
||||
lnum = fp->lnum;
|
||||
}
|
||||
}
|
||||
return lnum;
|
||||
}
|
||||
|
||||
/// Get the floating-point value of a VimL object
|
||||
///
|
||||
/// Raises an error if object is not number or floating-point.
|
||||
///
|
||||
/// @param[in] tv Object to get value of.
|
||||
///
|
||||
/// @return Floating-point value of the variable or zero.
|
||||
float_T tv_get_float(const typval_T *const tv)
|
||||
{
|
||||
switch (tv->v_type) {
|
||||
case VAR_NUMBER: {
|
||||
return (float_T)(tv->vval.v_number);
|
||||
}
|
||||
case VAR_FLOAT: {
|
||||
return tv->vval.v_float;
|
||||
}
|
||||
case VAR_PARTIAL:
|
||||
case VAR_FUNC: {
|
||||
EMSG(_("E891: Using a Funcref as a Float"));
|
||||
break;
|
||||
}
|
||||
case VAR_STRING: {
|
||||
EMSG(_("E892: Using a String as a Float"));
|
||||
break;
|
||||
}
|
||||
case VAR_LIST: {
|
||||
EMSG(_("E893: Using a List as a Float"));
|
||||
break;
|
||||
}
|
||||
case VAR_DICT: {
|
||||
EMSG(_("E894: Using a Dictionary as a Float"));
|
||||
break;
|
||||
}
|
||||
case VAR_SPECIAL: {
|
||||
EMSG(_("E907: Using a special value as a Float"));
|
||||
break;
|
||||
}
|
||||
case VAR_UNKNOWN: {
|
||||
EMSG2(_(e_intern2), "get_tv_float()");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Get the string value of a VimL object
|
||||
///
|
||||
/// @warning For number and special values it uses a single, static buffer. It
|
||||
/// may be used only once, next call to get_tv_string may reuse it. Use
|
||||
@@ -2027,38 +2093,38 @@ bool tv_check_str_or_nr(const typval_T *const tv)
|
||||
/// @note get_tv_string_chk() and get_tv_string_buf_chk() are similar, but
|
||||
/// return NULL on error.
|
||||
///
|
||||
/// @param[in] varp Varible to get value of.
|
||||
/// @param[in] tv Object to get value of.
|
||||
///
|
||||
/// @return Variable value if it is VAR_STRING variable, number converted to
|
||||
/// @return Object value if it is VAR_STRING object, number converted to
|
||||
/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or empty
|
||||
/// string.
|
||||
const char *tv_get_string(const typval_T *const varp)
|
||||
const char *tv_get_string(const typval_T *const tv)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
static char mybuf[NUMBUFLEN];
|
||||
return tv_get_string_buf((typval_T *)varp, mybuf);
|
||||
return tv_get_string_buf((typval_T *)tv, mybuf);
|
||||
}
|
||||
|
||||
/// Get the string value of a variable
|
||||
/// Get the string value of a VimL object
|
||||
///
|
||||
/// @note get_tv_string_chk() and get_tv_string_buf_chk() are similar, but
|
||||
/// return NULL on error.
|
||||
///
|
||||
/// @param[in] varp Varible to get value of.
|
||||
/// @param[in] tv Object to get value of.
|
||||
/// @param buf Buffer used to hold numbers and special variables converted to
|
||||
/// string. When function encounters one of these stringified value
|
||||
/// will be written to buf and buf will be returned.
|
||||
///
|
||||
/// Buffer must have NUMBUFLEN size.
|
||||
///
|
||||
/// @return Variable value if it is VAR_STRING variable, number converted to
|
||||
/// @return Object value if it is VAR_STRING object, number converted to
|
||||
/// a string for VAR_NUMBER, v: variable name for VAR_SPECIAL or empty
|
||||
/// string.
|
||||
const char *tv_get_string_buf(const typval_T *const varp, char *const buf)
|
||||
const char *tv_get_string_buf(const typval_T *const tv, char *const buf)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
const char *const res = (const char *)get_tv_string_buf_chk(
|
||||
(typval_T *)varp, (char_u *)buf);
|
||||
(typval_T *)tv, (char_u *)buf);
|
||||
|
||||
return res != NULL ? res : "";
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "nvim/profile.h" // for proftime_T
|
||||
#include "nvim/pos.h" // for linenr_T
|
||||
#include "nvim/gettext.h"
|
||||
#include "nvim/message.h"
|
||||
|
||||
/// Type used for VimL VAR_NUMBER values
|
||||
typedef int varnumber_T;
|
||||
@@ -373,7 +374,8 @@ extern bool tv_in_free_unref_items;
|
||||
} \
|
||||
})
|
||||
|
||||
static inline bool tv_get_float(const typval_T *const tv, float_T *const ret_f)
|
||||
static inline bool tv_get_float_chk(const typval_T *const tv,
|
||||
float_T *const ret_f)
|
||||
REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
// FIXME circular dependency, cannot import message.h.
|
||||
@@ -381,11 +383,14 @@ bool emsgf(const char *const fmt, ...);
|
||||
|
||||
/// Get the float value
|
||||
///
|
||||
/// Raises an error if object is not number or floating-point.
|
||||
///
|
||||
/// @param[in] tv VimL object to get value from.
|
||||
/// @param[out] ret_f Location where resulting float is stored.
|
||||
///
|
||||
/// @return true in case of success, false if tv is not a number or float.
|
||||
static inline bool tv_get_float(const typval_T *const tv, float_T *const ret_f)
|
||||
static inline bool tv_get_float_chk(const typval_T *const tv,
|
||||
float_T *const ret_f)
|
||||
{
|
||||
if (tv->v_type == VAR_FLOAT) {
|
||||
*ret_f = tv->vval.v_float;
|
||||
|
41
test/functional/eval/sort_spec.lua
Normal file
41
test/functional/eval/sort_spec.lua
Normal file
@@ -0,0 +1,41 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local eq = helpers.eq
|
||||
local NIL = helpers.NIL
|
||||
local eval = helpers.eval
|
||||
local clear = helpers.clear
|
||||
local meths = helpers.meths
|
||||
local funcs = helpers.funcs
|
||||
local command = helpers.command
|
||||
local exc_exec = helpers.exc_exec
|
||||
|
||||
before_each(clear)
|
||||
|
||||
describe('sort()', function()
|
||||
it('errors out when sorting special values', function()
|
||||
eq('Vim(call):E907: Using a special value as a Float',
|
||||
exc_exec('call sort([v:true, v:false], "f")'))
|
||||
end)
|
||||
|
||||
it('sorts “wrong” values between -0.0001 and 0.0001, preserving order',
|
||||
function()
|
||||
meths.set_var('list', {true, false, NIL, {}, {a=42}, 'check',
|
||||
0.0001, -0.0001})
|
||||
command('call insert(g:list, function("tr"))')
|
||||
local error_lines = funcs.split(
|
||||
funcs.execute('silent! call sort(g:list, "f")'), '\n')
|
||||
local errors = {}
|
||||
for _, err in ipairs(error_lines) do
|
||||
errors[err] = true
|
||||
end
|
||||
eq({
|
||||
['E891: Using a Funcref as a Float']=true,
|
||||
['E892: Using a String as a Float']=true,
|
||||
['E893: Using a List as a Float']=true,
|
||||
['E894: Using a Dictionary as a Float']=true,
|
||||
['E907: Using a special value as a Float']=true,
|
||||
}, errors)
|
||||
eq('[-1.0e-4, function(\'tr\'), v:true, v:false, v:null, [], {\'a\': 42}, \'check\', 1.0e-4]',
|
||||
eval('string(g:list)'))
|
||||
end)
|
||||
end)
|
Reference in New Issue
Block a user