]> granicus.if.org Git - vim/commitdiff
patch 8.1.0487: no menus specifically for the terminal window v8.1.0487
authorBram Moolenaar <Bram@vim.org>
Fri, 19 Oct 2018 20:36:53 +0000 (22:36 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 19 Oct 2018 20:36:53 +0000 (22:36 +0200)
Problem:    No menus specifically for the terminal window.
Solution:   Add :tlmenu. (Yee Cheng Chin, closes #3439) Add a menu test.

19 files changed:
runtime/delmenu.vim
runtime/doc/autocmd.txt
runtime/doc/gui.txt
runtime/doc/index.txt
runtime/doc/tags
runtime/doc/terminal.txt
runtime/doc/todo.txt
runtime/doc/usr_42.txt
runtime/menu.vim
runtime/syntax/vim.vim
src/ex_cmdidxs.h
src/ex_cmds.h
src/ex_docmd.c
src/menu.c
src/popupmnu.c
src/proto/menu.pro
src/structs.h
src/testdir/test_menu.vim
src/version.c

index 81df87d3463ac95b03dbd3563b6cb2316ef37f27..5cefe26d35fdaa1fefdf524c24e4c6adf606a54e 100644 (file)
@@ -5,6 +5,7 @@
 " Last Change: 2001 May 27
 
 aunmenu *
+tlunmenu *
 
 silent! unlet did_install_default_menus
 silent! unlet did_install_syntax_menu
index b6e50238fd0cd649fb1296f486dcfa2982871ce9..eae83d4ad697c6405030c53474d40cd9a66605ba 100644 (file)
@@ -835,13 +835,14 @@ MenuPopup                 Just before showing the popup menu (under the
                                right mouse button).  Useful for adjusting the
                                menu for what is under the cursor or mouse
                                pointer.
-                               The pattern is matched against a single
-                               character representing the mode:
+                               The pattern is matched against one or two
+                               characters representing the mode:
                                        n       Normal
                                        v       Visual
                                        o       Operator-pending
                                        i       Insert
                                        c       Command line
+                                       tl      Terminal
                                                        *OptionSet*
 OptionSet                      After setting an option.  The pattern is
                                matched against the long option name.
index 603a4d4ad3f120d22fe14b064f9451dc27ab9997..c621b40cbf06abb17a8a44026f22896134d7a5e8 100644 (file)
@@ -547,15 +547,16 @@ floating menus that do not appear on the main menu bar.
 
 5.2 Creating New Menus                                 *creating-menus*
 
-                               *:me*  *:menu*  *:noreme*  *:noremenu*
-                               *:am*  *:amenu* *:an*      *:anoremenu*
-                               *:nme* *:nmenu* *:nnoreme* *:nnoremenu*
-                               *:ome* *:omenu* *:onoreme* *:onoremenu*
-                               *:vme* *:vmenu* *:vnoreme* *:vnoremenu*
-                               *:xme* *:xmenu* *:xnoreme* *:xnoremenu*
-                               *:sme* *:smenu* *:snoreme* *:snoremenu*
-                               *:ime* *:imenu* *:inoreme* *:inoremenu*
-                               *:cme* *:cmenu* *:cnoreme* *:cnoremenu*
+                               *:me*  *:menu*   *:noreme*  *:noremenu*
+                               *:am*  *:amenu*  *:an*      *:anoremenu*
+                               *:nme* *:nmenu*  *:nnoreme* *:nnoremenu*
+                               *:ome* *:omenu*  *:onoreme* *:onoremenu*
+                               *:vme* *:vmenu*  *:vnoreme* *:vnoremenu*
+                               *:xme* *:xmenu*  *:xnoreme* *:xnoremenu*
+                               *:sme* *:smenu*  *:snoreme* *:snoremenu*
+                               *:ime* *:imenu*  *:inoreme* *:inoremenu*
+                               *:cme* *:cmenu*  *:cnoreme* *:cnoremenu*
+                               *:tlm* *:tlmenu* *:tln*     *:tlnoremenu*
                                *E330* *E327* *E331* *E336* *E333*
                                *E328* *E329* *E337* *E792*
 To create a new menu item, use the ":menu" commands.  They are mostly like
@@ -571,6 +572,10 @@ the mouse button down on this will pop up a menu containing the item
 "Big Changes", which is a sub-menu containing the item "Delete All Spaces",
 which when selected, performs the operation.
 
+To create a menu for terminal mode, use |:tlmenu| instead of |:tmenu| unlike
+key mapping (|:tmap|). This is because |:tmenu| is already used for defining
+tooltips for menus. See |terminal-typing|.
+
 Special characters in a menu name:
 
        &       The next character is the shortcut key.  Make sure each
@@ -589,9 +594,9 @@ With the shortcut "F" (while keeping the <Alt> key pressed), and then "O",
 this menu can be used.  The second part is shown as "Open     :e".  The ":e"
 is right aligned, and the "O" is underlined, to indicate it is the shortcut.
 
-The ":amenu" command can be used to define menu entries for all modes at once.
-To make the command work correctly, a character is automatically inserted for
-some modes:
+The ":amenu" command can be used to define menu entries for all modes at once,
+except for Terminal mode.  To make the command work correctly, a character is
+automatically inserted for some modes:
        mode            inserted        appended        ~
        Normal          nothing         nothing
        Visual          <C-C>           <C-\><C-G>
@@ -865,6 +870,16 @@ be used to complete the name of the menu item.
                                insert-mode menu Eg: >
        :emenu File.Exit
 
+:[range]em[enu] {mode} {menu}  Like above, but execute the menu for {mode}:
+                                   'n': |:nmenu|  Normal mode
+                                   'v': |:vmenu|  Visual mode
+                                   's': |:smenu|  Select mode
+                                   'o': |:omenu|  Operator-pending mode
+                                   't': |:tlmenu| Terminal mode
+                                   'i': |:imenu|  Insert mode
+                                   'c': |:cmenu|  Cmdline mode
+                               
+
 If the console-mode vim has been compiled with WANT_MENU defined, you can
 use :emenu to access useful menu items you may have got used to from GUI
 mode.  See 'wildmenu' for an option that works well with this.  See
@@ -885,6 +900,7 @@ using the last visual selection.
                                                *:sunme* *:sunmenu*
                                                *:iunme* *:iunmenu*
                                                *:cunme* *:cunmenu*
+                                               *:tlu*   *:tlunmenu*
 To delete a menu item or a whole submenu, use the unmenu commands, which are
 analogous to the unmap commands.  Eg: >
     :unmenu! Edit.Paste
@@ -951,6 +967,8 @@ See section |42.4| in the user manual.
 :tu[nmenu] {menupath}          Remove a tip for a menu or tool.
                                {only in X11 and Win32 GUI}
 
+Note: To create menus for terminal mode, use |:tlmenu| instead.
+
 When a tip is defined for a menu item, it appears in the command-line area
 when the mouse is over that item, much like a standard Windows menu hint in
 the status bar.  (Except when Vim is in Command-line mode, when of course
index 1a0d225267d9f99867238d7bd5169cebfb097b81..4abd25aa05ce75772e8007813a1dba8913667009 100644 (file)
@@ -1583,6 +1583,9 @@ tag             command         action ~
 |:tjump|       :tj[ump]        like ":tselect", but jump directly when there
                                is only one match
 |:tlast|       :tl[ast]        jump to last matching tag
+|:tlmenu|      :tlm[enu]       add menu for Terminal-Job mode
+|:tlnoremenu|  :tln[oremenu]   like ":noremenu" but for Terminal-Job mode
+|:tlunmenu|    :tlu[nmenu]     remove menu for Terminal-Job mode
 |:tmapclear|   :tmapc[lear]    remove all mappings for Terminal-Job mode
 |:tmap|                :tma[p]         like ":map" but for Terminal-Job mode
 |:tmenu|       :tm[enu]        define menu tooltip
index b31d430cae5179ce161e3195a6fb62eb98e54702..3936ebc71ef19f9bcd4315eaf2c463ee3e76e051 100644 (file)
@@ -3185,6 +3185,12 @@ $VIM_POSIX       vi_diff.txt     /*$VIM_POSIX*
 :tjump tagsrch.txt     /*:tjump*
 :tl    tagsrch.txt     /*:tl*
 :tlast tagsrch.txt     /*:tlast*
+:tlm   gui.txt /*:tlm*
+:tlmenu        gui.txt /*:tlmenu*
+:tln   gui.txt /*:tln*
+:tlnoremenu    gui.txt /*:tlnoremenu*
+:tlu   gui.txt /*:tlu*
+:tlunmenu      gui.txt /*:tlunmenu*
 :tm    gui.txt /*:tm*
 :tma   map.txt /*:tma*
 :tmap  map.txt /*:tmap*
index abc3d94fb485667b469ddeaf7ec83499dd71d418..499a2450a640062cfb7df64bc8ca497c3e5014eb 100644 (file)
@@ -114,6 +114,9 @@ break: >
    tnoremap <Esc> <C-W>N
    set notimeout ttimeout timeoutlen=100
 
+You can also create menus similar to terminal mode mappings, but you have to
+use |:tlmenu| instead of |:tmenu|.
+
 <                                                      *options-in-terminal*
 After opening the terminal window and setting 'buftype' to "terminal" the
 TerminalOpen autocommand event is triggered.  This makes it possible to set
index ea1e00a2e45120349524931410723ad9455177b2..f9c210139bd6566e36b965a2f61e83c5319bded9 100644 (file)
@@ -95,9 +95,6 @@ Terminal emulator window:
 Key mapping times out when using a timer in Gvim. (Michael Henry, 2018 Sep 9,
 #3417)
 
-Patch to check for directory access in term_start(). (Jason Franklin, 2018 Oct
-15)
-
 Does not build with MinGW out of the box:
 - _stat64 is not defined, need to use "struct stat" in vim.h
 - WINVER conflict, should use 0x0600 by default?
@@ -189,8 +186,6 @@ Memory leak in test_terminal:
 
 gethostbyname() is old, use getaddrinfo() if available. (#3227)
 
-Delete the src/main.aap file?
-
 matchaddpos() gets slow with many matches.  Proposal by Rick Howe, 2018 Jul
 19.
 
@@ -198,8 +193,6 @@ Patch to support ":tag <tagkind> <tagname>". (emmrk, 2018 May 7, #2871)
 Use something like ":tag {kind}/{tagname}".
 Not ready to include.
 
-Patch to support menus in terminal: ":tlmenu". (Yee Cheng Chin, #3439)
-
 :pedit resets the 'buflisted' option unexpectedly. (Wang Shidong, 2018 Oct 12,
 #3536)
 
@@ -2223,8 +2216,6 @@ still delete them.  Also convert all buffer file names?
 "gqip" in Insert mode has an off-by-one error, causing it to reflow text.
 (Raul Coronado, 2009 Nov 2)
 
-Update src/testdir/main.aap.
-
 Something wrong with session that has "cd" commands and "badd", in such a way
 that Vim doesn't find the edited file in the buffer list, causing the
 ATTENTION message?  (Tony Mechelynck, 2008 Dec 1)
index 46483613ae7bb70cf2e6a6647172190c358a4ae6..290191335cea33d3ee01dcf2c12fa4dd3c25678b 100644 (file)
@@ -150,7 +150,8 @@ like the variations on the ":map" command:
        :menu!          Insert and Command-line mode
        :imenu          Insert mode
        :cmenu          Command-line mode
-       :amenu          All modes
+       :tlmenu         Terminal mode
+       :amenu          All modes (except for Terminal mode)
 
 To avoid that the commands of a menu item are being mapped, use the command
 ":noremenu", ":nnoremenu", ":anoremenu", etc.
index 5e4bd1f11b4d4b907f5206c37f2fdb9ceda50793..a6ecf3ce52ecb38345d26dbdfcbd33076a83afd0 100644 (file)
@@ -160,6 +160,9 @@ vnoremenu 20.350 &Edit.&Copy<Tab>"+y                "+y
 cnoremenu 20.350 &Edit.&Copy<Tab>"+y           <C-Y>
 nnoremenu 20.360 &Edit.&Paste<Tab>"+gP         "+gP
 cnoremenu       &Edit.&Paste<Tab>"+gP          <C-R>+
+if exists(':tlmenu')
+  tlnoremenu    &Edit.&Paste<Tab>"+gP          <C-W>"+
+endif
 exe 'vnoremenu <script> &Edit.&Paste<Tab>"+gP  ' . paste#paste_cmd['v']
 exe 'inoremenu <script> &Edit.&Paste<Tab>"+gP  ' . paste#paste_cmd['i']
 nnoremenu 20.370 &Edit.Put\ &Before<Tab>[p     [p
index 30c3f2f16e64475c11acab8a7b26126f13ce5bd2..abd2d180189575b593c87755cc7ea6b927c08320 100644 (file)
@@ -407,7 +407,7 @@ syn case match
 " Menus {{{2
 " =====
 syn cluster    vimMenuList contains=vimMenuBang,vimMenuPriority,vimMenuName,vimMenuMod
-syn keyword    vimCommand      am[enu] an[oremenu] aun[menu] cme[nu] cnoreme[nu] cunme[nu] ime[nu] inoreme[nu] iunme[nu] me[nu] nme[nu] nnoreme[nu] noreme[nu] nunme[nu] ome[nu] onoreme[nu] ounme[nu] unme[nu] vme[nu] vnoreme[nu] vunme[nu] skipwhite nextgroup=@vimMenuList
+syn keyword    vimCommand      am[enu] an[oremenu] aun[menu] cme[nu] cnoreme[nu] cunme[nu] ime[nu] inoreme[nu] iunme[nu] me[nu] nme[nu] nnoreme[nu] noreme[nu] nunme[nu] ome[nu] onoreme[nu] ounme[nu] tlm[enu] tln[oremenu] tlu[nmenu] unme[nu] vme[nu] vnoreme[nu] vunme[nu] skipwhite nextgroup=@vimMenuList
 syn match      vimMenuName     "[^ \t\\<]\+"   contained nextgroup=vimMenuNameMore,vimMenuMap
 syn match      vimMenuPriority "\d\+\(\.\d\+\)*"       contained skipwhite nextgroup=vimMenuName
 syn match      vimMenuNameMore "\c\\\s\|<tab>\|\\\."   contained nextgroup=vimMenuName,vimMenuNameMore contains=vimNotation
index 736cc38895412436485596b9484ab4d8c40a967d..1c435caea8761fc445ea0212eacafc798eec4454 100644 (file)
@@ -25,12 +25,12 @@ static const unsigned short cmdidxs1[26] =
   /* r */ 351,
   /* s */ 370,
   /* t */ 437,
-  /* u */ 477,
-  /* v */ 488,
-  /* w */ 506,
-  /* x */ 521,
-  /* y */ 530,
-  /* z */ 531
+  /* u */ 480,
+  /* v */ 491,
+  /* w */ 509,
+  /* x */ 524,
+  /* y */ 533,
+  /* z */ 534
 };
 
 /*
@@ -60,7 +60,7 @@ static const unsigned char cmdidxs2[26][26] =
   /* q */ {  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
   /* r */ {  0,  0,  0,  0,  0,  0,  0,  0, 11,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 13, 18,  0,  0,  0,  0 },
   /* s */ {  2,  6, 15,  0, 18, 22,  0, 24, 25,  0,  0, 28, 30, 34, 38, 40,  0, 48,  0, 49,  0, 61, 62,  0, 63,  0 },
-  /* t */ {  2,  0, 19,  0, 22, 24,  0, 25,  0, 26,  0, 27, 28, 31, 33, 34,  0, 35, 37,  0, 38,  0,  0,  0,  0,  0 },
+  /* t */ {  2,  0, 19,  0, 22, 24,  0, 25,  0, 26,  0, 27, 31, 34, 36, 37,  0, 38, 40,  0, 41,  0,  0,  0,  0,  0 },
   /* u */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
   /* v */ {  0,  0,  0,  0,  1,  0,  0,  0,  4,  0,  0,  0,  9, 12,  0,  0,  0,  0, 15,  0, 16,  0,  0,  0,  0,  0 },
   /* w */ {  2,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  0,  0,  8,  0,  9, 10,  0, 12,  0, 13, 14,  0,  0,  0,  0 },
@@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][26] =
   /* z */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }
 };
 
-static const int command_count = 544;
+static const int command_count = 547;
index 187efea232837983f2c8423d29cc411905b4fd00..c5e0bf4495abb1a39bd9bd1eec05f316f850feda 100644 (file)
  * 1. Add an entry in the table below.  Keep it sorted on the shortest
  *    version of the command name that works.  If it doesn't start with a
  *    lower case letter, add it at the end.
- * 2. Add a "case: CMD_xxx" in the big switch in ex_docmd.c.
- * 3. Add an entry in the index for Ex commands at ":help ex-cmd-index".
- * 4. Add documentation in ../doc/xxx.txt.  Add a tag for both the short and
+ * 2. Run "make cmdidxs" to re-generate ex_cmdidxs.h.
+ * 3. Add a "case: CMD_xxx" in the big switch in ex_docmd.c.
+ * 4. Add an entry in the index for Ex commands at ":help ex-cmd-index".
+ * 5. Add documentation in ../doc/xxx.txt.  Add a tag for both the short and
  *    long name of the command.
  */
 
@@ -176,7 +177,7 @@ EX(CMD_bdelete,             "bdelete",      ex_bunload,
                        BANG|RANGE|NOTADR|BUFNAME|COUNT|EXTRA|TRLBAR,
                        ADDR_BUFFERS),
 EX(CMD_behave,         "behave",       ex_behave,
-                       NEEDARG|WORD1|TRLBAR|CMDWIN,
+                       BANG|NEEDARG|WORD1|TRLBAR|CMDWIN,
                        ADDR_LINES),
 EX(CMD_belowright,     "belowright",   ex_wrongmodifier,
                        NEEDARG|EXTRA|NOTRLCOM,
@@ -1498,6 +1499,15 @@ EX(CMD_tjump,            "tjump",        ex_tag,
 EX(CMD_tlast,          "tlast",        ex_tag,
                        BANG|TRLBAR,
                        ADDR_LINES),
+EX(CMD_tlmenu,         "tlmenu",       ex_menu,
+                       RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN,
+                       ADDR_LINES),
+EX(CMD_tlnoremenu,     "tlnoremenu",   ex_menu,
+                       RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN,
+                       ADDR_LINES),
+EX(CMD_tlunmenu,       "tlunmenu",     ex_menu,
+                       RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN,
+                       ADDR_LINES),
 EX(CMD_tmenu,          "tmenu",        ex_menu,
                        RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN,
                        ADDR_LINES),
index 70acfc83d3ffcc6f922a30f7e9c67f6b6610225a..d00ca5689d7eb9b380eb4a96751e6816c30d8078 100644 (file)
@@ -4283,6 +4283,7 @@ set_one_cmd_context(
        case CMD_omenu:     case CMD_onoremenu:     case CMD_ounmenu:
        case CMD_imenu:     case CMD_inoremenu:     case CMD_iunmenu:
        case CMD_cmenu:     case CMD_cnoremenu:     case CMD_cunmenu:
+       case CMD_tlmenu:    case CMD_tlnoremenu:    case CMD_tlunmenu:
        case CMD_tmenu:                             case CMD_tunmenu:
        case CMD_popup:     case CMD_tearoff:       case CMD_emenu:
            return set_context_in_menu_cmd(xp, cmd, arg, forceit);
index d253e72cb57504d563e520132b79297306810636..782235a11c25342f2da21211c4b923055828b5aa 100644 (file)
@@ -58,7 +58,7 @@ static void menu_unescape_name(char_u *p);
 static char_u *menu_translate_tab_and_shift(char_u *arg_start);
 
 /* The character for each menu mode */
-static char_u  menu_mode_chars[] = {'n', 'v', 's', 'o', 'i', 'c', 't'};
+static char *menu_mode_chars[] = {"n", "v", "s", "o", "i", "c", "tl", "t"};
 
 static char_u e_notsubmenu[] = N_("E327: Part of menu-item path is not sub-menu");
 static char_u e_othermode[] = N_("E328: Menu only exists in another mode");
@@ -1196,7 +1196,7 @@ show_menus_recursive(vimmenu_T *menu, int modes, int depth)
                    return;
                for (i = 0; i < depth + 2; i++)
                    MSG_PUTS("  ");
-               msg_putchar(menu_mode_chars[bit]);
+               msg_puts((char_u*)menu_mode_chars[bit]);
                if (menu->noremap[bit] == REMAP_NONE)
                    msg_putchar('*');
                else if (menu->noremap[bit] == REMAP_SCRIPT)
@@ -1645,6 +1645,12 @@ get_menu_cmd_modes(
            modes = MENU_INSERT_MODE;
            break;
        case 't':
+           if (*cmd == 'l')            /* tlmenu, tlunmenu, tlnoremenu */
+           {
+               modes = MENU_TERMINAL_MODE;
+               ++cmd;
+               break;
+           }
            modes = MENU_TIP_MODE;      /* tmenu */
            break;
        case 'c':                       /* cmenu */
@@ -1687,12 +1693,18 @@ popup_mode_name(char_u *name, int idx)
 {
     char_u     *p;
     int                len = (int)STRLEN(name);
+    char       *mode_chars = menu_mode_chars[idx];
+    int                mode_chars_len = (int)strlen(mode_chars);
+    int                i;
 
-    p = vim_strnsave(name, len + 1);
+    p = vim_strnsave(name, len + mode_chars_len);
     if (p != NULL)
     {
-       mch_memmove(p + 6, p + 5, (size_t)(len - 4));
-       p[5] = menu_mode_chars[idx];
+       mch_memmove(p + 5 + mode_chars_len, p + 5, (size_t)(len - 4));
+       for (i = 0; i < mode_chars_len; ++i)
+       {
+           p[5 + i] = menu_mode_chars[idx][i];
+       }
     }
     return p;
 }
@@ -1712,6 +1724,10 @@ get_menu_index(vimmenu_T *menu, int state)
        idx = MENU_INDEX_INSERT;
     else if (state & CMDLINE)
        idx = MENU_INDEX_CMDLINE;
+#ifdef FEAT_TERMINAL
+    else if (term_use_loop())
+       idx = MENU_INDEX_TERMINAL;
+#endif
     else if (VIsual_active)
     {
        if (VIsual_select)
@@ -1872,6 +1888,12 @@ menu_is_tearoff(char_u *name UNUSED)
     static int
 get_menu_mode(void)
 {
+#ifdef FEAT_TERMINAL
+    if (term_use_loop())
+    {
+       return MENU_INDEX_TERMINAL;
+    }
+#endif
     if (VIsual_active)
     {
        if (VIsual_select)
@@ -1910,23 +1932,20 @@ get_menu_mode_flag(void)
 show_popupmenu(void)
 {
     vimmenu_T  *menu;
-    int                mode;
+    int                menu_mode;
+    char*      mode;
+    int                mode_len;
 
-    mode = get_menu_mode();
-    if (mode == MENU_INDEX_INVALID)
+    menu_mode = get_menu_mode();
+    if (menu_mode == MENU_INDEX_INVALID)
        return;
-    mode = menu_mode_chars[mode];
+    mode = menu_mode_chars[menu_mode];
+    mode_len = (int)strlen(mode);
 
-    {
-       char_u      ename[2];
-
-       ename[0] = mode;
-       ename[1] = NUL;
-       apply_autocmds(EVENT_MENUPOPUP, ename, NULL, FALSE, curbuf);
-    }
+    apply_autocmds(EVENT_MENUPOPUP, (char_u*)mode, NULL, FALSE, curbuf);
 
     for (menu = root_menu; menu != NULL; menu = menu->next)
-       if (STRNCMP("PopUp", menu->name, 5) == 0 && menu->name[5] == mode)
+       if (STRNCMP("PopUp", menu->name, 5) == 0 && STRNCMP(menu->name + 5, mode, mode_len) == 0)
            break;
 
     /* Only show a popup when it is defined and has entries */
@@ -2249,82 +2268,86 @@ gui_destroy_tearoffs_recurse(vimmenu_T *menu)
 /*
  * Execute "menu".  Use by ":emenu" and the window toolbar.
  * "eap" is NULL for the window toolbar.
+ * "mode_idx" specifies a MENU_INDEX_ value, use -1 to depend on the current
+ * state.
  */
     void
-execute_menu(exarg_T *eap, vimmenu_T *menu)
+execute_menu(exarg_T *eap, vimmenu_T *menu, int mode_idx)
 {
-    char_u     *mode;
-    int                idx = -1;
+    int                idx = mode_idx;
 
-    /* Use the Insert mode entry when returning to Insert mode. */
-    if (restart_edit
+    if (idx < 0)
+    {
+       /* Use the Insert mode entry when returning to Insert mode. */
+       if (restart_edit
 #ifdef FEAT_EVAL
-           && !current_sctx.sc_sid
+               && !current_sctx.sc_sid
 #endif
-           )
-    {
-       mode = (char_u *)"Insert";
-       idx = MENU_INDEX_INSERT;
-    }
-    else if (VIsual_active)
-    {
-       mode = (char_u *)"Visual";
-       idx = MENU_INDEX_VISUAL;
-    }
-    else if (eap != NULL && eap->addr_count)
-    {
-       pos_T   tpos;
-
-       mode = (char_u *)"Visual";
-       idx = MENU_INDEX_VISUAL;
-
-       /* GEDDES: This is not perfect - but it is a
-        * quick way of detecting whether we are doing this from a
-        * selection - see if the range matches up with the visual
-        * select start and end.  */
-       if ((curbuf->b_visual.vi_start.lnum == eap->line1)
-               && (curbuf->b_visual.vi_end.lnum) == eap->line2)
+               )
        {
-           /* Set it up for visual mode - equivalent to gv.  */
-           VIsual_mode = curbuf->b_visual.vi_mode;
-           tpos = curbuf->b_visual.vi_end;
-           curwin->w_cursor = curbuf->b_visual.vi_start;
-           curwin->w_curswant = curbuf->b_visual.vi_curswant;
+           idx = MENU_INDEX_INSERT;
        }
-       else
+#ifdef FEAT_TERMINAL
+       else if (term_use_loop())
        {
-           /* Set it up for line-wise visual mode */
-           VIsual_mode = 'V';
-           curwin->w_cursor.lnum = eap->line1;
-           curwin->w_cursor.col = 1;
-           tpos.lnum = eap->line2;
-           tpos.col = MAXCOL;
-#ifdef FEAT_VIRTUALEDIT
-           tpos.coladd = 0;
+           idx = MENU_INDEX_TERMINAL;
+       }
 #endif
+       else if (VIsual_active)
+       {
+           idx = MENU_INDEX_VISUAL;
        }
+       else if (eap != NULL && eap->addr_count)
+       {
+           pos_T       tpos;
 
-       /* Activate visual mode */
-       VIsual_active = TRUE;
-       VIsual_reselect = TRUE;
-       check_cursor();
-       VIsual = curwin->w_cursor;
-       curwin->w_cursor = tpos;
+           idx = MENU_INDEX_VISUAL;
 
-       check_cursor();
+           /* GEDDES: This is not perfect - but it is a
+            * quick way of detecting whether we are doing this from a
+            * selection - see if the range matches up with the visual
+            * select start and end.  */
+           if ((curbuf->b_visual.vi_start.lnum == eap->line1)
+                   && (curbuf->b_visual.vi_end.lnum) == eap->line2)
+           {
+               /* Set it up for visual mode - equivalent to gv.  */
+               VIsual_mode = curbuf->b_visual.vi_mode;
+               tpos = curbuf->b_visual.vi_end;
+               curwin->w_cursor = curbuf->b_visual.vi_start;
+               curwin->w_curswant = curbuf->b_visual.vi_curswant;
+           }
+           else
+           {
+               /* Set it up for line-wise visual mode */
+               VIsual_mode = 'V';
+               curwin->w_cursor.lnum = eap->line1;
+               curwin->w_cursor.col = 1;
+               tpos.lnum = eap->line2;
+               tpos.col = MAXCOL;
+#ifdef FEAT_VIRTUALEDIT
+               tpos.coladd = 0;
+#endif
+           }
 
-       /* Adjust the cursor to make sure it is in the correct pos
-        * for exclusive mode */
-       if (*p_sel == 'e' && gchar_cursor() != NUL)
-           ++curwin->w_cursor.col;
+           /* Activate visual mode */
+           VIsual_active = TRUE;
+           VIsual_reselect = TRUE;
+           check_cursor();
+           VIsual = curwin->w_cursor;
+           curwin->w_cursor = tpos;
+
+           check_cursor();
+
+           /* Adjust the cursor to make sure it is in the correct pos
+            * for exclusive mode */
+           if (*p_sel == 'e' && gchar_cursor() != NUL)
+               ++curwin->w_cursor.col;
+       }
     }
 
     /* For the WinBar menu always use the Normal mode menu. */
     if (idx == -1 || eap == NULL)
-    {
-       mode = (char_u *)"Normal";
        idx = MENU_INDEX_NORMAL;
-    }
 
     if (idx != MENU_INDEX_INVALID && menu->strings[idx] != NULL)
     {
@@ -2351,7 +2374,35 @@ execute_menu(exarg_T *eap, vimmenu_T *menu)
                                                     TRUE, menu->silent[idx]);
     }
     else if (eap != NULL)
+    {
+       char_u  *mode;
+
+       switch (idx)
+       {
+           case MENU_INDEX_VISUAL:
+               mode = (char_u *)"Visual";
+               break;
+           case MENU_INDEX_SELECT:
+               mode = (char_u *)"Select";
+               break;
+           case MENU_INDEX_OP_PENDING:
+               mode = (char_u *)"Op-pending";
+               break;
+           case MENU_INDEX_TERMINAL:
+               mode = (char_u *)"Terminal";
+               break;
+           case MENU_INDEX_INSERT:
+               mode = (char_u *)"Insert";
+               break;
+           case MENU_INDEX_CMDLINE:
+               mode = (char_u *)"Cmdline";
+               break;
+           // case MENU_INDEX_TIP: cannot happen
+           default:
+               mode = (char_u *)"Normal";
+       }
        EMSG2(_("E335: Menu not defined for %s mode"), mode);
+    }
 }
 
 /*
@@ -2364,9 +2415,29 @@ ex_emenu(exarg_T *eap)
     vimmenu_T  *menu;
     char_u     *name;
     char_u     *saved_name;
+    char_u     *arg = eap->arg;
     char_u     *p;
+    int                gave_emsg = FALSE;
+    int                mode_idx = -1;
+
+    if (arg[0] && VIM_ISWHITE(arg[1]))
+    {
+       switch (arg[0])
+       {
+           case 'n': mode_idx = MENU_INDEX_NORMAL; break;
+           case 'v': mode_idx = MENU_INDEX_VISUAL; break;
+           case 's': mode_idx = MENU_INDEX_SELECT; break;
+           case 'o': mode_idx = MENU_INDEX_OP_PENDING; break;
+           case 't': mode_idx = MENU_INDEX_TERMINAL; break;
+           case 'i': mode_idx = MENU_INDEX_INSERT; break;
+           case 'c': mode_idx = MENU_INDEX_CMDLINE; break;
+           default: EMSG2(_(e_invarg2), arg);
+                    return;
+       }
+       arg = skipwhite(arg + 2);
+    }
 
-    saved_name = vim_strsave(eap->arg);
+    saved_name = vim_strsave(arg);
     if (saved_name == NULL)
        return;
 
@@ -2384,6 +2455,7 @@ ex_emenu(exarg_T *eap)
                if (*p == NUL && menu->children != NULL)
                {
                    EMSG(_("E333: Menu path must lead to a menu item"));
+                   gave_emsg = TRUE;
                    menu = NULL;
                }
                else if (*p != NUL && menu->children == NULL)
@@ -2403,12 +2475,13 @@ ex_emenu(exarg_T *eap)
     vim_free(saved_name);
     if (menu == NULL)
     {
-       EMSG2(_("E334: Menu not found: %s"), eap->arg);
+       if (!gave_emsg)
+           EMSG2(_("E334: Menu not found: %s"), arg);
        return;
     }
 
-    /* Found the menu, so execute. */
-    execute_menu(eap, menu);
+    // Found the menu, so execute.
+    execute_menu(eap, menu, mode_idx);
 }
 
 /*
@@ -2445,7 +2518,7 @@ winbar_click(win_T *wp, int col)
                check_cursor();
            }
 
-           execute_menu(NULL, item->wb_menu);
+           execute_menu(NULL, item->wb_menu, -1);
 
            if (save_curwin != NULL)
            {
index 0f920dc69ea4a5354af6004365f2fce897026c2f..c481d4be738879896388e611a59862cd2a60782c 100644 (file)
@@ -1176,7 +1176,7 @@ pum_execute_menu(vimmenu_T *menu, int mode)
        if ((mp->modes & mp->enabled & mode) && idx++ == pum_selected)
        {
            vim_memset(&ea, 0, sizeof(ea));
-           execute_menu(&ea, mp);
+           execute_menu(&ea, mp, -1);
            break;
        }
 }
index 63f8d11bddb1bd3ba7998ea92ac13c7057917e1e..411c040b482e46532db291ecc948b50d47be8746 100644 (file)
@@ -19,7 +19,7 @@ void gui_create_initial_menus(vimmenu_T *menu);
 void gui_update_menus(int modes);
 int gui_is_menu_shortcut(int key);
 void gui_mch_toggle_tearoffs(int enable);
-void execute_menu(exarg_T *eap, vimmenu_T *menu);
+void execute_menu(exarg_T *eap, vimmenu_T *menu, int mode_idx);
 void ex_emenu(exarg_T *eap);
 void winbar_click(win_T *wp, int col);
 vimmenu_T *gui_find_menu(char_u *path_name);
index 560ce42b41a4a631455451754fbf9edec2ca0876..a0c06b5f25f8daf39e4913f280b3d439000ff87f 100644 (file)
@@ -3101,8 +3101,9 @@ typedef struct cursor_entry
 #define MENU_INDEX_OP_PENDING  3
 #define MENU_INDEX_INSERT      4
 #define MENU_INDEX_CMDLINE     5
-#define MENU_INDEX_TIP         6
-#define MENU_MODES             7
+#define MENU_INDEX_TERMINAL    6
+#define MENU_INDEX_TIP         7
+#define MENU_MODES             8
 
 /* Menu modes */
 #define MENU_NORMAL_MODE       (1 << MENU_INDEX_NORMAL)
@@ -3111,6 +3112,7 @@ typedef struct cursor_entry
 #define MENU_OP_PENDING_MODE   (1 << MENU_INDEX_OP_PENDING)
 #define MENU_INSERT_MODE       (1 << MENU_INDEX_INSERT)
 #define MENU_CMDLINE_MODE      (1 << MENU_INDEX_CMDLINE)
+#define MENU_TERMINAL_MODE     (1 << MENU_INDEX_TERMINAL)
 #define MENU_TIP_MODE          (1 << MENU_INDEX_TIP)
 #define MENU_ALL_MODES         ((1 << MENU_INDEX_TIP) - 1)
 /*note MENU_INDEX_TIP is not a 'real' mode*/
index 055d944b1536395a2e7a80869e46dcd58d408259..6462d5196c762acc523c9cf76b959426955fd0cf 100644 (file)
@@ -30,3 +30,37 @@ func Test_translate_menu()
 
   source $VIMRUNTIME/delmenu.vim
 endfunc
+
+func Test_menu_commands()
+  nmenu 2 Test.FooBar :let g:did_menu = 'normal'<CR>
+  vmenu 2 Test.FooBar :let g:did_menu = 'visual'<CR>
+  smenu 2 Test.FooBar :let g:did_menu = 'select'<CR>
+  omenu 2 Test.FooBar :let g:did_menu = 'op-pending'<CR>
+  tlmenu 2 Test.FooBar :let g:did_menu = 'terminal'<CR>
+  imenu 2 Test.FooBar :let g:did_menu = 'insert'<CR>
+  cmenu 2 Test.FooBar :let g:did_menu = 'cmdline'<CR>
+  emenu n Test.FooBar
+  call assert_equal('normal', g:did_menu)
+  emenu v Test.FooBar
+  call assert_equal('visual', g:did_menu)
+  emenu s Test.FooBar
+  call assert_equal('select', g:did_menu)
+  emenu o Test.FooBar
+  call assert_equal('op-pending', g:did_menu)
+  emenu t Test.FooBar
+  call assert_equal('terminal', g:did_menu)
+  emenu i Test.FooBar
+  call assert_equal('insert', g:did_menu)
+  emenu c Test.FooBar
+  call assert_equal('cmdline', g:did_menu)
+
+  aunmenu Test.FooBar
+  tlunmenu Test.FooBar
+  call assert_fails('emenu n Test.FooBar', 'E334:')
+
+  nmenu 2 Test.FooBar.Child :let g:did_menu = 'foobar'<CR>
+  call assert_fails('emenu n Test.FooBar', 'E333:')
+  nunmenu Test.FooBar.Child
+
+  unlet g:did_menu
+endfun
index 726f5eeae213614ceacd28d010e693525029cf74..4189eb04aadbab76863146a55ba6acd98abefe3e 100644 (file)
@@ -792,6 +792,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    487,
 /**/
     486,
 /**/