aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-06-30 15:30:54 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-07-01 10:17:39 +0800
commit610cf9f95032bd219cb5695d169fe2cd698ec307 (patch)
treee294c5bcae1401e0ba3fa37ed6c60417d47f960f
parentcf8df141f3c7e706c86aadba404ae8ad54d5c795 (diff)
downloadrneovim-610cf9f95032bd219cb5695d169fe2cd698ec307.tar.gz
rneovim-610cf9f95032bd219cb5695d169fe2cd698ec307.tar.bz2
rneovim-610cf9f95032bd219cb5695d169fe2cd698ec307.zip
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. https://github.com/vim/vim/commit/29a2c08d792e4458a0af8371f5341394829fce29
-rw-r--r--runtime/doc/gui.txt5
-rw-r--r--src/nvim/ex_cmds.lua2
-rw-r--r--src/nvim/ex_docmd.c6
-rw-r--r--src/nvim/menu.c56
-rw-r--r--src/nvim/popupmnu.c22
-rw-r--r--test/functional/api/vim_spec.lua2
6 files changed, 86 insertions, 7 deletions
diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt
index e296141c39..4205362484 100644
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -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.
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index b18bdefc2a..cc69921883 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -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',
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 4c9c1665fd..2ca038e56d 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -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) {
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 5e4dc12e40..73472ff1c4 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -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.
*/
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index cf87f469b9..82ad409c39 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -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);
+ }
+}
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 858463efbd..002bcd92a4 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -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" }, {})