diff options
Diffstat (limited to 'src/nvim/eval')
-rw-r--r-- | src/nvim/eval/funcs.c | 49 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 32 | ||||
-rw-r--r-- | src/nvim/eval/typval.h | 1 |
3 files changed, 75 insertions, 7 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 01d23654de..deeda28571 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4312,6 +4312,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "title", "user-commands", // was accidentally included in 5.4 "user_commands", + "vartabs", "vertsplit", "virtualedit", "visual", @@ -8848,6 +8849,18 @@ static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + rettv->vval.v_number = 0; + + if (argvars[0].v_type != VAR_UNKNOWN) { + long col; + + col = (long)tv_get_number_chk(argvars, NULL); + if (col < 0) { + return; // type error; errmsg already given + } + rettv->vval.v_number = get_sw_value_col(curbuf, col); + return; + } rettv->vval.v_number = get_sw_value(curbuf); } @@ -8989,7 +9002,7 @@ static void f_sign_jump(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = -1; - // Sign identifer + // Sign identifier sign_id = (int)tv_get_number_chk(&argvars[0], ¬anum); if (notanum) { return; @@ -9037,7 +9050,7 @@ static void f_sign_place(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = -1; - // Sign identifer + // Sign identifier sign_id = (int)tv_get_number_chk(&argvars[0], ¬anum); if (notanum) { return; @@ -10189,6 +10202,38 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string = (char_u *)xmemdupz(p + n, (size_t)len); } +// "strptime({format}, {timestring})" function +static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + char fmt_buf[NUMBUFLEN]; + char str_buf[NUMBUFLEN]; + + struct tm tmval = { + .tm_isdst = -1, + }; + char *fmt = (char *)tv_get_string_buf(&argvars[0], fmt_buf); + char *str = (char *)tv_get_string_buf(&argvars[1], str_buf); + + vimconv_T conv = { + .vc_type = CONV_NONE, + }; + char_u *enc = enc_locale(); + convert_setup(&conv, p_enc, enc); + if (conv.vc_type != CONV_NONE) { + fmt = (char *)string_convert(&conv, (char_u *)fmt, NULL); + } + if (fmt == NULL + || os_strptime(str, fmt, &tmval) == NULL + || (rettv->vval.v_number = mktime(&tmval)) == -1) { + rettv->vval.v_number = 0; + } + if (conv.vc_type != CONV_NONE) { + xfree(fmt); + } + convert_setup(&conv, NULL, NULL); + xfree(enc); +} + /* * "strridx()" function */ diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 9be487f4fd..fe3d147040 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1109,6 +1109,7 @@ void tv_dict_watcher_add(dict_T *const dict, const char *const key_pattern, watcher->key_pattern_len = key_pattern_len; watcher->callback = callback; watcher->busy = false; + watcher->needs_free = false; QUEUE_INSERT_TAIL(&dict->watchers, &watcher->node); } @@ -1182,22 +1183,30 @@ bool tv_dict_watcher_remove(dict_T *const dict, const char *const key_pattern, QUEUE *w = NULL; DictWatcher *watcher = NULL; bool matched = false; - QUEUE_FOREACH(w, &dict->watchers) { + bool queue_is_busy = false; + QUEUE_FOREACH(w, &dict->watchers, { watcher = tv_dict_watcher_node_data(w); + if (watcher->busy) { + queue_is_busy = true; + } if (tv_callback_equal(&watcher->callback, &callback) && watcher->key_pattern_len == key_pattern_len && memcmp(watcher->key_pattern, key_pattern, key_pattern_len) == 0) { matched = true; break; } - } + }) if (!matched) { return false; } - QUEUE_REMOVE(w); - tv_dict_watcher_free(watcher); + if (queue_is_busy) { + watcher->needs_free = true; + } else { + QUEUE_REMOVE(w); + tv_dict_watcher_free(watcher); + } return true; } @@ -1258,9 +1267,10 @@ void tv_dict_watcher_notify(dict_T *const dict, const char *const key, typval_T rettv; + bool any_needs_free = false; dict->dv_refcount++; QUEUE *w; - QUEUE_FOREACH(w, &dict->watchers) { + QUEUE_FOREACH(w, &dict->watchers, { DictWatcher *watcher = tv_dict_watcher_node_data(w); if (!watcher->busy && tv_dict_watcher_matches(watcher, key)) { rettv = TV_INITIAL_VALUE; @@ -1268,7 +1278,19 @@ void tv_dict_watcher_notify(dict_T *const dict, const char *const key, callback_call(&watcher->callback, 3, argv, &rettv); watcher->busy = false; tv_clear(&rettv); + if (watcher->needs_free) { + any_needs_free = true; + } } + }) + if (any_needs_free) { + QUEUE_FOREACH(w, &dict->watchers, { + DictWatcher *watcher = tv_dict_watcher_node_data(w); + if (watcher->needs_free) { + QUEUE_REMOVE(w); + tv_dict_watcher_free(watcher); + } + }) } tv_dict_unref(dict); diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 531b17cb59..2b4612016b 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -89,6 +89,7 @@ typedef struct dict_watcher { size_t key_pattern_len; QUEUE node; bool busy; // prevent recursion if the dict is changed in the callback + bool needs_free; } DictWatcher; /// Bool variable values |