feat(api): autocmd group can be either name or id (#17559)

* feat(api): `group` can be either string or int

This affects the following API functions:
- `vim.api.nvim_create_autocmd`
- `vim.api.nvim_get_autocmds`
- `vim.api.nvim_do_autocmd`

closes #17552

* refactor: add two maps for fast lookups

* fix: delete augroup info from id->name map

When in "stupid_legacy_mode", the value in name->id map would be updated
to `AUGROUP_DELETED`, but the entry would still remain in id->name. This
would create a problem in `augroup_name` function which would return the
name of the augroup instead of `--DELETED--`.

The id->name map is only used for fast loopup in `augroup_name` function
so there's no point in keeping the entry of deleted augroup in it.

Co-authored-by: TJ DeVries <devries.timothyj@gmail.com>
This commit is contained in:
Dhruv Manilawala
2022-03-08 09:45:43 +05:30
committed by GitHub
parent 3cc48e6273
commit 2783f4cc4a
6 changed files with 198 additions and 71 deletions

View File

@@ -105,15 +105,24 @@ static char_u *old_termresponse = NULL;
#define FOR_ALL_AUPATS_IN_EVENT(event, ap) \
for (AutoPat *ap = first_autopat[event]; ap != NULL; ap = ap->next) // NOLINT
// Map of autocmd group names.
// Map of autocmd group names and ids.
// name -> ID
static Map(String, int) augroup_map = MAP_INIT;
// ID -> name
static Map(String, int) map_augroup_name_to_id = MAP_INIT;
static Map(int, String) map_augroup_id_to_name = MAP_INIT;
static void augroup_map_del(char *name)
static void augroup_map_del(int id, char *name)
{
String key = map_key(String, int)(&augroup_map, cstr_as_string(name));
map_del(String, int)(&augroup_map, key);
api_free_string(key);
if (name != NULL) {
String key = map_key(String, int)(&map_augroup_name_to_id, cstr_as_string(name));
map_del(String, int)(&map_augroup_name_to_id, key);
api_free_string(key);
}
if (id > 0) {
String mapped = map_get(int, String)(&map_augroup_id_to_name, id);
api_free_string(mapped);
map_del(int, String)(&map_augroup_id_to_name, id);
}
}
@@ -382,12 +391,14 @@ int augroup_add(char *name)
}
if (existing_id == AUGROUP_DELETED) {
augroup_map_del(name);
augroup_map_del(existing_id, name);
}
int next_id = next_augroup_id++;
String name_copy = cstr_to_string(name);
map_put(String, int)(&augroup_map, name_copy, next_id);
String name_key = cstr_to_string(name);
String name_val = cstr_to_string(name);
map_put(String, int)(&map_augroup_name_to_id, name_key, next_id);
map_put(int, String)(&map_augroup_id_to_name, next_id, name_val);
return next_id;
}
@@ -416,7 +427,8 @@ void augroup_del(char *name, bool stupid_legacy_mode)
FOR_ALL_AUPATS_IN_EVENT(event, ap) {
if (ap->group == i && ap->pat != NULL) {
give_warning((char_u *)_("W19: Deleting augroup that is still in use"), true);
map_put(String, int)(&augroup_map, cstr_as_string(name), AUGROUP_DELETED);
map_put(String, int)(&map_augroup_name_to_id, cstr_as_string(name), AUGROUP_DELETED);
augroup_map_del(ap->group, NULL);
return;
}
}
@@ -432,7 +444,7 @@ void augroup_del(char *name, bool stupid_legacy_mode)
}
// Remove the group because it's not currently in use.
augroup_map_del(name);
augroup_map_del(i, name);
au_cleanup();
}
}
@@ -445,7 +457,7 @@ void augroup_del(char *name, bool stupid_legacy_mode)
int augroup_find(const char *name)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
int existing_id = map_get(String, int)(&augroup_map, cstr_as_string((char *)name));
int existing_id = map_get(String, int)(&map_augroup_name_to_id, cstr_as_string((char *)name));
if (existing_id == AUGROUP_DELETED) {
return existing_id;
}
@@ -487,13 +499,10 @@ char *augroup_name(int group)
return NULL;
}
String key;
int value;
map_foreach(&augroup_map, key, value, {
if (value == group) {
return key.data;
}
});
String key = map_get(int, String)(&map_augroup_id_to_name, group);
if (key.data != NULL) {
return key.data;
}
// If it's not in the map anymore, then it must have been deleted.
return (char *)get_deleted_augroup();
@@ -526,7 +535,7 @@ void do_augroup(char_u *arg, int del_group)
String name;
int value;
map_foreach(&augroup_map, name, value, {
map_foreach(&map_augroup_name_to_id, name, value, {
if (value > 0) {
msg_puts(name.data);
} else {
@@ -556,11 +565,17 @@ void free_all_autocmds(void)
// Delete the augroup_map, including free the data
String name;
int id;
map_foreach(&augroup_map, name, id, {
map_foreach(&map_augroup_name_to_id, name, id, {
(void)id;
api_free_string(name);
})
map_destroy(String, int)(&augroup_map);
map_destroy(String, int)(&map_augroup_name_to_id);
map_foreach(&map_augroup_id_to_name, id, name, {
(void)id;
api_free_string(name);
})
map_destroy(int, String)(&map_augroup_id_to_name);
}
#endif