vim-patch:8.0.1570: can't use :popup for a menu in the terminal

Problem:    Can't use :popup for a menu in the terminal. (Wei Zhang)
Solution:   Make :popup work in the terminal.  Also fix that entries were
            included that don't work in the current state.
29a2c08d79
This commit is contained in:
zeertzjq 2022-06-30 15:30:54 +08:00
parent cf8df141f3
commit 610cf9f950
6 changed files with 86 additions and 7 deletions

View File

@ -577,8 +577,8 @@ a menu item - you don't need to do a :tunmenu as well.
5.9 Popup Menus
In the Win32 GUI, you can cause a menu to popup at the cursor. This behaves
similarly to the PopUp menus except that any menu tree can be popped up.
You can cause a menu to popup at the cursor. This behaves similarly to the
PopUp menus except that any menu tree can be popped up.
This command is for backwards compatibility, using it is discouraged, because
it behaves in a strange way.
@ -587,7 +587,6 @@ it behaves in a strange way.
:popu[p] {name} Popup the menu {name}. The menu named must
have at least one subentry, but need not
appear on the menu-bar (see |hidden-menus|).
{only available for Win32 GUI}
:popu[p]! {name} Like above, but use the position of the mouse
pointer instead of the cursor.

View File

@ -1991,7 +1991,7 @@ module.cmds = {
command='popup',
flags=bit.bor(NEEDARG, EXTRA, BANG, TRLBAR, NOTRLCOM, CMDWIN),
addr_type='ADDR_NONE',
func='ex_ni',
func='ex_popup',
},
{
command='ppop',

View File

@ -62,6 +62,7 @@
#include "nvim/os/time.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
#include "nvim/popupmnu.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
#include "nvim/screen.h"
@ -7985,6 +7986,11 @@ static void ex_nogui(exarg_T *eap)
eap->errmsg = N_("E25: Nvim does not have a built-in GUI");
}
static void ex_popup(exarg_T *eap)
{
pum_make_popup(eap->arg, eap->forceit);
}
static void ex_swapname(exarg_T *eap)
{
if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL) {

View File

@ -1382,6 +1382,16 @@ static int get_menu_mode(void)
return MENU_INDEX_INVALID;
}
int get_menu_mode_flag(void)
{
int mode = get_menu_mode();
if (mode == MENU_INDEX_INVALID) {
return 0;
}
return 1 << mode;
}
/// Display the Special "PopUp" menu as a pop-up at the current mouse
/// position. The "PopUpn" menu is for Normal mode, "PopUpi" for Insert mode,
/// etc.
@ -1545,6 +1555,52 @@ void ex_emenu(exarg_T *eap)
execute_menu(eap, menu);
}
/// Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy.
vimmenu_T *menu_find(const char *path_name)
{
vimmenu_T *menu = *get_root_menu(path_name);
char *saved_name = xstrdup(path_name);
char *name = saved_name;
while (*name) {
// find the end of one dot-separated name and put a NUL at the dot
char *p = menu_name_skip(name);
while (menu != NULL) {
if (menu_name_equal(name, menu)) {
if (menu->children == NULL) {
// found a menu item instead of a sub-menu
if (*p == NUL) {
emsg(_("E336: Menu path must lead to a sub-menu"));
} else {
emsg(_(e_notsubmenu));
}
menu = NULL;
goto theend;
}
if (*p == NUL) { // found a full match
goto theend;
}
break;
}
menu = menu->next;
}
if (menu == NULL) { // didn't find it
break;
}
// Found a match, search the sub-menu.
menu = menu->children;
name = p;
}
if (menu == NULL) {
emsg(_("E337: Menu not found - check menu names"));
}
theend:
xfree(saved_name);
return menu;
}
/*
* Translation of menu names. Just a simple lookup table.
*/

View File

@ -1000,10 +1000,13 @@ void pum_show_popupmenu(vimmenu_T *menu)
{
pum_undisplay(true);
pum_size = 0;
int mode = get_menu_mode_flag();
for (vimmenu_T *mp = menu->children; mp != NULL; mp = mp->next) {
if (menu_is_separator(mp->dname) || (mp->modes & mp->enabled & mode)) {
pum_size++;
}
}
int idx = 0;
pumitem_T *array = (pumitem_T *)xcalloc((size_t)pum_size, sizeof(pumitem_T));
@ -1011,7 +1014,7 @@ void pum_show_popupmenu(vimmenu_T *menu)
for (vimmenu_T *mp = menu->children; mp != NULL; mp = mp->next) {
if (menu_is_separator(mp->dname)) {
array[idx++].pum_text = (char_u *)"";
} else {
} else if (mp->modes & mp->enabled & mode) {
array[idx++].pum_text = (char_u *)mp->dname;
}
}
@ -1079,3 +1082,18 @@ void pum_show_popupmenu(vimmenu_T *menu)
xfree(array);
pum_undisplay(true);
}
void pum_make_popup(const char *path_name, int use_mouse_pos)
{
if (!use_mouse_pos) {
// Hack: set mouse position at the cursor so that the menu pops up
// around there.
mouse_row = curwin->w_winrow + curwin->w_wrow;
mouse_col = curwin->w_wincol + curwin->w_wcol;
}
vimmenu_T *menu = menu_find(path_name);
if (menu != NULL) {
pum_show_popupmenu(menu);
}
}

View File

@ -3748,7 +3748,7 @@ describe('API', function()
eq("foo", meths.cmd({ cmd = "Foo" }, { output = true }))
end)
it('errors if command is not implemented', function()
eq("Command not implemented: popup", pcall_err(meths.cmd, { cmd = "popup" }, {}))
eq("Command not implemented: winpos", pcall_err(meths.cmd, { cmd = "winpos" }, {}))
end)
it('works with empty arguments list', function()
meths.cmd({ cmd = "update" }, {})