0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.1.1969: popup window filter is used in all modes

Problem:    Popup window filter is used in all modes.
Solution:   Add the "filtermode" property.
This commit is contained in:
Bram Moolenaar
2019-09-03 22:08:33 +02:00
parent 27da7de7c5
commit 581ba39aef
8 changed files with 132 additions and 22 deletions

View 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 VIM REFERENCE MANUAL by Bram Moolenaar
@@ -442,7 +442,7 @@ popup_notification({what}, {options}) *popup_notification()*
< The PopupNotification highlight group is used instead of < The PopupNotification highlight group is used instead of
WarningMsg if it is defined. 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. automatically, the user has to click in it.
The position will be adjusted to avoid overlap with other The position will be adjusted to avoid overlap with other
@@ -486,7 +486,7 @@ popup_setoptions({id}, {options}) *popup_setoptions()*
"tabpage" cannot be changed. "tabpage" cannot be changed.
popup_settext({id}, {text}) *popup_settext()* 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 same as supplied to |popup_create()|, except that a buffer
number is not allowed. number is not allowed.
Does not change the window size or position, other than caused 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. start and end as padding.
wrap TRUE to make the lines wrap (default TRUE). wrap TRUE to make the lines wrap (default TRUE).
drag TRUE to allow the popup to be dragged with the mouse 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 popup does not have a border. As soon as dragging
starts and "pos" is "center" it is changed to starts and "pos" is "center" it is changed to
"topleft". "topleft".
resize TRUE to allow the popup to be resized with the mouse resize TRUE to allow the popup to be resized with the mouse
by grabbing at at the bottom right cornder. Has no by grabbing at the bottom right corner. Has no effect
effect if the popup does not have a border. if the popup does not have a border.
close When "button" an X is displayed in the top-right, on close When "button" an X is displayed in the top-right, on
top of any border, padding or text. When clicked on top of any border, padding or text. When clicked on
the X the popup will close. Any callback is invoked 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 mapping Allow for key mapping. When FALSE and the popup is
visible and has a filter callback key mapping is visible and has a filter callback key mapping is
disabled. Default value is TRUE. 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. callback A callback that is called when the popup closes, e.g.
when using |popup_filter_menu()|, see |popup-callback|. when using |popup_filter_menu()|, see |popup-callback|.
@@ -784,13 +796,20 @@ key as a string, e.g.: >
endif endif
return 0 return 0
endfunc 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 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 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 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()|. 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) x close the popup (see note below)
cursor keys select another entry cursor keys select another entry
Tab accept current suggestion Tab accept current suggestion
@@ -941,7 +960,7 @@ this example simulated with a timer callback: >
call popup_close(s:winid) call popup_close(s:winid)
let s:winid = 0 let s:winid = 0
endif 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 let s:balloonText = v:beval_text
call timer_start(100, 'ShowPopup') call timer_start(100, 'ShowPopup')
return '' return ''

View File

@@ -897,20 +897,10 @@ map_clear_int(
} }
#if defined(FEAT_EVAL) || defined(PROTO) #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 int
map_to_exists(char_u *str, char_u *modechars, int abbr) mode_str2flags(char_u *modechars)
{ {
int mode = 0; 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) if (vim_strchr(modechars, 'n') != NULL)
mode |= NORMAL; mode |= NORMAL;
@@ -929,7 +919,24 @@ map_to_exists(char_u *str, char_u *modechars, int abbr)
if (vim_strchr(modechars, 'c') != NULL) if (vim_strchr(modechars, 'c') != NULL)
mode |= CMDLINE; 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); vim_free(buf);
return retval; return retval;

View File

@@ -845,6 +845,15 @@ apply_general_options(win_T *wp, dict_T *dict)
wp->w_popup_flags &= ~POPF_MAPPING; 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); di = dict_find(dict, (char_u *)"callback", -1);
if (di != NULL) 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_border_char[i] = 0;
wp->w_want_scrollbar = 1; wp->w_want_scrollbar = 1;
wp->w_popup_fixed = 0; wp->w_popup_fixed = 0;
wp->w_filter_mode = MODE_ALL;
if (d != NULL) if (d != NULL)
// Deal with options. // Deal with options.
@@ -2768,6 +2778,7 @@ popup_do_filter(int c)
int res = FALSE; int res = FALSE;
win_T *wp; win_T *wp;
int save_KeyTyped = KeyTyped; int save_KeyTyped = KeyTyped;
int state;
if (recursive) if (recursive)
return FALSE; return FALSE;
@@ -2785,8 +2796,10 @@ popup_do_filter(int c)
res = TRUE; res = TRUE;
} }
state = get_real_state();
while (!res && (wp = find_next_popup(FALSE)) != NULL) 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); res = invoke_popup_filter(wp, c);
recursive = FALSE; recursive = FALSE;

View File

@@ -4,6 +4,7 @@ mapblock_T *get_buf_maphash_list(int state, int c);
int is_maphash_valid(void); int is_maphash_valid(void);
int do_map(int maptype, char_u *arg, int mode, int abbrev); 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); 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(char_u *str, char_u *modechars, int abbr);
int map_to_exists_mode(char_u *rhs, int mode, 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); 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);

View File

@@ -3054,6 +3054,7 @@ struct window_S
// computed // computed
callback_T w_close_cb; // popup close callback callback_T w_close_cb; // popup close callback
callback_T w_filter_cb; // popup filter 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 win_T *w_popup_curwin; // close popup if curwin differs
linenr_T w_popup_lnum; // close popup if cursor not on this line linenr_T w_popup_lnum; // close popup if cursor not on this line

View File

@@ -1892,6 +1892,72 @@ func Test_popupwin_garbage_collect()
delfunc MyPopupFilter delfunc MyPopupFilter
endfunc 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() func Test_popupwin_with_buffer()
call writefile(['some text', 'in a buffer'], 'XsomeFile') call writefile(['some text', 'in a buffer'], 'XsomeFile')
let buf = bufadd('XsomeFile') let buf = bufadd('XsomeFile')

View File

@@ -761,6 +761,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1969,
/**/ /**/
1968, 1968,
/**/ /**/

View File

@@ -680,6 +680,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define CONFIRM 0x800 // ":confirm" prompt #define CONFIRM 0x800 // ":confirm" prompt
#define SELECTMODE 0x1000 // Select mode, only for mappings #define SELECTMODE 0x1000 // Select mode, only for mappings
#define TERMINAL 0x2000 // Terminal mode #define TERMINAL 0x2000 // Terminal mode
#define MODE_ALL 0xffff
// all mode bits used for mapping // all mode bits used for mapping
#define MAP_ALL_MODES (0x3f | SELECTMODE | TERMINAL) #define MAP_ALL_MODES (0x3f | SELECTMODE | TERMINAL)