forked from aniani/vim
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:
@@ -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 ''
|
||||
|
31
src/map.c
31
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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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')
|
||||
|
@@ -761,6 +761,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1969,
|
||||
/**/
|
||||
1968,
|
||||
/**/
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user