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

@@ -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,9 +1000,12 @@ 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) {
pum_size++;
if (menu_is_separator(mp->dname) || (mp->modes & mp->enabled & mode)) {
pum_size++;
}
}
int idx = 0;
@@ -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);
}
}