aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval/funcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval/funcs.c')
-rw-r--r--src/nvim/eval/funcs.c480
1 files changed, 240 insertions, 240 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index deeda28571..caaf675db2 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -391,28 +391,16 @@ static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
+// "assert_beeps(cmd [, error])" function
static void f_assert_beeps(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- const char *const cmd = tv_get_string_chk(&argvars[0]);
- garray_T ga;
- int ret = 0;
-
- called_vim_beep = false;
- suppress_errthrow = true;
- emsg_silent = false;
- do_cmdline_cmd(cmd);
- if (!called_vim_beep) {
- prepare_assert_error(&ga);
- ga_concat(&ga, (const char_u *)"command did not beep: ");
- ga_concat(&ga, (const char_u *)cmd);
- assert_error(&ga);
- ga_clear(&ga);
- ret = 1;
- }
+ rettv->vval.v_number = assert_beeps(argvars, false);
+}
- suppress_errthrow = false;
- emsg_on_display = false;
- rettv->vval.v_number = ret;
+// "assert_nobeep(cmd [, error])" function
+static void f_assert_nobeep(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ rettv->vval.v_number = assert_beeps(argvars, true);
}
// "assert_equal(expected, actual[, msg])" function
@@ -614,12 +602,7 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (argvars[0].v_type == VAR_UNKNOWN) {
buf = curbuf;
} else {
- if (!tv_check_str_or_nr(&argvars[0])) {
- return;
- }
- emsg_off++;
- buf = tv_get_buf(&argvars[0], false);
- emsg_off--;
+ buf = tv_get_buf_from_arg(&argvars[0]);
}
if (buf != NULL && buf->b_fname != NULL) {
rettv->vval.v_string = (char_u *)xstrdup((char *)buf->b_fname);
@@ -639,6 +622,9 @@ static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (argvars[0].v_type == VAR_UNKNOWN) {
buf = curbuf;
} else {
+ // Don't use tv_get_buf_from_arg(); we continue if the buffer wasn't found
+ // and the second argument isn't zero, but we want to return early if the
+ // first argument isn't a string or number so only one error is shown.
if (!tv_check_str_or_nr(&argvars[0])) {
return;
}
@@ -665,18 +651,12 @@ static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr)
{
- if (!tv_check_str_or_nr(&argvars[0])) {
+ const buf_T *const buf = tv_get_buf_from_arg(&argvars[0]);
+ if (buf == NULL) { // no need to search if invalid arg or buffer not found
rettv->vval.v_number = -1;
return;
}
- emsg_off++;
- buf_T *buf = tv_get_buf(&argvars[0], true);
- if (buf == NULL) { // no need to search if buffer was not found
- rettv->vval.v_number = -1;
- goto end;
- }
-
int winnr = 0;
int winid;
bool found_buf = false;
@@ -689,8 +669,6 @@ static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr)
}
}
rettv->vval.v_number = (found_buf ? (get_nr ? winnr : winid) : -1);
-end:
- emsg_off--;
}
/// "bufwinid(nr)" function
@@ -743,6 +721,18 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only)
return buf;
}
+/// Like tv_get_buf() but give an error message if the type is wrong.
+buf_T *tv_get_buf_from_arg(typval_T *const tv) FUNC_ATTR_NONNULL_ALL
+{
+ if (!tv_check_str_or_nr(tv)) {
+ return NULL;
+ }
+ emsg_off++;
+ buf_T *const buf = tv_get_buf(tv, false);
+ emsg_off--;
+ return buf;
+}
+
/// Get the buffer from "arg" and give an error and return NULL if it is not
/// valid.
buf_T * get_buf_arg(typval_T *arg)
@@ -822,6 +812,7 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
+ bool owned = false;
char_u *func;
partial_T *partial = NULL;
dict_T *selfdict = NULL;
@@ -832,6 +823,7 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr)
func = partial_name(partial);
} else if (nlua_is_table_from_lua(&argvars[0])) {
func = nlua_register_table_as_callable(&argvars[0]);
+ owned = true;
} else {
func = (char_u *)tv_get_string(&argvars[0]);
}
@@ -849,6 +841,9 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
func_call(func, &argvars[1], partial, selfdict, rettv);
+ if (owned) {
+ func_unref(func);
+ }
}
/*
@@ -923,7 +918,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
uint64_t id = argvars[0].vval.v_number;
const char *error = NULL;
- rettv->vval.v_number = channel_send(id, input, input_len, &error);
+ rettv->vval.v_number = channel_send(id, input, input_len, true, &error);
if (error) {
EMSG(error);
}
@@ -1105,7 +1100,7 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_complete_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0);
+ rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0, false);
}
/*
@@ -1855,15 +1850,30 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr)
ptrdiff_t len = end - str;
assert(len > 0);
const char * value = str + len + 1;
- if (tv_dict_find(rettv->vval.v_dict, str, len) != NULL) {
+
+ char c = env[i][len];
+ env[i][len] = NUL;
+
+#ifdef WIN32
+ // Upper-case all the keys for Windows so we can detect duplicates
+ char *const key = strcase_save(str, true);
+#else
+ char *const key = xstrdup(str);
+#endif
+
+ env[i][len] = c;
+
+ if (tv_dict_find(rettv->vval.v_dict, key, len) != NULL) {
// Since we're traversing from the end of the env block to the front, any
// duplicate names encountered should be ignored. This preserves the
// semantics of env vars defined later in the env block taking precedence.
+ xfree(key);
continue;
}
tv_dict_add_str(rettv->vval.v_dict,
- str, len,
+ key, len,
value);
+ xfree(key);
}
os_free_fullenv(env);
}
@@ -1958,8 +1968,8 @@ static char_u *get_list_line(int c, void *cookie, int indent, bool do_concat)
return (char_u *)(s == NULL ? NULL : xstrdup(s));
}
-// "execute(command)" function
-static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr,
+ int arg_off)
{
const int save_msg_silent = msg_silent;
const int save_emsg_silent = emsg_silent;
@@ -1973,9 +1983,9 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
- if (argvars[1].v_type != VAR_UNKNOWN) {
+ if (argvars[arg_off + 1].v_type != VAR_UNKNOWN) {
char buf[NUMBUFLEN];
- const char *const s = tv_get_string_buf_chk(&argvars[1], buf);
+ const char *const s = tv_get_string_buf_chk(&argvars[arg_off + 1], buf);
if (s == NULL) {
return;
@@ -2002,10 +2012,10 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
msg_col = 0; // prevent leading spaces
}
- if (argvars[0].v_type != VAR_LIST) {
- do_cmdline_cmd(tv_get_string(&argvars[0]));
- } else if (argvars[0].vval.v_list != NULL) {
- list_T *const list = argvars[0].vval.v_list;
+ if (argvars[arg_off].v_type != VAR_LIST) {
+ do_cmdline_cmd(tv_get_string(&argvars[arg_off]));
+ } else if (argvars[arg_off].vval.v_list != NULL) {
+ list_T *const list = argvars[arg_off].vval.v_list;
tv_list_ref(list);
GetListLineCookie cookie = {
.l = list,
@@ -2037,6 +2047,39 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
capture_ga = save_capture_ga;
}
+// "execute(command)" function
+static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ execute_common(argvars, rettv, fptr, 0);
+}
+
+// "win_execute(win_id, command)" function
+static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ tabpage_T *tp;
+ win_T *wp = win_id2wp_tp(argvars, &tp);
+ win_T *save_curwin;
+ tabpage_T *save_curtab;
+ // Return an empty string if something fails.
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = NULL;
+
+ if (wp != NULL && tp != NULL) {
+ pos_T curpos = wp->w_cursor;
+ if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, true) ==
+ OK) {
+ check_cursor();
+ execute_common(argvars, rettv, fptr, 1);
+ }
+ restore_win_noblock(save_curwin, save_curtab, true);
+
+ // Update the status line if the cursor moved.
+ if (win_valid(wp) && !equalpos(curpos, wp->w_cursor)) {
+ wp->w_redr_status = true;
+ }
+ }
+}
+
/// "exepath()" function
static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
@@ -2058,7 +2101,6 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int n = false;
- int len = 0;
const char *p = tv_get_string(&argvars[0]);
if (*p == '$') { // Environment variable.
@@ -2089,29 +2131,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
n = au_exists(p + 1);
}
} else { // Internal variable.
- typval_T tv;
-
- // get_name_len() takes care of expanding curly braces
- const char *name = p;
- char *tofree;
- len = get_name_len((const char **)&p, &tofree, true, false);
- if (len > 0) {
- if (tofree != NULL) {
- name = tofree;
- }
- n = (get_var_tv(name, len, &tv, NULL, false, true) == OK);
- if (n) {
- // Handle d.key, l[idx], f(expr).
- n = (handle_subscript(&p, &tv, true, false) == OK);
- if (n) {
- tv_clear(&tv);
- }
- }
- }
- if (*p != NUL)
- n = FALSE;
-
- xfree(tofree);
+ n = var_exists(p);
}
rettv->vval.v_number = n;
@@ -2765,10 +2785,9 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
} else if (strcmp(what, "args") == 0) {
rettv->v_type = VAR_LIST;
- if (tv_list_alloc_ret(rettv, pt->pt_argc) != NULL) {
- for (int i = 0; i < pt->pt_argc; i++) {
- tv_list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]);
- }
+ tv_list_alloc_ret(rettv, pt->pt_argc);
+ for (int i = 0; i < pt->pt_argc; i++) {
+ tv_list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]);
}
} else {
EMSG2(_(e_invarg2), what);
@@ -2829,13 +2848,9 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
} else if (argvars[0].v_type != VAR_UNKNOWN) {
// Information about one buffer. Argument specifies the buffer
- if (tv_check_num(&argvars[0])) { // issue errmsg if type error
- emsg_off++;
- argbuf = tv_get_buf(&argvars[0], false);
- emsg_off--;
- if (argbuf == NULL) {
- return;
- }
+ argbuf = tv_get_buf_from_arg(&argvars[0]);
+ if (argbuf == NULL) {
+ return;
}
}
@@ -2905,13 +2920,7 @@ static void get_buffer_lines(buf_T *buf,
*/
static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf = NULL;
-
- if (tv_check_str_or_nr(&argvars[0])) {
- emsg_off++;
- buf = tv_get_buf(&argvars[0], false);
- emsg_off--;
- }
+ buf_T *const buf = tv_get_buf_from_arg(&argvars[0]);
const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf);
const linenr_T end = (argvars[2].v_type == VAR_UNKNOWN
@@ -3054,7 +3063,10 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
n = safe_vgetc();
}
- if (n == K_IGNORE || n == K_VER_SCROLLBAR || n == K_HOR_SCROLLBAR) {
+ if (n == K_IGNORE
+ || n == K_MOUSEMOVE
+ || n == K_VER_SCROLLBAR
+ || n == K_HOR_SCROLLBAR) {
continue;
}
break;
@@ -5099,7 +5111,21 @@ static dict_T *create_environment(const dictitem_T *job_env,
}
if (job_env) {
+#ifdef WIN32
+ TV_DICT_ITER(job_env->di_tv.vval.v_dict, var, {
+ // Always use upper-case keys for Windows so we detect duplicate keys
+ char *const key = strcase_save((const char *)var->di_key, true);
+ size_t len = strlen(key);
+ dictitem_T *dv = tv_dict_find(env, key, len);
+ if (dv) {
+ tv_dict_item_remove(env, dv);
+ }
+ tv_dict_add_str(env, key, len, tv_get_string(&var->di_tv));
+ xfree(key);
+ });
+#else
tv_dict_extend(env, job_env->di_tv.vval.v_dict, "force");
+#endif
}
if (pty) {
@@ -5542,18 +5568,36 @@ static void f_libcallnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
libcall_common(argvars, rettv, VAR_NUMBER);
}
-/*
- * "line(string)" function
- */
+// "line(string, [winid])" function
static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum = 0;
- pos_T *fp;
+ pos_T *fp = NULL;
int fnum;
- fp = var2fpos(&argvars[0], TRUE, &fnum);
- if (fp != NULL)
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ tabpage_T *tp;
+ win_T *save_curwin;
+ tabpage_T *save_curtab;
+
+ // use window specified in the second argument
+ win_T *wp = win_id2wp_tp(&argvars[1], &tp);
+ if (wp != NULL && tp != NULL) {
+ if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, true)
+ == OK) {
+ check_cursor();
+ fp = var2fpos(&argvars[0], true, &fnum);
+ }
+ restore_win_noblock(save_curwin, save_curtab, true);
+ }
+ } else {
+ // use current window
+ fp = var2fpos(&argvars[0], true, &fnum);
+ }
+
+ if (fp != NULL) {
lnum = fp->lnum;
+ }
rettv->vval.v_number = lnum;
}
@@ -6529,6 +6573,26 @@ static void f_prompt_setinterrupt(typval_T *argvars,
buf->b_prompt_interrupt= interrupt_callback;
}
+/// "prompt_getprompt({buffer})" function
+void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // return an empty string by default, e.g. it's not a prompt buffer
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = NULL;
+
+ buf_T *const buf = tv_get_buf_from_arg(&argvars[0]);
+ if (buf == NULL) {
+ return;
+ }
+
+ if (!bt_prompt(buf)) {
+ return;
+ }
+
+ rettv->vval.v_string = vim_strsave(buf_prompt_text(buf));
+}
+
// "prompt_setprompt({buffer}, {text})" function
static void f_prompt_setprompt(typval_T *argvars,
typval_T *rettv, FunPtr fptr)
@@ -8868,56 +8932,30 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_sign_define(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *name;
- dict_T *dict;
- char *icon = NULL;
- char *linehl = NULL;
- char *text = NULL;
- char *texthl = NULL;
- char *numhl = NULL;
- rettv->vval.v_number = -1;
+ if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_UNKNOWN) {
+ // Define multiple signs
+ tv_list_alloc_ret(rettv, kListLenMayKnow);
- name = tv_get_string_chk(&argvars[0]);
- if (name == NULL) {
+ sign_define_multiple(argvars[0].vval.v_list, rettv->vval.v_list);
return;
}
- if (argvars[1].v_type != VAR_UNKNOWN) {
- if (argvars[1].v_type != VAR_DICT) {
- EMSG(_(e_dictreq));
- return;
- }
+ // Define a single sign
+ rettv->vval.v_number = -1;
- // sign attributes
- dict = argvars[1].vval.v_dict;
- if (tv_dict_find(dict, "icon", -1) != NULL) {
- icon = tv_dict_get_string(dict, "icon", true);
- }
- if (tv_dict_find(dict, "linehl", -1) != NULL) {
- linehl = tv_dict_get_string(dict, "linehl", true);
- }
- if (tv_dict_find(dict, "text", -1) != NULL) {
- text = tv_dict_get_string(dict, "text", true);
- }
- if (tv_dict_find(dict, "texthl", -1) != NULL) {
- texthl = tv_dict_get_string(dict, "texthl", true);
- }
- if (tv_dict_find(dict, "numhl", -1) != NULL) {
- numhl = tv_dict_get_string(dict, "numhl", true);
- }
+ name = tv_get_string_chk(&argvars[0]);
+ if (name == NULL) {
+ return;
}
- if (sign_define_by_name((char_u *)name, (char_u *)icon, (char_u *)linehl,
- (char_u *)text, (char_u *)texthl, (char_u *)numhl)
- == OK) {
- rettv->vval.v_number = 0;
+ if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_DICT) {
+ EMSG(_(e_dictreq));
+ return;
}
- xfree(icon);
- xfree(linehl);
- xfree(text);
- xfree(texthl);
- xfree(numhl);
+ rettv->vval.v_number = sign_define_from_dict(
+ name, argvars[1].v_type == VAR_DICT ? argvars[1].vval.v_dict : NULL);
}
/// "sign_getdefined()" function
@@ -9038,83 +9076,44 @@ cleanup:
/// "sign_place()" function
static void f_sign_place(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- int sign_id;
- char_u *group = NULL;
- const char *sign_name;
- buf_T *buf;
- dict_T *dict;
- dictitem_T *di;
- linenr_T lnum = 0;
- int prio = SIGN_DEF_PRIO;
- bool notanum = false;
+ dict_T *dict = NULL;
rettv->vval.v_number = -1;
- // Sign identifier
- sign_id = (int)tv_get_number_chk(&argvars[0], &notanum);
- if (notanum) {
- return;
- }
- if (sign_id < 0) {
- EMSG(_(e_invarg));
+ if (argvars[4].v_type != VAR_UNKNOWN
+ && (argvars[4].v_type != VAR_DICT
+ || ((dict = argvars[4].vval.v_dict) == NULL))) {
+ EMSG(_(e_dictreq));
return;
}
- // Sign group
- const char *group_chk = tv_get_string_chk(&argvars[1]);
- if (group_chk == NULL) {
- return;
- }
- if (group_chk[0] == '\0') {
- group = NULL; // global sign group
- } else {
- group = vim_strsave((const char_u *)group_chk);
- }
+ rettv->vval.v_number = sign_place_from_dict(
+ &argvars[0], &argvars[1], &argvars[2], &argvars[3], dict);
+}
- // Sign name
- sign_name = tv_get_string_chk(&argvars[2]);
- if (sign_name == NULL) {
- goto cleanup;
- }
+/// "sign_placelist()" function. Place multiple signs.
+static void f_sign_placelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ int sign_id;
- // Buffer to place the sign
- buf = get_buf_arg(&argvars[3]);
- if (buf == NULL) {
- goto cleanup;
+ tv_list_alloc_ret(rettv, kListLenMayKnow);
+
+ if (argvars[0].v_type != VAR_LIST) {
+ EMSG(_(e_listreq));
+ return;
}
- if (argvars[4].v_type != VAR_UNKNOWN) {
- if (argvars[4].v_type != VAR_DICT
- || ((dict = argvars[4].vval.v_dict) == NULL)) {
+ // Process the List of sign attributes
+ TV_LIST_ITER_CONST(argvars[0].vval.v_list, li, {
+ sign_id = -1;
+ if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) {
+ sign_id = sign_place_from_dict(
+ NULL, NULL, NULL, NULL, TV_LIST_ITEM_TV(li)->vval.v_dict);
+ } else {
EMSG(_(e_dictreq));
- goto cleanup;
- }
-
- // Line number where the sign is to be placed
- if ((di = tv_dict_find(dict, "lnum", -1)) != NULL) {
- lnum = (linenr_T)tv_get_number_chk(&di->di_tv, &notanum);
- if (notanum) {
- goto cleanup;
- }
- (void)lnum;
- lnum = tv_get_lnum(&di->di_tv);
}
- if ((di = tv_dict_find(dict, "priority", -1)) != NULL) {
- // Sign priority
- prio = (int)tv_get_number_chk(&di->di_tv, &notanum);
- if (notanum) {
- goto cleanup;
- }
- }
- }
-
- if (sign_place(&sign_id, group, (const char_u *)sign_name, buf, lnum, prio)
- == OK) {
- rettv->vval.v_number = sign_id;
- }
-
-cleanup:
- xfree(group);
+ tv_list_append_number(rettv->vval.v_list, sign_id);
+ });
}
/// "sign_undefine()" function
@@ -9122,6 +9121,14 @@ static void f_sign_undefine(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *name;
+ if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_UNKNOWN) {
+ // Undefine multiple signs
+ tv_list_alloc_ret(rettv, kListLenMayKnow);
+
+ sign_undefine_multiple(argvars[0].vval.v_list, rettv->vval.v_list);
+ return;
+ }
+
rettv->vval.v_number = -1;
if (argvars[0].v_type == VAR_UNKNOWN) {
@@ -9144,11 +9151,7 @@ static void f_sign_undefine(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "sign_unplace()" function
static void f_sign_unplace(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- dict_T *dict;
- dictitem_T *di;
- int sign_id = 0;
- buf_T *buf = NULL;
- char_u *group = NULL;
+ dict_T *dict = NULL;
rettv->vval.v_number = -1;
@@ -9157,46 +9160,38 @@ static void f_sign_unplace(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
- const char *group_chk = tv_get_string(&argvars[0]);
- if (group_chk[0] == '\0') {
- group = NULL; // global sign group
- } else {
- group = vim_strsave((const char_u *)group_chk);
- }
-
if (argvars[1].v_type != VAR_UNKNOWN) {
if (argvars[1].v_type != VAR_DICT) {
EMSG(_(e_dictreq));
- goto cleanup;
+ return;
}
dict = argvars[1].vval.v_dict;
-
- if ((di = tv_dict_find(dict, "buffer", -1)) != NULL) {
- buf = get_buf_arg(&di->di_tv);
- if (buf == NULL) {
- goto cleanup;
- }
- }
- if (tv_dict_find(dict, "id", -1) != NULL) {
- sign_id = tv_dict_get_number(dict, "id");
- }
}
- if (buf == NULL) {
- // Delete the sign in all the buffers
- FOR_ALL_BUFFERS(cbuf) {
- if (sign_unplace(sign_id, group, cbuf, 0) == OK) {
- rettv->vval.v_number = 0;
- }
- }
- } else {
- if (sign_unplace(sign_id, group, buf, 0) == OK) {
- rettv->vval.v_number = 0;
- }
+ rettv->vval.v_number = sign_unplace_from_dict(&argvars[0], dict);
+}
+
+/// "sign_unplacelist()" function
+static void f_sign_unplacelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ int retval;
+
+ tv_list_alloc_ret(rettv, kListLenMayKnow);
+
+ if (argvars[0].v_type != VAR_LIST) {
+ EMSG(_(e_listreq));
+ return;
}
-cleanup:
- xfree(group);
+ TV_LIST_ITER_CONST(argvars[0].vval.v_list, li, {
+ retval = -1;
+ if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) {
+ retval = sign_unplace_from_dict(NULL, TV_LIST_ITEM_TV(li)->vval.v_dict);
+ } else {
+ EMSG(_(e_dictreq));
+ }
+ tv_list_append_number(rettv->vval.v_list, retval);
+ });
}
/*
@@ -9265,6 +9260,7 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// struct storing information about current sort
typedef struct {
int item_compare_ic;
+ bool item_compare_lc;
bool item_compare_numeric;
bool item_compare_numbers;
bool item_compare_float;
@@ -9339,10 +9335,10 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero)
p2 = "";
}
if (!sortinfo->item_compare_numeric) {
- if (sortinfo->item_compare_ic) {
- res = STRICMP(p1, p2);
+ if (sortinfo->item_compare_lc) {
+ res = strcoll(p1, p2);
} else {
- res = STRCMP(p1, p2);
+ res = sortinfo->item_compare_ic ? STRICMP(p1, p2): STRCMP(p1, p2);
}
} else {
double n1, n2;
@@ -9477,6 +9473,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
}
info.item_compare_ic = false;
+ info.item_compare_lc = false;
info.item_compare_numeric = false;
info.item_compare_numbers = false;
info.item_compare_float = false;
@@ -9521,6 +9518,9 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
} else if (strcmp(info.item_compare_func, "i") == 0) {
info.item_compare_func = NULL;
info.item_compare_ic = true;
+ } else if (strcmp(info.item_compare_func, "l") == 0) {
+ info.item_compare_func = NULL;
+ info.item_compare_lc = true;
}
}
}