]> granicus.if.org Git - vim/commitdiff
patch 8.1.1969: popup window filter is used in all modes v8.1.1969
authorBram Moolenaar <Bram@vim.org>
Tue, 3 Sep 2019 20:08:33 +0000 (22:08 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 3 Sep 2019 20:08:33 +0000 (22:08 +0200)
Problem:    Popup window filter is used in all modes.
Solution:   Add the "filtermode" property.

runtime/doc/popup.txt
src/map.c
src/popupwin.c
src/proto/map.pro
src/structs.h
src/testdir/test_popupwin.vim
src/version.c
src/vim.h

index 0a464103c8c2f764de8d5ae1fac171e61a8dcf08..de26bf26860f9c1fa23b864714a23e43a0b0fd69 100644 (file)
@@ -1,4 +1,4 @@
-*popup.txt*  For Vim version 8.1.  Last change: 2019 Aug 31
+*popup.txt*  For Vim version 8.1.  Last change: 2019 Sep 03
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -442,7 +442,7 @@ popup_notification({what}, {options})                        *popup_notification()*
 <              The PopupNotification highlight group is used instead of
                WarningMsg if it is defined.
 
-               Without the |+timers| feature the poup will not disappear
+               Without the |+timers| feature the popup will not disappear
                automatically, the user has to click in it.
 
                The position will be adjusted to avoid overlap with other
@@ -486,7 +486,7 @@ popup_setoptions({id}, {options})                   *popup_setoptions()*
                "tabpage" cannot be changed.
 
 popup_settext({id}, {text})                            *popup_settext()*
-               Set the text of the buffer in poup win {id}. {text} is the
+               Set the text of the buffer in popup win {id}. {text} is the
                same as supplied to |popup_create()|, except that a buffer
                number is not allowed.
                Does not change the window size or position, other than caused
@@ -583,13 +583,13 @@ The second argument of |popup_create()| is a dictionary with options:
                        start and end as padding.
        wrap            TRUE to make the lines wrap (default TRUE).
        drag            TRUE to allow the popup to be dragged with the mouse
-                       by grabbing at at the border.  Has no effect if the
+                       by grabbing at the border.  Has no effect if the
                        popup does not have a border. As soon as dragging
                        starts and "pos" is "center" it is changed to
                        "topleft".
        resize          TRUE to allow the popup to be resized with the mouse
-                       by grabbing at at the bottom right cornder.  Has no
-                       effect if the popup does not have a border.
+                       by grabbing at the bottom right corner.  Has no effect
+                       if the popup does not have a border.
        close           When "button" an X is displayed in the top-right, on
                        top of any border, padding or text.  When clicked on
                        the X the popup will close.  Any callback is invoked
@@ -662,6 +662,18 @@ The second argument of |popup_create()| is a dictionary with options:
        mapping         Allow for key mapping.  When FALSE and the popup is
                        visible and has a filter callback key mapping is
                        disabled.  Default value is TRUE.
+       filtermode      In which modes the filter is used (same flags as with
+                       |hasmapto()| plus "a"):
+                               n       Normal mode
+                               v       Visual and Select mode
+                               x       Visual mode
+                               s       Select mode
+                               o       Operator-pending mode
+                               i       Insert mode
+                               l       Language-Argument ("r", "f", "t", etc.)
+                               c       Command-line mode
+                               a       all modes
+                       The default value is "a".
        callback        A callback that is called when the popup closes, e.g.
                        when using |popup_filter_menu()|, see |popup-callback|.
 
@@ -784,13 +796,20 @@ key as a string, e.g.: >
          endif
          return 0
        endfunc
-<                                                      *popup-mapping*
+<                                                      *popup-filter-mode*
+The "filtermode" property can be used to specify in what mode the filter is
+invoked.  The default is "a": all modes.  When using "nvi" Command-line mode
+is not included, so that any command typed on the command line is not
+filtered.  However, to get to Command-line mode the filter must not consume
+":".  Just like it must not consume "v" to allow for entering Visual mode.
+
+                                                       *popup-mapping*
 Normally the key is what results after any mapping, since the keys pass on as
 normal input if the filter does not use it.  If the filter consumes all the
 keys, set the "mapping" property to zero so that mappings do not get in the
 way.  This is default for |popup_menu()| and |popup_dialog()|.
 
-Some common key actions:
+Some recommended key actions:
        x               close the popup (see note below)
        cursor keys     select another entry
        Tab             accept current suggestion
@@ -941,7 +960,7 @@ this example simulated with a timer callback: >
            call popup_close(s:winid)
            let s:winid = 0
          endif
-         " simulate an asynchronous loopup for the text to display
+         " simulate an asynchronous lookup for the text to display
          let s:balloonText = v:beval_text
          call timer_start(100, 'ShowPopup')
          return ''
index ac223a9c1bdcd85c97c8b242108e19c939cfa4b0..df8cbedb1f2cef260dbb09931f2a28c9834e88c3 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -897,20 +897,10 @@ map_clear_int(
 }
 
 #if defined(FEAT_EVAL) || defined(PROTO)
-/*
- * Return TRUE if a map exists that has "str" in the rhs for mode "modechars".
- * Recognize termcap codes in "str".
- * Also checks mappings local to the current buffer.
- */
     int
-map_to_exists(char_u *str, char_u *modechars, int abbr)
+mode_str2flags(char_u *modechars)
 {
     int                mode = 0;
-    char_u     *rhs;
-    char_u     *buf;
-    int                retval;
-
-    rhs = replace_termcodes(str, &buf, FALSE, TRUE, FALSE);
 
     if (vim_strchr(modechars, 'n') != NULL)
        mode |= NORMAL;
@@ -929,7 +919,24 @@ map_to_exists(char_u *str, char_u *modechars, int abbr)
     if (vim_strchr(modechars, 'c') != NULL)
        mode |= CMDLINE;
 
-    retval = map_to_exists_mode(rhs, mode, abbr);
+    return mode;
+}
+
+/*
+ * Return TRUE if a map exists that has "str" in the rhs for mode "modechars".
+ * Recognize termcap codes in "str".
+ * Also checks mappings local to the current buffer.
+ */
+    int
+map_to_exists(char_u *str, char_u *modechars, int abbr)
+{
+    char_u     *rhs;
+    char_u     *buf;
+    int                retval;
+
+    rhs = replace_termcodes(str, &buf, FALSE, TRUE, FALSE);
+
+    retval = map_to_exists_mode(rhs, mode_str2flags(modechars), abbr);
     vim_free(buf);
 
     return retval;
index abf40e8c066c1e2263acf7344db47211e2e7dc60..226232dd0ec18c005bb59d81a6df6ce2c5082e1c 100644 (file)
@@ -845,6 +845,15 @@ apply_general_options(win_T *wp, dict_T *dict)
            wp->w_popup_flags &= ~POPF_MAPPING;
     }
 
+    str = dict_get_string(dict, (char_u *)"filtermode", FALSE);
+    if (str != NULL)
+    {
+       if (STRCMP(str, "a") == 0)
+           wp->w_filter_mode = MODE_ALL;
+       else
+           wp->w_filter_mode = mode_str2flags(str);
+    }
+
     di = dict_find(dict, (char_u *)"callback", -1);
     if (di != NULL)
     {
@@ -1851,6 +1860,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
        wp->w_border_char[i] = 0;
     wp->w_want_scrollbar = 1;
     wp->w_popup_fixed = 0;
+    wp->w_filter_mode = MODE_ALL;
 
     if (d != NULL)
        // Deal with options.
@@ -2768,6 +2778,7 @@ popup_do_filter(int c)
     int                res = FALSE;
     win_T      *wp;
     int                save_KeyTyped = KeyTyped;
+    int                state;
 
     if (recursive)
        return FALSE;
@@ -2785,8 +2796,10 @@ popup_do_filter(int c)
            res = TRUE;
     }
 
+    state = get_real_state();
     while (!res && (wp = find_next_popup(FALSE)) != NULL)
-       if (wp->w_filter_cb.cb_name != NULL)
+       if (wp->w_filter_cb.cb_name != NULL
+               && (wp->w_filter_mode & state) != 0)
            res = invoke_popup_filter(wp, c);
 
     recursive = FALSE;
index 05d66fb876531a0b505e63b0eed6caa1c9e2703d..cf1b31a4cc1d658ac8a612e2ef36602120330489 100644 (file)
@@ -4,6 +4,7 @@ mapblock_T *get_buf_maphash_list(int state, int c);
 int is_maphash_valid(void);
 int do_map(int maptype, char_u *arg, int mode, int abbrev);
 void map_clear_int(buf_T *buf, int mode, int local, int abbr);
+int mode_str2flags(char_u *modechars);
 int map_to_exists(char_u *str, char_u *modechars, int abbr);
 int map_to_exists_mode(char_u *rhs, int mode, int abbr);
 char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg, int forceit, int isabbrev, int isunmap, cmdidx_T cmdidx);
index 35a22b10218cefaca047a9e91494d0283af67402..e599550a126f7ef317271fb1880563c19bb57eeb 100644 (file)
@@ -3054,6 +3054,7 @@ struct window_S
                                      // computed
     callback_T w_close_cb;         // popup close callback
     callback_T w_filter_cb;        // popup filter callback
+    int                w_filter_mode;      // mode when filter callback is used
 
     win_T      *w_popup_curwin;    // close popup if curwin differs
     linenr_T   w_popup_lnum;       // close popup if cursor not on this line
index 8fd4da157299d4c037128492fff69d23d6f8a4a6..36cf306a7118faf8f5564534d627d37311da74e4 100644 (file)
@@ -1892,6 +1892,72 @@ func Test_popupwin_garbage_collect()
   delfunc MyPopupFilter
 endfunc
 
+func Test_popupwin_filter_mode()
+  func MyPopupFilter(winid, c)
+    let s:typed = a:c
+    if a:c == ':' || a:c == "\r" || a:c == 'v'
+      " can start cmdline mode, get out, and start/stop Visual mode
+      return 0
+    endif
+    return 1
+  endfunc
+
+  " Normal, Visual and Insert mode
+  let winid = popup_create('something', #{filter: 'MyPopupFilter', filtermode: 'nvi'})
+  redraw
+  call feedkeys('x', 'xt')
+  call assert_equal('x', s:typed)
+
+  call feedkeys(":let g:foo = 'foo'\<CR>", 'xt')
+  call assert_equal(':', s:typed)
+  call assert_equal('foo', g:foo)
+
+  let @x = 'something'
+  call feedkeys('v$"xy', 'xt')
+  call assert_equal('y', s:typed)
+  call assert_equal('something', @x)  " yank command is filtered out
+  call feedkeys('v', 'xt')  " end Visual mode
+
+  call popup_close(winid)
+
+  " only Normal mode
+  let winid = popup_create('something', #{filter: 'MyPopupFilter', filtermode: 'n'})
+  redraw
+  call feedkeys('x', 'xt')
+  call assert_equal('x', s:typed)
+
+  call feedkeys(":let g:foo = 'foo'\<CR>", 'xt')
+  call assert_equal(':', s:typed)
+  call assert_equal('foo', g:foo)
+
+  let @x = 'something'
+  call feedkeys('v$"xy', 'xt')
+  call assert_equal('v', s:typed)
+  call assert_notequal('something', @x)
+
+  call popup_close(winid)
+
+  " default: all modes
+  let winid = popup_create('something', #{filter: 'MyPopupFilter'})
+  redraw
+  call feedkeys('x', 'xt')
+  call assert_equal('x', s:typed)
+
+  let g:foo = 'bar'
+  call feedkeys(":let g:foo = 'foo'\<CR>", 'xt')
+  call assert_equal("\r", s:typed)
+  call assert_equal('bar', g:foo)
+
+  let @x = 'something'
+  call feedkeys('v$"xy', 'xt')
+  call assert_equal('y', s:typed)
+  call assert_equal('something', @x)  " yank command is filtered out
+  call feedkeys('v', 'xt')  " end Visual mode
+
+  call popup_close(winid)
+  delfunc MyPopupFilter
+endfunc
+
 func Test_popupwin_with_buffer()
   call writefile(['some text', 'in a buffer'], 'XsomeFile')
   let buf = bufadd('XsomeFile')
index 5dbdc9fa4e150e8ab31aad861539eac7a72fda34..655b68a99e24e646d806bc30c486772dda882870 100644 (file)
@@ -761,6 +761,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1969,
 /**/
     1968,
 /**/
index e9d586b40ebcf79628ee9f11094a52f2e223ceca..29441c8445bb2ed64e9f14b1d632e5ea216ccebc 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -680,6 +680,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
 #define CONFIRM                0x800   // ":confirm" prompt
 #define SELECTMODE     0x1000  // Select mode, only for mappings
 #define TERMINAL        0x2000  // Terminal mode
+#define MODE_ALL       0xffff
 
 // all mode bits used for mapping
 #define MAP_ALL_MODES  (0x3f | SELECTMODE | TERMINAL)