mirror of
https://github.com/neovim/neovim
synced 2025-07-16 09:11:51 +00:00
fix(menu): fix listing of submenus (#34315)
Problem: Listing submenus with :menu doesn't work.
Solution: Don't go to the parent of the return value of find_menu(), and
handle empty path at the caller.
Related #8194, which actually only fixed the problem for menu_get(), not
for :menu Ex command.
(cherry picked from commit 5e470c7af5
)
This commit is contained in:
committed by
github-actions[bot]
parent
25a869a097
commit
f7b1b0595d
@ -708,10 +708,13 @@ static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes)
|
|||||||
/// @return false if could not find path_name
|
/// @return false if could not find path_name
|
||||||
bool menu_get(char *const path_name, int modes, list_T *list)
|
bool menu_get(char *const path_name, int modes, list_T *list)
|
||||||
{
|
{
|
||||||
vimmenu_T *menu = find_menu(*get_root_menu(path_name), path_name, modes);
|
vimmenu_T *menu = *get_root_menu(path_name);
|
||||||
|
if (*path_name != NUL) {
|
||||||
|
menu = find_menu(menu, path_name, modes);
|
||||||
if (!menu) {
|
if (!menu) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (; menu != NULL; menu = menu->next) {
|
for (; menu != NULL; menu = menu->next) {
|
||||||
dict_T *d = menu_get_recursive(menu, modes);
|
dict_T *d = menu_get_recursive(menu, modes);
|
||||||
if (d && tv_dict_len(d) > 0) {
|
if (d && tv_dict_len(d) > 0) {
|
||||||
@ -726,13 +729,15 @@ bool menu_get(char *const path_name, int modes, list_T *list)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find menu matching `name` and `modes`.
|
/// Find menu matching `name` and `modes`. Does not handle empty `name`.
|
||||||
///
|
///
|
||||||
/// @param menu top menu to start looking from
|
/// @param menu top menu to start looking from
|
||||||
/// @param name path towards the menu
|
/// @param name path towards the menu
|
||||||
/// @return menu if \p name is null, found menu or NULL
|
/// @return found menu or NULL
|
||||||
static vimmenu_T *find_menu(vimmenu_T *menu, char *name, int modes)
|
static vimmenu_T *find_menu(vimmenu_T *menu, char *name, int modes)
|
||||||
{
|
{
|
||||||
|
assert(*name);
|
||||||
|
|
||||||
while (*name) {
|
while (*name) {
|
||||||
// find the end of one dot-separated name and put a NUL at the dot
|
// find the end of one dot-separated name and put a NUL at the dot
|
||||||
char *p = menu_name_skip(name);
|
char *p = menu_name_skip(name);
|
||||||
@ -759,31 +764,29 @@ static vimmenu_T *find_menu(vimmenu_T *menu, char *name, int modes)
|
|||||||
}
|
}
|
||||||
// Found a match, search the sub-menu.
|
// Found a match, search the sub-menu.
|
||||||
name = p;
|
name = p;
|
||||||
|
assert(*name);
|
||||||
menu = menu->children;
|
menu = menu->children;
|
||||||
}
|
}
|
||||||
return menu;
|
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show the mapping associated with a menu item or hierarchy in a sub-menu.
|
/// Show the mapping associated with a menu item or hierarchy in a sub-menu.
|
||||||
static int show_menus(char *const path_name, int modes)
|
static int show_menus(char *const path_name, int modes)
|
||||||
{
|
{
|
||||||
vimmenu_T *menu = *get_root_menu(path_name);
|
vimmenu_T *menu = NULL;
|
||||||
if (menu != NULL) {
|
if (*path_name != NUL) {
|
||||||
// First, find the (sub)menu with the given name
|
// First, find the (sub)menu with the given name
|
||||||
menu = find_menu(menu, path_name, modes);
|
menu = find_menu(*get_root_menu(path_name), path_name, modes);
|
||||||
if (menu == NULL) {
|
if (menu == NULL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// When there are no menus at all, the title still needs to be shown.
|
|
||||||
|
|
||||||
// Now we have found the matching menu, and we list the mappings
|
// Now we have found the matching menu, and we list the mappings.
|
||||||
// Highlight title
|
|
||||||
msg_puts_title(_("\n--- Menus ---"));
|
msg_puts_title(_("\n--- Menus ---"));
|
||||||
|
show_menus_recursive(menu, modes, 0);
|
||||||
|
|
||||||
if (menu != NULL) {
|
|
||||||
show_menus_recursive(menu->parent, modes, 0);
|
|
||||||
}
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,10 +59,7 @@ describe(':emenu', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('menu_get', function()
|
local test_menus_cmd = [=[
|
||||||
before_each(function()
|
|
||||||
clear()
|
|
||||||
command([=[
|
|
||||||
aunmenu *
|
aunmenu *
|
||||||
|
|
||||||
nnoremenu &Test.Test inormal<ESC>
|
nnoremenu &Test.Test inormal<ESC>
|
||||||
@ -78,7 +75,64 @@ describe('menu_get', function()
|
|||||||
|
|
||||||
nnoremenu Edit.Paste p
|
nnoremenu Edit.Paste p
|
||||||
cnoremenu Edit.Paste <C-R>"
|
cnoremenu Edit.Paste <C-R>"
|
||||||
]=])
|
]=]
|
||||||
|
|
||||||
|
describe(':menu listing', function()
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
command(test_menus_cmd)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('matches by path argument', function()
|
||||||
|
eq(
|
||||||
|
[[
|
||||||
|
--- Menus ---
|
||||||
|
500 Edit
|
||||||
|
500 Paste
|
||||||
|
c* <C-R>"]],
|
||||||
|
n.exec_capture('cmenu Edit')
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
[[
|
||||||
|
--- Menus ---
|
||||||
|
500 &Test
|
||||||
|
500 Test
|
||||||
|
n* inormal<Esc>
|
||||||
|
500 Nested
|
||||||
|
500 test
|
||||||
|
n level1
|
||||||
|
500 Nested2
|
||||||
|
n level2]],
|
||||||
|
n.exec_capture('nmenu Test')
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
[[
|
||||||
|
--- Menus ---
|
||||||
|
500 Nested
|
||||||
|
500 test
|
||||||
|
o level1
|
||||||
|
500 Nested2
|
||||||
|
o level2]],
|
||||||
|
n.exec_capture('omenu Test.Nested')
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
[[
|
||||||
|
--- Menus ---
|
||||||
|
500 Test
|
||||||
|
n* inormal<Esc>
|
||||||
|
v* x
|
||||||
|
s* x
|
||||||
|
i* insert
|
||||||
|
c* cmdmode]],
|
||||||
|
n.exec_capture('amenu Test.Test')
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe('menu_get', function()
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
command(test_menus_cmd)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("path='', modes='a'", function()
|
it("path='', modes='a'", function()
|
||||||
|
Reference in New Issue
Block a user