diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 502 |
1 files changed, 411 insertions, 91 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index b51480afc6..0ff70df54d 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -66,7 +66,6 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" -#include "nvim/tempfile.h" #include "nvim/ui.h" #include "nvim/mouse.h" #include "nvim/terminal.h" @@ -4741,13 +4740,14 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) ++name; break; - /* Special key, e.g.: "\<C-W>" */ - case '<': extra = trans_special(&p, name, TRUE); + // Special key, e.g.: "\<C-W>" + case '<': + extra = trans_special((const char_u **) &p, STRLEN(p), name, true); if (extra != 0) { name += extra; break; } - /* FALLTHROUGH */ + // FALLTHROUGH default: MB_COPY_CHAR(p, name); break; @@ -6656,7 +6656,7 @@ static struct fst { } functions[] = { { "abs", 1, 1, f_abs }, - { "acos", 1, 1, f_acos }, // WJMc + { "acos", 1, 1, f_acos }, // WJMc { "add", 2, 2, f_add }, { "and", 2, 2, f_and }, { "append", 2, 2, f_append }, @@ -6666,6 +6666,7 @@ static struct fst { { "argv", 0, 1, f_argv }, { "asin", 1, 1, f_asin }, // WJMc { "assert_equal", 2, 3, f_assert_equal }, + { "assert_exception", 1, 2, f_assert_exception }, { "assert_false", 1, 2, f_assert_false }, { "assert_true", 1, 2, f_assert_true }, { "atan", 1, 1, f_atan }, @@ -6673,9 +6674,9 @@ static struct fst { { "browse", 4, 4, f_browse }, { "browsedir", 2, 2, f_browsedir }, { "bufexists", 1, 1, f_bufexists }, - { "buffer_exists", 1, 1, f_bufexists }, // obsolete - { "buffer_name", 1, 1, f_bufname }, // obsolete - { "buffer_number", 1, 1, f_bufnr }, // obsolete + { "buffer_exists", 1, 1, f_bufexists }, // obsolete + { "buffer_name", 1, 1, f_bufname }, // obsolete + { "buffer_number", 1, 1, f_bufnr }, // obsolete { "buflisted", 1, 1, f_buflisted }, { "bufloaded", 1, 1, f_bufloaded }, { "bufname", 1, 1, f_bufname }, @@ -6702,7 +6703,7 @@ static struct fst { { "cscope_connection", 0, 3, f_cscope_connection }, { "cursor", 1, 3, f_cursor }, { "deepcopy", 1, 2, f_deepcopy }, - { "delete", 1, 1, f_delete }, + { "delete", 1, 2, f_delete }, { "dictwatcheradd", 3, 3, f_dictwatcheradd }, { "dictwatcherdel", 3, 3, f_dictwatcherdel }, { "did_filetype", 0, 0, f_did_filetype }, @@ -6719,7 +6720,7 @@ static struct fst { { "expand", 1, 3, f_expand }, { "extend", 2, 3, f_extend }, { "feedkeys", 1, 2, f_feedkeys }, - { "file_readable", 1, 1, f_filereadable }, // obsolete + { "file_readable", 1, 1, f_filereadable }, // obsolete { "filereadable", 1, 1, f_filereadable }, { "filewritable", 1, 1, f_filewritable }, { "filter", 2, 2, f_filter }, @@ -6749,7 +6750,7 @@ static struct fst { { "getcmdtype", 0, 0, f_getcmdtype }, { "getcmdwintype", 0, 0, f_getcmdwintype }, { "getcurpos", 0, 0, f_getcurpos }, - { "getcwd", 0, 0, f_getcwd }, + { "getcwd", 0, 2, f_getcwd }, { "getfontname", 0, 1, f_getfontname }, { "getfperm", 1, 1, f_getfperm }, { "getfsize", 1, 1, f_getfsize }, @@ -6773,7 +6774,7 @@ static struct fst { { "globpath", 2, 5, f_globpath }, { "has", 1, 1, f_has }, { "has_key", 2, 2, f_has_key }, - { "haslocaldir", 0, 0, f_haslocaldir }, + { "haslocaldir", 0, 2, f_haslocaldir }, { "hasmapto", 1, 3, f_hasmapto }, { "highlightID", 1, 1, f_hlID }, // obsolete { "highlight_exists", 1, 1, f_hlexists }, // obsolete @@ -7628,6 +7629,26 @@ static void f_assert_equal(typval_T *argvars, typval_T *rettv) } } +/// "assert_exception(string[, msg])" function +static void f_assert_exception(typval_T *argvars, typval_T *rettv) +{ + garray_T ga; + + char *error = (char *)get_tv_string_chk(&argvars[0]); + if (vimvars[VV_EXCEPTION].vv_str == NULL) { + prepare_assert_error(&ga); + ga_concat(&ga, (char_u *)"v:exception is not set"); + assert_error(&ga); + ga_clear(&ga); + } else if (strstr((char *)vimvars[VV_EXCEPTION].vv_str, error) == NULL) { + prepare_assert_error(&ga); + fill_assert_error(&ga, &argvars[1], NULL, &argvars[0], + &vimvars[VV_EXCEPTION].vv_tv); + assert_error(&ga); + ga_clear(&ga); + } +} + // Common for assert_true() and assert_false(). static void assert_bool(typval_T *argvars, bool is_true) { @@ -8305,12 +8326,12 @@ static void f_cscope_connection(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = cs_connection(num, dbpath, prepend); } -/* - * "cursor(lnum, col)" function - * - * Moves the cursor to the specified line and column. - * Returns 0 when the position could be set, -1 otherwise. - */ +/// "cursor(lnum, col)" function, or +/// "cursor(list)" +/// +/// Moves the cursor to the specified line and column. +/// +/// @returns 0 when the position could be set, -1 otherwise. static void f_cursor(typval_T *argvars, typval_T *rettv) { long line, col; @@ -8322,8 +8343,10 @@ static void f_cursor(typval_T *argvars, typval_T *rettv) colnr_T curswant = -1; if (list2fpos(argvars, &pos, NULL, &curswant) == FAIL) { + EMSG(_(e_invarg)); return; } + line = pos.lnum; col = pos.col; coladd = pos.coladd; @@ -8374,15 +8397,42 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv) } } -/* - * "delete()" function - */ +// "delete()" function static void f_delete(typval_T *argvars, typval_T *rettv) { - if (check_restricted() || check_secure()) - rettv->vval.v_number = -1; - else - rettv->vval.v_number = os_remove((char *)get_tv_string(&argvars[0])); + char_u nbuf[NUMBUFLEN]; + char_u *name; + char_u *flags; + + rettv->vval.v_number = -1; + if (check_restricted() || check_secure()) { + return; + } + + name = get_tv_string(&argvars[0]); + if (name == NULL || *name == NUL) { + EMSG(_(e_invarg)); + return; + } + + if (argvars[1].v_type != VAR_UNKNOWN) { + flags = get_tv_string_buf(&argvars[1], nbuf); + } else { + flags = (char_u *)""; + } + + if (*flags == NUL) { + // delete a file + rettv->vval.v_number = os_remove((char *)name) == 0 ? 0 : -1; + } else if (STRCMP(flags, "d") == 0) { + // delete an empty directory + rettv->vval.v_number = os_rmdir((char *)name) == 0 ? 0 : -1; + } else if (STRCMP(flags, "rf") == 0) { + // delete a directory recursively + rettv->vval.v_number = delete_recursive(name); + } else { + EMSG2(_(e_invexpr2), flags); + } } // dictwatcheradd(dict, key, funcref) function @@ -9758,22 +9808,143 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv) rettv->vval.v_string[0] = cmdwin_type; } -/* - * "getcwd()" function - */ +/// `getcwd([{win}[, {tab}]])` function +/// +/// Every scope not specified implies the currently selected scope object. +/// +/// @pre The arguments must be of type number. +/// @pre There may not be more than two arguments. +/// @pre An argument may not be -1 if preceding arguments are not all -1. +/// +/// @post The return value will be a string. static void f_getcwd(typval_T *argvars, typval_T *rettv) { - char_u *cwd; + // Possible scope of working directory to return. + CdScope scope = kCdScopeWindow; + + // Numbers of the scope objects (window, tab) we want the working directory + // of. A `-1` means to skip this scope, a `0` means the current object. + int scope_number[] = { + [kCdScopeWindow] = 0, // Number of window to look at. + [kCdScopeTab ] = 0, // Number of tab to look at. + }; + + char_u *cwd = NULL; // Current working directory to print + char_u *from = NULL; // The original string to copy + + tabpage_T *tp = curtab; // The tabpage to look at. + win_T *win = curwin; // The window to look at. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; + + // Pre-conditions and scope extraction together + for (int i = 0; i < kCdScopeGlobal; i++) { + if (argvars[i].v_type == VAR_UNKNOWN) { + break; + } + if (argvars[i].v_type != VAR_NUMBER) { + EMSG(_(e_invarg)); + return; + } + scope_number[i] = argvars[i].vval.v_number; + // The scope is the current iteration step. + scope = i; + + if (scope_number[i] < -1) { + EMSG(_(e_invarg)); + return; + } + } + + // Allocate and initialize the string to return. cwd = xmalloc(MAXPATHL); - if (os_dirname(cwd, MAXPATHL) != FAIL) { - rettv->vval.v_string = vim_strsave(cwd); + + // Get the scope and numbers from the arguments + for (int i = 0; i < MAX_CD_SCOPE; i++) { + // If there is no argument there are no more scopes after it, break out. + if (argvars[i].v_type == VAR_UNKNOWN) { + break; + } + scope_number[i] = argvars[i].vval.v_number; + // The scope is the current iteration step. + scope = i; + // It is an error for the scope number to be less than `-1`. + if (scope_number[i] < -1) { + EMSG(_(e_invarg)); + goto end; + } + } + + // If the deepest scope number is `-1` advance the scope. + if (scope_number[scope] < 0) { + scope++; + } + + // Find the tabpage by number + if (scope_number[kCdScopeTab] == -1) { + tp = NULL; + } else if (scope_number[kCdScopeTab] > 0) { + tp = find_tabpage(scope_number[kCdScopeTab]); + if (!tp) { + EMSG(_("E5000: Cannot find tab number.")); + goto end; + } + } + + // Find the window in `tp` by number, `NULL` if none. + if (scope_number[kCdScopeWindow] == -1) { + win = NULL; + } else if (scope_number[kCdScopeWindow] >= 0) { + if (!tp) { + EMSG(_("E5001: Higher scope cannot be -1 if lower scope is >= 0.")); + goto end; + } + + if (scope_number[kCdScopeWindow] > 0) { + win = find_win_by_nr(&argvars[0], curtab); + if (!win) { + EMSG(_("E5002: Cannot find window number.")); + goto end; + } + } + } + + switch (scope) { + case kCdScopeWindow: + from = win->w_localdir; + if (from) { + break; + } + case kCdScopeTab: // FALLTHROUGH + from = tp->localdir; + if (from) { + break; + } + case kCdScopeGlobal: // FALLTHROUGH + // The `globaldir` variable is not always set. + if (globaldir) { + from = globaldir; + } else { + // Copy the OS path directly into output string and jump to the end. + if (os_dirname(cwd, MAXPATHL) == FAIL) { + EMSG(_("E41: Could not display path.")); + goto end; + } + } + break; + } + + if (from) { + xstrlcpy((char *)cwd, (char *)from, MAXPATHL); + } + + rettv->vval.v_string = vim_strsave(cwd); #ifdef BACKSLASH_IN_FILENAME - slash_adjust(rettv->vval.v_string); + slash_adjust(rettv->vval.v_string); #endif - } + +end: xfree(cwd); } @@ -10024,6 +10195,7 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos) list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); if (getcurpos) { + update_curswant(); list_append_number(l, curwin->w_curswant == MAXCOL ? (varnumber_T)MAXCOL : (varnumber_T)curwin->w_curswant + 1); @@ -10593,12 +10765,98 @@ static void f_has_key(typval_T *argvars, typval_T *rettv) get_tv_string(&argvars[1]), -1) != NULL; } -/* - * "haslocaldir()" function - */ +/// `haslocaldir([{win}[, {tab}]])` function +/// +/// Returns `1` if the scope object has a local directory, `0` otherwise. If a +/// scope object is not specified the current one is implied. This function +/// share a lot of code with `f_getcwd`. +/// +/// @pre The arguments must be of type number. +/// @pre There may not be more than two arguments. +/// @pre An argument may not be -1 if preceding arguments are not all -1. +/// +/// @post The return value will be either the number `1` or `0`. static void f_haslocaldir(typval_T *argvars, typval_T *rettv) { - rettv->vval.v_number = (curwin->w_localdir != NULL); + // Possible scope of working directory to return. + CdScope scope = kCdScopeWindow; + + // Numbers of the scope objects (window, tab) we want the working directory + // of. A `-1` means to skip this scope, a `0` means the current object. + int scope_number[] = { + [kCdScopeWindow] = 0, // Number of window to look at. + [kCdScopeTab ] = 0, // Number of tab to look at. + }; + + tabpage_T *tp = curtab; // The tabpage to look at. + win_T *win = curwin; // The window to look at. + + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + // Pre-conditions and scope extraction together + for (int i = 0; i < kCdScopeGlobal; i++) { + if (argvars[i].v_type == VAR_UNKNOWN) { + break; + } + if (argvars[i].v_type != VAR_NUMBER) { + EMSG(_(e_invarg)); + return; + } + scope_number[i] = argvars[i].vval.v_number; + // The scope is the current iteration step. + scope = i; + if (scope_number[i] < -1) { + EMSG(_(e_invarg)); + return; + } + } + + // It the deepest scope number is `-1` advance the scope by one. + if (scope_number[scope] < 0) { + ++scope; + } + + // Find the tabpage by number + if (scope_number[kCdScopeTab] == -1) { + tp = NULL; + } else if (scope_number[kCdScopeTab] > 0) { + tp = find_tabpage(scope_number[kCdScopeTab]); + if (!tp) { + EMSG(_("5000: Cannot find tab number.")); + return; + } + } + + // Find the window in `tp` by number, `NULL` if none. + if (scope_number[kCdScopeWindow] == -1) { + win = NULL; + } else if (scope_number[kCdScopeWindow] >= 0) { + if (!tp) { + EMSG(_("E5001: Higher scope cannot be -1 if lower scope is >= 0.")); + return; + } + + if (scope_number[kCdScopeWindow] > 0) { + win = find_win_by_nr(&argvars[0], curtab); + if (!win) { + EMSG(_("E5002: Cannot find window number.")); + return; + } + } + } + + switch (scope) { + case kCdScopeWindow: + rettv->vval.v_number = win->w_localdir ? 1 : 0; + break; + case kCdScopeTab: + rettv->vval.v_number = tp->localdir ? 1 : 0; + break; + case kCdScopeGlobal: + assert(0); + break; + } } /* @@ -10631,21 +10889,22 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv) */ static void f_histadd(typval_T *argvars, typval_T *rettv) { - int histype; + HistoryType histype; char_u *str; char_u buf[NUMBUFLEN]; - rettv->vval.v_number = FALSE; - if (check_restricted() || check_secure()) + rettv->vval.v_number = false; + if (check_restricted() || check_secure()) { return; - str = get_tv_string_chk(&argvars[0]); /* NULL on type error */ - histype = str != NULL ? get_histtype(str) : -1; - if (histype >= 0) { + } + str = get_tv_string_chk(&argvars[0]); // NULL on type error + histype = str != NULL ? get_histtype(str, STRLEN(str), false) : HIST_INVALID; + if (histype != HIST_INVALID) { str = get_tv_string_buf(&argvars[1], buf); if (*str != NUL) { init_history(); - add_to_history(histype, str, FALSE, NUL); - rettv->vval.v_number = TRUE; + add_to_history(histype, str, false, NUL); + rettv->vval.v_number = true; return; } } @@ -10660,20 +10919,21 @@ static void f_histdel(typval_T *argvars, typval_T *rettv) char_u buf[NUMBUFLEN]; char_u *str; - str = get_tv_string_chk(&argvars[0]); /* NULL on type error */ - if (str == NULL) + str = get_tv_string_chk(&argvars[0]); // NULL on type error + if (str == NULL) { n = 0; - else if (argvars[1].v_type == VAR_UNKNOWN) - /* only one argument: clear entire history */ - n = clr_history(get_histtype(str)); - else if (argvars[1].v_type == VAR_NUMBER) - /* index given: remove that entry */ - n = del_history_idx(get_histtype(str), - (int)get_tv_number(&argvars[1])); - else - /* string given: remove all matching entries */ - n = del_history_entry(get_histtype(str), - get_tv_string_buf(&argvars[1], buf)); + } else if (argvars[1].v_type == VAR_UNKNOWN) { + // only one argument: clear entire history + n = clr_history(get_histtype(str, STRLEN(str), false)); + } else if (argvars[1].v_type == VAR_NUMBER) { + // index given: remove that entry + n = del_history_idx(get_histtype(str, STRLEN(str), false), + (int) get_tv_number(&argvars[1])); + } else { + // string given: remove all matching entries + n = del_history_entry(get_histtype(str, STRLEN(str), false), + get_tv_string_buf(&argvars[1], buf)); + } rettv->vval.v_number = n; } @@ -10682,20 +10942,21 @@ static void f_histdel(typval_T *argvars, typval_T *rettv) */ static void f_histget(typval_T *argvars, typval_T *rettv) { - int type; + HistoryType type; int idx; char_u *str; - str = get_tv_string_chk(&argvars[0]); /* NULL on type error */ - if (str == NULL) + str = get_tv_string_chk(&argvars[0]); // NULL on type error + if (str == NULL) { rettv->vval.v_string = NULL; - else { - type = get_histtype(str); - if (argvars[1].v_type == VAR_UNKNOWN) + } else { + type = get_histtype(str, STRLEN(str), false); + if (argvars[1].v_type == VAR_UNKNOWN) { idx = get_history_idx(type); - else + } else { idx = (int)get_tv_number_chk(&argvars[1], NULL); - /* -1 on type error */ + } + // -1 on type error rettv->vval.v_string = vim_strsave(get_history_entry(type, idx)); } rettv->v_type = VAR_STRING; @@ -10710,11 +10971,13 @@ static void f_histnr(typval_T *argvars, typval_T *rettv) char_u *history = get_tv_string_chk(&argvars[0]); - i = history == NULL ? HIST_CMD - 1 : get_histtype(history); - if (i >= HIST_CMD && i < HIST_COUNT) + i = history == NULL ? HIST_CMD - 1 : get_histtype(history, STRLEN(history), + false); + if (i != HIST_INVALID) { i = get_history_idx(i); - else + } else { i = -1; + } rettv->vval.v_number = i; } @@ -11851,8 +12114,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) mode = get_map_mode(&which, 0); - keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE); - rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local); + keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, false, + CPO_TO_CPO_FLAGS); + rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local); xfree(keys_buf); if (!get_dict) { @@ -13303,14 +13567,14 @@ static void f_reverse(typval_T *argvars, typval_T *rettv) } } -#define SP_NOMOVE 0x01 /* don't move cursor */ -#define SP_REPEAT 0x02 /* repeat to find outer pair */ -#define SP_RETCOUNT 0x04 /* return matchcount */ -#define SP_SETPCMARK 0x08 /* set previous context mark */ -#define SP_START 0x10 /* accept match at start position */ -#define SP_SUBPAT 0x20 /* return nr of matching sub-pattern */ -#define SP_END 0x40 /* leave cursor at end of match */ - +#define SP_NOMOVE 0x01 ///< don't move cursor +#define SP_REPEAT 0x02 ///< repeat to find outer pair +#define SP_RETCOUNT 0x04 ///< return matchcount +#define SP_SETPCMARK 0x08 ///< set previous context mark +#define SP_START 0x10 ///< accept match at start position +#define SP_SUBPAT 0x20 ///< return nr of matching sub-pattern +#define SP_END 0x40 ///< leave cursor at end of match +#define SP_COLUMN 0x80 ///< start at cursor column /* * Get flags for a search function. @@ -13336,13 +13600,14 @@ static int get_search_arg(typval_T *varp, int *flagsp) default: mask = 0; if (flagsp != NULL) switch (*flags) { - case 'c': mask = SP_START; break; - case 'e': mask = SP_END; break; - case 'm': mask = SP_RETCOUNT; break; - case 'n': mask = SP_NOMOVE; break; - case 'p': mask = SP_SUBPAT; break; - case 'r': mask = SP_REPEAT; break; - case 's': mask = SP_SETPCMARK; break; + case 'c': mask = SP_START; break; + case 'e': mask = SP_END; break; + case 'm': mask = SP_RETCOUNT; break; + case 'n': mask = SP_NOMOVE; break; + case 'p': mask = SP_SUBPAT; break; + case 'r': mask = SP_REPEAT; break; + case 's': mask = SP_SETPCMARK; break; + case 'z': mask = SP_COLUMN; break; } if (mask == 0) { EMSG2(_(e_invarg2), flags); @@ -13358,9 +13623,7 @@ static int get_search_arg(typval_T *varp, int *flagsp) return dir; } -/* - * Shared by search() and searchpos() functions - */ +// Shared by search() and searchpos() functions. static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) { int flags; @@ -13381,10 +13644,15 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) if (dir == 0) goto theend; flags = *flagsp; - if (flags & SP_START) + if (flags & SP_START) { options |= SEARCH_START; - if (flags & SP_END) + } + if (flags & SP_END) { options |= SEARCH_END; + } + if (flags & SP_COLUMN) { + options |= SEARCH_COL; + } /* Optional arguments: line number to stop searching and timeout. */ if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { @@ -14714,6 +14982,8 @@ typedef struct { static int item_compare_ic; static bool item_compare_numeric; +static bool item_compare_numbers; +static bool item_compare_float; static char_u *item_compare_func; static dict_T *item_compare_selfdict; static int item_compare_func_err; @@ -14735,6 +15005,21 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) si2 = (sortItem_T *)s2; typval_T *tv1 = &si1->item->li_tv; typval_T *tv2 = &si2->item->li_tv; + + if (item_compare_numbers) { + long v1 = get_tv_number(tv1); + long v2 = get_tv_number(tv2); + + return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + } + + if (item_compare_float) { + float_T v1 = get_tv_float(tv1); + float_T v2 = get_tv_float(tv2); + + return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; + } + // encode_tv2string() puts quotes around a string and allocates memory. Don't // do that for string variables. Use a single quote when comparing with // a non-string to do what the docs promise. @@ -14881,6 +15166,8 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) item_compare_ic = FALSE; item_compare_numeric = false; + item_compare_numbers = false; + item_compare_float = false; item_compare_func = NULL; item_compare_selfdict = NULL; @@ -14902,6 +15189,12 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) if (STRCMP(item_compare_func, "n") == 0) { item_compare_func = NULL; item_compare_numeric = true; + } else if (STRCMP(item_compare_func, "N") == 0) { + item_compare_func = NULL; + item_compare_numbers = true; + } else if (STRCMP(item_compare_func, "f") == 0) { + item_compare_func = NULL; + item_compare_float = true; } else if (STRCMP(item_compare_func, "i") == 0) { item_compare_func = NULL; item_compare_ic = TRUE; @@ -17603,6 +17896,33 @@ long get_tv_number_chk(typval_T *varp, int *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: + 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. |