From d48516d66dae7055f0bb79e4561a1d2207f36072 Mon Sep 17 00:00:00 2001 From: altermo <107814000+altermo@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:20:11 +0200 Subject: [PATCH] refactor: implement augroups as namespaces --- src/nvim/autocmd.c | 155 ++++++++++-------------- src/nvim/autocmd.h | 2 - test/functional/api/autocmd_spec.lua | 125 +++++++++++++++++++ test/functional/api/extmark_spec.lua | 24 ++-- test/functional/api/vim_spec.lua | 24 ++-- test/functional/lua/inspector_spec.lua | 12 +- test/functional/ui/bufhl_spec.lua | 19 +-- test/functional/ui/decorations_spec.lua | 2 +- 8 files changed, 234 insertions(+), 129 deletions(-) diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index c5d81d4cd2731b..63d8b16d653f05 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -8,6 +8,7 @@ #include #include "klib/kvec.h" +#include "nvim/api/extmark.h" #include "nvim/api/private/helpers.h" #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" @@ -90,12 +91,12 @@ static const char e_autocommand_nesting_too_deep[] // Code for automatic commands. static AutoPatCmd *active_apc_list = NULL; // stack of active autocommands -// ID for associating autocmds created via nvim_create_autocmd -// Used to delete autocmds from nvim_del_autocmd -static int next_augroup_id = 1; - -// use get_deleted_augroup() to get this -static const char *deleted_augroup = NULL; +// The ID of the deleted group. +// Zero until the group is initialized. +static int deleted_augroup_id = 0; +static const char *deleted_augroup_name = "--Deleted--"; +static Set(int) deleted_augroup_map = SET_INIT; +static Set(int) shown_deleted_augroup_map = SET_INIT; // The ID of the current group. static int current_augroup = AUGROUP_DEFAULT; @@ -111,31 +112,16 @@ static bool autocmd_include_groups = false; static char *old_termresponse = NULL; -// Map of autocmd group names and ids. -// name -> ID -// 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(int id, const char *name) +static void augroup_map_del(int id) { - if (name != NULL) { - String key; - map_del(String, int)(&map_augroup_name_to_id, cstr_as_string(name), &key); - api_free_string(key); - } - if (id > 0) { - String mapped = map_del(int, String)(&map_augroup_id_to_name, id, NULL); - api_free_string(mapped); - } + set_put(int, &deleted_augroup_map, id); } -static inline const char *get_deleted_augroup(void) FUNC_ATTR_ALWAYS_INLINE +static int get_deleted_augroup_id(void) { - if (deleted_augroup == NULL) { - deleted_augroup = _("--Deleted--"); - } - return deleted_augroup; + int id = augroup_add(deleted_augroup_name); + deleted_augroup_id = id; + return id; } static void au_show_for_all_events(int group, const char *pat) @@ -219,7 +205,7 @@ static void au_show_for_event(int group, event_T event, const char *pat) // show the group name, if it's not the default group if (ac->pat->group != AUGROUP_DEFAULT) { if (last_group_name == NULL) { - msg_puts_attr(get_deleted_augroup(), HL_ATTR(HLF_E)); + msg_puts_attr(deleted_augroup_name, HL_ATTR(HLF_E)); } else { msg_puts_attr(last_group_name, HL_ATTR(HLF_T)); } @@ -396,24 +382,16 @@ void aubuflocal_remove(buf_T *buf) int augroup_add(const char *name) { assert(STRICMP(name, "end") != 0); + assert(STRICMP(name, "") != 0); - int existing_id = augroup_find(name); - if (existing_id > 0) { - assert(existing_id != AUGROUP_DELETED); - return existing_id; - } + int id = (int)nvim_create_namespace(cstr_as_string(name)); - if (existing_id == AUGROUP_DELETED) { - augroup_map_del(existing_id, name); + if (set_has(int, &deleted_augroup_map, id)) { + set_put(int, &deleted_augroup_map, (int)nvim_create_namespace(cstr_as_string(""))); + set_del(int, &deleted_augroup_map, id); } - int next_id = next_augroup_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; + return id; } /// Delete the augroup that matches name. @@ -439,18 +417,21 @@ void augroup_del(char *name, bool stupid_legacy_mode) } if (stupid_legacy_mode) { + bool flag = false; FOR_ALL_AUEVENTS(event) { AutoCmdVec *const acs = &autocmds[(int)event]; for (size_t i = 0; i < kv_size(*acs); i++) { AutoPat *const ap = kv_A(*acs, i).pat; if (ap != NULL && ap->group == group) { give_warning(_("W19: Deleting augroup that is still in use"), true); - map_put(String, int)(&map_augroup_name_to_id, cstr_as_string(name), AUGROUP_DELETED); - augroup_map_del(ap->group, NULL); - return; + ap->group = get_deleted_augroup_id(); + flag = true; } } } + if (flag) { + set_put(int, &shown_deleted_augroup_map, group); + } } else { FOR_ALL_AUEVENTS(event) { AutoCmdVec *const acs = &autocmds[(int)event]; @@ -464,7 +445,7 @@ void augroup_del(char *name, bool stupid_legacy_mode) } // Remove the group because it's not currently in use. - augroup_map_del(group, name); + augroup_map_del(group); au_cleanup(); } @@ -476,11 +457,10 @@ 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)(&map_augroup_name_to_id, cstr_as_string(name)); - if (existing_id == AUGROUP_DELETED) { - return existing_id; + int existing_id = map_get(String, int)(&namespace_ids, cstr_as_string(name)); + if (set_has(int, &deleted_augroup_map, existing_id)) { + return AUGROUP_ERROR; } - if (existing_id > 0) { return existing_id; } @@ -493,38 +473,37 @@ char *augroup_name(int group) { assert(group != 0); - if (group == AUGROUP_DELETED) { - return (char *)get_deleted_augroup(); - } - if (group == AUGROUP_ALL) { group = current_augroup; } - // next_augroup_id is the "source of truth" about what autocmds have existed - // - // The map_size is not the source of truth because groups can be removed from - // the map. When this happens, the map size is reduced. That's why this function - // relies on next_augroup_id instead. + if (group < 0) { + return (char *)deleted_augroup_name; + } // "END" is always considered the last augroup ID. // Used for expand_get_event_name and expand_get_augroup_name - if (group == next_augroup_id) { + if (group == next_namespace_id) { return "END"; } - - // If it's larger than the largest group, then it doesn't have a name - if (group > next_augroup_id) { + if (group > next_namespace_id) { return NULL; } - - String key = map_get(int, String)(&map_augroup_id_to_name, group); - if (key.data != NULL) { - return key.data; + if (set_has(int, &deleted_augroup_map, group)) { + return (char *)deleted_augroup_name; + } + if (group == deleted_augroup_id) { + return ""; } - // If it's not in the map anymore, then it must have been deleted. - return (char *)get_deleted_augroup(); + String name; + int value; + map_foreach(&namespace_ids, name, value, { + if (value == group) { + return name.data; + } + }); + return ""; } /// Return true if augroup "name" exists. @@ -554,14 +533,18 @@ void do_augroup(char *arg, bool del_group) String name; int value; - map_foreach(&map_augroup_name_to_id, name, value, { - if (value > 0) { - msg_puts(name.data); - } else { - msg_puts(augroup_name(value)); + map_foreach(&namespace_ids, name, value, { + if (value > 0 && value != deleted_augroup_id) { + if (set_has(int, &deleted_augroup_map, value)) { + if (!set_has(int, &shown_deleted_augroup_map, value)) { + continue; + } + msg_puts(deleted_augroup_name); + } else { + msg_puts(name.data); + } + msg_puts(" "); } - - msg_puts(" "); }); msg_clr_eos(); @@ -581,17 +564,7 @@ void free_all_autocmds(void) au_need_clean = false; } - // Delete the augroup_map, including free the data - String name; - map_foreach_key(&map_augroup_name_to_id, name, { - api_free_string(name); - }) - map_destroy(String, &map_augroup_name_to_id); - - map_foreach_value(&map_augroup_id_to_name, name, { - api_free_string(name); - }) - map_destroy(int, &map_augroup_id_to_name); + set_destroy(int, &deleted_augroup_map); // aucmd_win[] is freed in win_free_all() } @@ -2028,10 +2001,12 @@ static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc) abort(); // unreachable case AUGROUP_DEFAULT: case AUGROUP_ALL: - case AUGROUP_DELETED: // omit group in these cases break; default: + if (group == deleted_augroup_id) { + break; + } PUT_C(data, "group", INTEGER_OBJ(group)); break; } @@ -2232,7 +2207,7 @@ char *expand_get_event_name(expand_T *xp, int idx) char *name = augroup_name(idx + 1); if (name != NULL) { // skip when not including groups or skip deleted entries - if (!autocmd_include_groups || name == get_deleted_augroup()) { + if (!autocmd_include_groups || name == deleted_augroup_name) { return ""; } @@ -2240,7 +2215,7 @@ char *expand_get_event_name(expand_T *xp, int idx) } // List event names - return event_names[idx - next_augroup_id].name; + return event_names[idx - next_namespace_id].name; } /// Function given to ExpandGeneric() to obtain the list of event names. Don't diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h index b298fbb6a117ca..ba931c6e950d42 100644 --- a/src/nvim/autocmd.h +++ b/src/nvim/autocmd.h @@ -58,8 +58,6 @@ enum { AUGROUP_DEFAULT = -1, ///< default autocmd group AUGROUP_ERROR = -2, ///< erroneous autocmd group AUGROUP_ALL = -3, ///< all autocmd groups - AUGROUP_DELETED = -4, ///< all autocmd groups - // AUGROUP_NS = -5, // TODO(tjdevries): Support namespaced based augroups }; enum { BUFLOCAL_PAT_LEN = 25, }; diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua index d2ec3a576ca044..e5e2c4d86fb91b 100644 --- a/test/functional/api/autocmd_spec.lua +++ b/test/functional/api/autocmd_spec.lua @@ -1539,4 +1539,129 @@ describe('autocmd api', function() eq(1, #with_group) end) end) + + describe('autocmd as namespace:', function() + it('named namespaces work as augroups', function() + local ns = api.nvim_create_namespace('test') + eq(true, pcall(api.nvim_get_autocmds, { group = 'test' })) + eq(true, pcall(api.nvim_get_autocmds, { group = ns })) + eq(true, pcall(api.nvim_create_autocmd, 'BufNew', { command = '', group = 'test' })) + eq(true, pcall(api.nvim_create_autocmd, 'BufNew', { command = '', group = ns })) + end) + + it('anonymous namespaces error when used as augroups', function() + local ns = api.nvim_create_namespace('') + eq(false, pcall(api.nvim_get_autocmds, { group = ns })) + eq(false, pcall(api.nvim_create_autocmd, 'BufNew', { command = '', group = ns })) + end) + + it('legacy style deleted autocmds work as expected', function() + api.nvim_create_augroup('TEMP_A', {}) + api.nvim_create_autocmd('BufNew', { command = '', group = 'TEMP_A' }) + + local ns = api.nvim_create_namespace('') + + command('augroup! TEMP_A') + + api.nvim_create_augroup('TEMP_B', {}) + api.nvim_create_autocmd('BufNew', { command = '', group = 'TEMP_B' }) + command('augroup! TEMP_B') + + eq(false, pcall(api.nvim_get_autocmds, { group = ns + 1 })) + eq(ns + 1, api.nvim_get_namespaces()['--Deleted--']) + local autocmds = api.nvim_get_autocmds({ event = 'BufNew' }) + eq(ns + 1, autocmds[1].group) + eq(ns + 1, autocmds[2].group) + + --eq('--Deleted--', autocmds[2].group_name) --TODO(altermo): fix this + + --TODO(altermo): maybe we should allow the usage of deleted augroup + --eq(2, #api.nvim_get_autocmds({ group = ns + 1 })) + --eq(false, pcall(api.nvim_create_autocmd, 'BufNew', { command = '', group = ns })) + end) + + it('listing augroups show named namespaces', function() + api.nvim_create_namespace('') + api.nvim_create_namespace('test') + api.nvim_create_namespace('') + + eq( + { 'END', 'nvim_cmdwin', 'nvim_swapfile', 'nvim_terminal', 'test' }, + exec_lua([[return vim.fn.getcompletion("","augroup")]]) + ) + eq( + 'nvim_terminal nvim_cmdwin nvim_swapfile test ', + api.nvim_exec2('augroup', { output = true }).output + ) + end) + + it('deleted augroup are sometimes not shown when listing augroups', function() + api.nvim_create_namespace('test') + api.nvim_del_augroup_by_name('test') + + eq( + { '--Deleted--', 'END', 'nvim_cmdwin', 'nvim_swapfile', 'nvim_terminal' }, + exec_lua([[return vim.fn.getcompletion("","augroup")]]) + ) + eq( + 'nvim_terminal nvim_cmdwin nvim_swapfile ', + api.nvim_exec2('augroup', { output = true }).output + ) + end) + + it( + 'legacy deleted augroup are sometimes shown as `--Deleted--` when listing augroups', + function() + api.nvim_create_augroup('TEMP_A', {}) + api.nvim_create_autocmd('BufNew', { command = '', group = 'TEMP_A' }) + command('augroup! TEMP_A') + + eq( + { '--Deleted--', 'END', 'nvim_cmdwin', 'nvim_swapfile', 'nvim_terminal' }, + exec_lua([[return vim.fn.getcompletion("","augroup")]]) + ) + eq( + 'nvim_terminal nvim_cmdwin nvim_swapfile --Deleted-- ', + api.nvim_exec2('augroup', { output = true }).output + ) + + api.nvim_create_augroup('TEMP_A', {}) + api.nvim_create_autocmd('BufNew', { command = '', group = 'TEMP_A' }) + command('augroup! TEMP_A') + + eq( + 'nvim_terminal nvim_cmdwin nvim_swapfile --Deleted-- ', + api.nvim_exec2('augroup', { output = true }).output + ) + + api.nvim_create_augroup('TEMP_B', {}) + api.nvim_create_autocmd('BufNew', { command = '', group = 'TEMP_B' }) + command('augroup! TEMP_B') + + eq( + 'nvim_terminal nvim_cmdwin nvim_swapfile --Deleted-- --Deleted-- ', + api.nvim_exec2('augroup', { output = true }).output + ) + + api.nvim_create_augroup('TEMP_B', {}) + api.nvim_create_autocmd('BufNew', { command = '', group = 'TEMP_B' }) + command('augroup! TEMP_B') + + eq({ + '--Deleted--', + '--Deleted--', + '--Deleted--', + '--Deleted--', + 'END', + 'nvim_cmdwin', + 'nvim_swapfile', + 'nvim_terminal', + }, exec_lua([[return vim.fn.getcompletion("","augroup")]])) + eq( + 'nvim_terminal nvim_cmdwin nvim_swapfile --Deleted-- --Deleted-- ', + api.nvim_exec2('augroup', { output = true }).output + ) + end + ) + end) end) diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua index 82e7ad3988a366..f7f22172021e34 100644 --- a/test/functional/api/extmark_spec.lua +++ b/test/functional/api/extmark_spec.lua @@ -1423,13 +1423,11 @@ describe('API/extmarks', function() it('throws consistent error codes', function() local ns_invalid = ns2 + 1 - eq( - "Invalid 'ns_id': 3", - pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2]) - ) - eq("Invalid 'ns_id': 3", pcall_err(api.nvim_buf_del_extmark, 0, ns_invalid, marks[1])) - eq("Invalid 'ns_id': 3", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2])) - eq("Invalid 'ns_id': 3", pcall_err(get_extmark_by_id, ns_invalid, marks[1])) + local errmsg = "Invalid 'ns_id': " .. ns_invalid + eq(errmsg, pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2])) + eq(errmsg, pcall_err(api.nvim_buf_del_extmark, 0, ns_invalid, marks[1])) + eq(errmsg, pcall_err(get_extmarks, ns_invalid, positions[1], positions[2])) + eq(errmsg, pcall_err(get_extmark_by_id, ns_invalid, marks[1])) end) it('when col = line-length, set the mark on eol', function() @@ -1532,7 +1530,7 @@ describe('API/extmarks', function() 0, 0, { - ns_id = 1, + ns_id = ns, end_col = 0, end_row = 1, right_gravity = true, @@ -1595,7 +1593,7 @@ describe('API/extmarks', function() hl_group = 'String', hl_mode = 'blend', line_hl_group = 'Statement', - ns_id = 1, + ns_id = ns, number_hl_group = 'Statement', priority = 0, right_gravity = false, @@ -1618,7 +1616,7 @@ describe('API/extmarks', function() 0, 0, { - ns_id = 1, + ns_id = ns, right_gravity = true, priority = 0, virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } }, @@ -1633,7 +1631,7 @@ describe('API/extmarks', function() 0, 0, { - ns_id = 1, + ns_id = ns, cursorline_hl_group = 'Statement', priority = 4096, right_gravity = true, @@ -1652,7 +1650,7 @@ describe('API/extmarks', function() end_col = 1, end_right_gravity = false, end_row = 0, - ns_id = 1, + ns_id = ns, right_gravity = true, spell = true, }, @@ -1668,7 +1666,7 @@ describe('API/extmarks', function() end_col = 1, end_right_gravity = false, end_row = 0, - ns_id = 1, + ns_id = ns, right_gravity = true, spell = false, }, diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index c412773482ff50..b9364ccd9053f0 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3013,14 +3013,22 @@ describe('API', function() describe('nvim_create_namespace', function() it('works', function() - eq({}, api.nvim_get_namespaces()) - eq(1, api.nvim_create_namespace('ns-1')) - eq(2, api.nvim_create_namespace('ns-2')) - eq(1, api.nvim_create_namespace('ns-1')) - eq({ ['ns-1'] = 1, ['ns-2'] = 2 }, api.nvim_get_namespaces()) - eq(3, api.nvim_create_namespace('')) - eq(4, api.nvim_create_namespace('')) - eq({ ['ns-1'] = 1, ['ns-2'] = 2 }, api.nvim_get_namespaces()) + local augoup_ns = { nvim_cmdwin = 2, nvim_swapfile = 3, nvim_terminal = 1 } + eq(augoup_ns, api.nvim_get_namespaces()) + local ns_offset = vim.tbl_count(augoup_ns) + eq(1 + ns_offset, api.nvim_create_namespace('ns-1')) + eq(2 + ns_offset, api.nvim_create_namespace('ns-2')) + eq(1 + ns_offset, api.nvim_create_namespace('ns-1')) + eq( + vim.tbl_extend('error', { ['ns-1'] = 1 + ns_offset, ['ns-2'] = 2 + ns_offset }, augoup_ns), + api.nvim_get_namespaces() + ) + eq(3 + ns_offset, api.nvim_create_namespace('')) + eq(4 + ns_offset, api.nvim_create_namespace('')) + eq( + vim.tbl_extend('error', { ['ns-1'] = 1 + ns_offset, ['ns-2'] = 2 + ns_offset }, augoup_ns), + api.nvim_get_namespaces() + ) end) end) diff --git a/test/functional/lua/inspector_spec.lua b/test/functional/lua/inspector_spec.lua index 3fd8daff2e132d..5e61b131b2e965 100644 --- a/test/functional/lua/inspector_spec.lua +++ b/test/functional/lua/inspector_spec.lua @@ -23,9 +23,9 @@ describe('vim.inspect_pos', function() vim.api.nvim_buf_set_extmark(buf, ns1, 0, 10, { hl_group = "Normal" }) vim.api.nvim_buf_set_extmark(buf, ns2, 0, 10, { hl_group = "Normal" }) vim.cmd("syntax on") - return {buf, vim.inspect_pos(0, 0, 10), vim.inspect_pos(buf1, 0, 10).syntax } + return {ns1, buf, vim.inspect_pos(0, 0, 10), vim.inspect_pos(buf1, 0, 10).syntax } ]]) - local buf, items, other_buf_syntax = unpack(ret) + local ns1, buf, items, other_buf_syntax = unpack(ret) eq('', eval('v:errmsg')) eq({ @@ -39,12 +39,12 @@ describe('vim.inspect_pos', function() end_row = 0, id = 1, ns = 'ns1', - ns_id = 1, + ns_id = ns1, opts = { hl_eol = false, hl_group = 'Normal', hl_group_link = 'Normal', - ns_id = 1, + ns_id = ns1, priority = 4096, right_gravity = true, }, @@ -56,12 +56,12 @@ describe('vim.inspect_pos', function() end_row = 0, id = 1, ns = '', - ns_id = 2, + ns_id = ns1 + 1, opts = { hl_eol = false, hl_group = 'Normal', hl_group_link = 'Normal', - ns_id = 2, + ns_id = ns1 + 1, priority = 4096, right_gravity = true, }, diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua index 7ea7319cf85575..d284bf91e91c3e 100644 --- a/test/functional/ui/bufhl_spec.lua +++ b/test/functional/ui/bufhl_spec.lua @@ -702,14 +702,14 @@ describe('Buffer highlighting', function() local s1 = { { 'Köttbullar', 'Comment' }, { 'Kräuterbutter' } } local s2 = { { 'こんにちは', 'Comment' } } - set_virtual_text(0, id1, 0, s1, {}) + local ns = set_virtual_text(0, id1, 0, s1, {}) eq({ { 1, 0, 0, { - ns_id = 1, + ns_id = ns, priority = 0, virt_text = s1, -- other details @@ -729,7 +729,7 @@ describe('Buffer highlighting', function() lastline, 0, { - ns_id = 1, + ns_id = ns, priority = 0, virt_text = s2, -- other details @@ -898,11 +898,12 @@ describe('Buffer highlighting', function() end) it('and virtual text use the same namespace counter', function() - eq(1, add_highlight(0, 0, 'String', 0, 0, -1)) - eq(2, set_virtual_text(0, 0, 0, { { '= text', 'Comment' } }, {})) - eq(3, api.nvim_create_namespace('my-ns')) - eq(4, add_highlight(0, 0, 'String', 0, 0, -1)) - eq(5, set_virtual_text(0, 0, 0, { { '= text', 'Comment' } }, {})) - eq(6, api.nvim_create_namespace('other-ns')) + local ns = api.nvim_create_namespace('') + eq(1 + ns, add_highlight(0, 0, 'String', 0, 0, -1)) + eq(2 + ns, set_virtual_text(0, 0, 0, { { '= text', 'Comment' } }, {})) + eq(3 + ns, api.nvim_create_namespace('my-ns')) + eq(4 + ns, add_highlight(0, 0, 'String', 0, 0, -1)) + eq(5 + ns, set_virtual_text(0, 0, 0, { { '= text', 'Comment' } }, {})) + eq(6 + ns, api.nvim_create_namespace('other-ns')) end) end) diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index eea62140ce55c4..3620f177460360 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -2144,7 +2144,7 @@ describe('extmark decorations', function() eq({ { 1, 0, 8, { end_col = 13, end_right_gravity = false, end_row = 0, hl_eol = false, hl_group = "NonText", undo_restore = false, - ns_id = 1, priority = 4096, right_gravity = true } } }, + ns_id = ns, priority = 4096, right_gravity = true } } }, api.nvim_buf_get_extmarks(0, ns, {0,0}, {0, -1}, {details=true})) end)