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:
@@ -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 ''
|
||||||
|
31
src/map.c
31
src/map.c
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
@@ -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')
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user