aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-11-23 09:54:48 +0800
committerGitHub <noreply@github.com>2022-11-23 09:54:48 +0800
commit4571ba4d0a5234408e544c3a98f107688a792f0d (patch)
tree0418fe6a170f8d2f6f97dd6182753dfdd89eb7bf /src/nvim/eval
parentd41e93d5a83642f90898cae211e017d99ff97fd9 (diff)
downloadrneovim-4571ba4d0a5234408e544c3a98f107688a792f0d.tar.gz
rneovim-4571ba4d0a5234408e544c3a98f107688a792f0d.tar.bz2
rneovim-4571ba4d0a5234408e544c3a98f107688a792f0d.zip
vim-patch:partial:9.0.0917: the WinScrolled autocommand event is not enough (#21161)
Problem: The WinScrolled autocommand event is not enough. Solution: Add WinResized and provide information about what changed. (closes vim/vim#11576) https://github.com/vim/vim/commit/35fc61cb5b5eba8bbb9d8f0700332fbab38f40ca Omit "func_name" comment in tv_dict_extend(): Vim9 script only. Skip layout locking and E1312. Skip list_alloc_with_items() and list_set_item(). Since this overrides remaining changes in patch 9.0.0913, that patch can now be marked as fully ported: vim-patch:9.0.0913: only change in current window triggers the WinScrolled event N/A patches for version.c: vim-patch:9.0.0919: build failure with tiny features Problem: Build failure with tiny features. Solution: Adjust #ifdef's. https://github.com/vim/vim/commit/9c5b7cb4cf67c64648a324e9dfd1e17d793335a4 Co-authored-by: Bram Moolenaar <Bram@vim.org>
Diffstat (limited to 'src/nvim/eval')
-rw-r--r--src/nvim/eval/typval.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index f38e07f09d..47c3551a56 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -2446,10 +2446,10 @@ void tv_dict_clear(dict_T *const d)
///
/// @param d1 Dictionary to extend.
/// @param[in] d2 Dictionary to extend with.
-/// @param[in] action "error", "force", "keep":
-///
+/// @param[in] action "error", "force", "move", "keep":
/// e*, including "error": duplicate key gives an error.
/// f*, including "force": duplicate d2 keys override d1.
+/// m*, including "move": move items instead of copying.
/// other, including "keep": duplicate d2 keys ignored.
void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action)
FUNC_ATTR_NONNULL_ALL
@@ -2458,19 +2458,31 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action
const char *const arg_errmsg = _("extend() argument");
const size_t arg_errmsg_len = strlen(arg_errmsg);
- TV_DICT_ITER(d2, di2, {
+ if (*action == 'm') {
+ hash_lock(&d2->dv_hashtab); // don't rehash on hash_remove()
+ }
+
+ HASHTAB_ITER(&d2->dv_hashtab, hi2, {
+ dictitem_T *const di2 = TV_DICT_HI2DI(hi2);
dictitem_T *const di1 = tv_dict_find(d1, (const char *)di2->di_key, -1);
// Check the key to be valid when adding to any scope.
if (d1->dv_scope != VAR_NO_SCOPE && !valid_varname((const char *)di2->di_key)) {
break;
}
if (di1 == NULL) {
- dictitem_T *const new_di = tv_dict_item_copy(di2);
- if (tv_dict_add(d1, new_di) == FAIL) {
- tv_dict_item_free(new_di);
- } else if (watched) {
- tv_dict_watcher_notify(d1, (const char *)new_di->di_key, &new_di->di_tv,
- NULL);
+ if (*action == 'm') {
+ // cheap way to move a dict item from "d2" to "d1"
+ dictitem_T *const new_di = di2;
+ tv_dict_add(d1, new_di);
+ hash_remove(&d2->dv_hashtab, hi2);
+ tv_dict_watcher_notify(d1, (const char *)new_di->di_key, &new_di->di_tv, NULL);
+ } else {
+ dictitem_T *const new_di = tv_dict_item_copy(di2);
+ if (tv_dict_add(d1, new_di) == FAIL) {
+ tv_dict_item_free(new_di);
+ } else if (watched) {
+ tv_dict_watcher_notify(d1, (const char *)new_di->di_key, &new_di->di_tv, NULL);
+ }
}
} else if (*action == 'e') {
semsg(_("E737: Key already exists: %s"), di2->di_key);
@@ -2501,6 +2513,10 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action
}
}
});
+
+ if (*action == 'm') {
+ hash_unlock(&d2->dv_hashtab);
+ }
}
/// Compare two dictionaries