mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +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,9 +708,12 @@ static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes)
 | 
			
		||||
/// @return false if could not find path_name
 | 
			
		||||
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);
 | 
			
		||||
  if (!menu) {
 | 
			
		||||
    return false;
 | 
			
		||||
  vimmenu_T *menu = *get_root_menu(path_name);
 | 
			
		||||
  if (*path_name != NUL) {
 | 
			
		||||
    menu = find_menu(menu, path_name, modes);
 | 
			
		||||
    if (!menu) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  for (; menu != NULL; menu = menu->next) {
 | 
			
		||||
    dict_T *d = menu_get_recursive(menu, modes);
 | 
			
		||||
@@ -726,13 +729,15 @@ bool menu_get(char *const path_name, int modes, list_T *list)
 | 
			
		||||
  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 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)
 | 
			
		||||
{
 | 
			
		||||
  assert(*name);
 | 
			
		||||
 | 
			
		||||
  while (*name) {
 | 
			
		||||
    // find the end of one dot-separated name and put a NUL at the dot
 | 
			
		||||
    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.
 | 
			
		||||
    name = p;
 | 
			
		||||
    assert(*name);
 | 
			
		||||
    menu = menu->children;
 | 
			
		||||
  }
 | 
			
		||||
  return menu;
 | 
			
		||||
 | 
			
		||||
  abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Show the mapping associated with a menu item or hierarchy in a sub-menu.
 | 
			
		||||
static int show_menus(char *const path_name, int modes)
 | 
			
		||||
{
 | 
			
		||||
  vimmenu_T *menu = *get_root_menu(path_name);
 | 
			
		||||
  if (menu != NULL) {
 | 
			
		||||
  vimmenu_T *menu = NULL;
 | 
			
		||||
  if (*path_name != NUL) {
 | 
			
		||||
    // 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) {
 | 
			
		||||
      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
 | 
			
		||||
  // Highlight title
 | 
			
		||||
  // Now we have found the matching menu, and we list the mappings.
 | 
			
		||||
  msg_puts_title(_("\n--- Menus ---"));
 | 
			
		||||
  show_menus_recursive(menu, modes, 0);
 | 
			
		||||
 | 
			
		||||
  if (menu != NULL) {
 | 
			
		||||
    show_menus_recursive(menu->parent, modes, 0);
 | 
			
		||||
  }
 | 
			
		||||
  return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -59,26 +59,80 @@ describe(':emenu', function()
 | 
			
		||||
  end)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
local test_menus_cmd = [=[
 | 
			
		||||
  aunmenu *
 | 
			
		||||
 | 
			
		||||
  nnoremenu &Test.Test inormal<ESC>
 | 
			
		||||
  inoremenu Test.Test insert
 | 
			
		||||
  vnoremenu Test.Test x
 | 
			
		||||
  cnoremenu Test.Test cmdmode
 | 
			
		||||
  menu Test.Nested.test level1
 | 
			
		||||
  menu Test.Nested.Nested2 level2
 | 
			
		||||
 | 
			
		||||
  nnoremenu <script> Export.Script p
 | 
			
		||||
  tmenu Export.Script This is the tooltip
 | 
			
		||||
  menu ]Export.hidden thisoneshouldbehidden
 | 
			
		||||
 | 
			
		||||
  nnoremenu Edit.Paste p
 | 
			
		||||
  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([=[
 | 
			
		||||
      aunmenu *
 | 
			
		||||
 | 
			
		||||
      nnoremenu &Test.Test inormal<ESC>
 | 
			
		||||
      inoremenu Test.Test insert
 | 
			
		||||
      vnoremenu Test.Test x
 | 
			
		||||
      cnoremenu Test.Test cmdmode
 | 
			
		||||
      menu Test.Nested.test level1
 | 
			
		||||
      menu Test.Nested.Nested2 level2
 | 
			
		||||
 | 
			
		||||
      nnoremenu <script> Export.Script p
 | 
			
		||||
      tmenu Export.Script This is the tooltip
 | 
			
		||||
      menu ]Export.hidden thisoneshouldbehidden
 | 
			
		||||
 | 
			
		||||
      nnoremenu Edit.Paste p
 | 
			
		||||
      cnoremenu Edit.Paste <C-R>"
 | 
			
		||||
    ]=])
 | 
			
		||||
    command(test_menus_cmd)
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it("path='', modes='a'", function()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user