summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-09-03 22:08:33 +0200
committerBram Moolenaar <Bram@vim.org>2019-09-03 22:08:33 +0200
commit581ba39aefe837298a9943b04a1dab13a7ec6772 (patch)
tree156f0c8dd74bd6e76c850239f753cbaa17c12924 /src
parent27da7de7c547dbf983ed7dd901ea59be4e7c9ab2 (diff)
downloadvim-git-581ba39aefe837298a9943b04a1dab13a7ec6772.tar.gz
patch 8.1.1969: popup window filter is used in all modesv8.1.1969
Problem: Popup window filter is used in all modes. Solution: Add the "filtermode" property.
Diffstat (limited to 'src')
-rw-r--r--src/map.c31
-rw-r--r--src/popupwin.c15
-rw-r--r--src/proto/map.pro1
-rw-r--r--src/structs.h1
-rw-r--r--src/testdir/test_popupwin.vim66
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h1
7 files changed, 104 insertions, 13 deletions
diff --git a/src/map.c b/src/map.c
index ac223a9c1..df8cbedb1 100644
--- 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;
diff --git a/src/popupwin.c b/src/popupwin.c
index abf40e8c0..226232dd0 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -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;
diff --git a/src/proto/map.pro b/src/proto/map.pro
index 05d66fb87..cf1b31a4c 100644
--- a/src/proto/map.pro
+++ b/src/proto/map.pro
@@ -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);
diff --git a/src/structs.h b/src/structs.h
index 35a22b102..e599550a1 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -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
diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim
index 8fd4da157..36cf306a7 100644
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -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')
diff --git a/src/version.c b/src/version.c
index 5dbdc9fa4..655b68a99 100644
--- a/src/version.c
+++ b/src/version.c
@@ -762,6 +762,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1969,
+/**/
1968,
/**/
1967,
diff --git a/src/vim.h b/src/vim.h
index e9d586b40..29441c844 100644
--- 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)