Skip to content

Commit 581ba39

Browse files
committed
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.
1 parent 27da7de commit 581ba39

8 files changed

Lines changed: 132 additions & 22 deletions

File tree

runtime/doc/popup.txt

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*popup.txt* For Vim version 8.1. Last change: 2019 Aug 31
1+
*popup.txt* For Vim version 8.1. Last change: 2019 Sep 03
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -442,7 +442,7 @@ popup_notification({what}, {options}) *popup_notification()*
442442
< The PopupNotification highlight group is used instead of
443443
WarningMsg if it is defined.
444444

445-
Without the |+timers| feature the poup will not disappear
445+
Without the |+timers| feature the popup will not disappear
446446
automatically, the user has to click in it.
447447

448448
The position will be adjusted to avoid overlap with other
@@ -486,7 +486,7 @@ popup_setoptions({id}, {options}) *popup_setoptions()*
486486
"tabpage" cannot be changed.
487487

488488
popup_settext({id}, {text}) *popup_settext()*
489-
Set the text of the buffer in poup win {id}. {text} is the
489+
Set the text of the buffer in popup win {id}. {text} is the
490490
same as supplied to |popup_create()|, except that a buffer
491491
number is not allowed.
492492
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:
583583
start and end as padding.
584584
wrap TRUE to make the lines wrap (default TRUE).
585585
drag TRUE to allow the popup to be dragged with the mouse
586-
by grabbing at at the border. Has no effect if the
586+
by grabbing at the border. Has no effect if the
587587
popup does not have a border. As soon as dragging
588588
starts and "pos" is "center" it is changed to
589589
"topleft".
590590
resize TRUE to allow the popup to be resized with the mouse
591-
by grabbing at at the bottom right cornder. Has no
592-
effect if the popup does not have a border.
591+
by grabbing at the bottom right corner. Has no effect
592+
if the popup does not have a border.
593593
close When "button" an X is displayed in the top-right, on
594594
top of any border, padding or text. When clicked on
595595
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:
662662
mapping Allow for key mapping. When FALSE and the popup is
663663
visible and has a filter callback key mapping is
664664
disabled. Default value is TRUE.
665+
filtermode In which modes the filter is used (same flags as with
666+
|hasmapto()| plus "a"):
667+
n Normal mode
668+
v Visual and Select mode
669+
x Visual mode
670+
s Select mode
671+
o Operator-pending mode
672+
i Insert mode
673+
l Language-Argument ("r", "f", "t", etc.)
674+
c Command-line mode
675+
a all modes
676+
The default value is "a".
665677
callback A callback that is called when the popup closes, e.g.
666678
when using |popup_filter_menu()|, see |popup-callback|.
667679

@@ -784,13 +796,20 @@ key as a string, e.g.: >
784796
endif
785797
return 0
786798
endfunc
787-
< *popup-mapping*
799+
< *popup-filter-mode*
800+
The "filtermode" property can be used to specify in what mode the filter is
801+
invoked. The default is "a": all modes. When using "nvi" Command-line mode
802+
is not included, so that any command typed on the command line is not
803+
filtered. However, to get to Command-line mode the filter must not consume
804+
":". Just like it must not consume "v" to allow for entering Visual mode.
805+
806+
*popup-mapping*
788807
Normally the key is what results after any mapping, since the keys pass on as
789808
normal input if the filter does not use it. If the filter consumes all the
790809
keys, set the "mapping" property to zero so that mappings do not get in the
791810
way. This is default for |popup_menu()| and |popup_dialog()|.
792811

793-
Some common key actions:
812+
Some recommended key actions:
794813
x close the popup (see note below)
795814
cursor keys select another entry
796815
Tab accept current suggestion
@@ -941,7 +960,7 @@ this example simulated with a timer callback: >
941960
call popup_close(s:winid)
942961
let s:winid = 0
943962
endif
944-
" simulate an asynchronous loopup for the text to display
963+
" simulate an asynchronous lookup for the text to display
945964
let s:balloonText = v:beval_text
946965
call timer_start(100, 'ShowPopup')
947966
return ''

src/map.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -897,20 +897,10 @@ map_clear_int(
897897
}
898898

899899
#if defined(FEAT_EVAL) || defined(PROTO)
900-
/*
901-
* Return TRUE if a map exists that has "str" in the rhs for mode "modechars".
902-
* Recognize termcap codes in "str".
903-
* Also checks mappings local to the current buffer.
904-
*/
905900
int
906-
map_to_exists(char_u *str, char_u *modechars, int abbr)
901+
mode_str2flags(char_u *modechars)
907902
{
908903
int mode = 0;
909-
char_u *rhs;
910-
char_u *buf;
911-
int retval;
912-
913-
rhs = replace_termcodes(str, &buf, FALSE, TRUE, FALSE);
914904

915905
if (vim_strchr(modechars, 'n') != NULL)
916906
mode |= NORMAL;
@@ -929,7 +919,24 @@ map_to_exists(char_u *str, char_u *modechars, int abbr)
929919
if (vim_strchr(modechars, 'c') != NULL)
930920
mode |= CMDLINE;
931921

932-
retval = map_to_exists_mode(rhs, mode, abbr);
922+
return mode;
923+
}
924+
925+
/*
926+
* Return TRUE if a map exists that has "str" in the rhs for mode "modechars".
927+
* Recognize termcap codes in "str".
928+
* Also checks mappings local to the current buffer.
929+
*/
930+
int
931+
map_to_exists(char_u *str, char_u *modechars, int abbr)
932+
{
933+
char_u *rhs;
934+
char_u *buf;
935+
int retval;
936+
937+
rhs = replace_termcodes(str, &buf, FALSE, TRUE, FALSE);
938+
939+
retval = map_to_exists_mode(rhs, mode_str2flags(modechars), abbr);
933940
vim_free(buf);
934941

935942
return retval;

src/popupwin.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,15 @@ apply_general_options(win_T *wp, dict_T *dict)
845845
wp->w_popup_flags &= ~POPF_MAPPING;
846846
}
847847

848+
str = dict_get_string(dict, (char_u *)"filtermode", FALSE);
849+
if (str != NULL)
850+
{
851+
if (STRCMP(str, "a") == 0)
852+
wp->w_filter_mode = MODE_ALL;
853+
else
854+
wp->w_filter_mode = mode_str2flags(str);
855+
}
856+
848857
di = dict_find(dict, (char_u *)"callback", -1);
849858
if (di != NULL)
850859
{
@@ -1851,6 +1860,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
18511860
wp->w_border_char[i] = 0;
18521861
wp->w_want_scrollbar = 1;
18531862
wp->w_popup_fixed = 0;
1863+
wp->w_filter_mode = MODE_ALL;
18541864

18551865
if (d != NULL)
18561866
// Deal with options.
@@ -2768,6 +2778,7 @@ popup_do_filter(int c)
27682778
int res = FALSE;
27692779
win_T *wp;
27702780
int save_KeyTyped = KeyTyped;
2781+
int state;
27712782

27722783
if (recursive)
27732784
return FALSE;
@@ -2785,8 +2796,10 @@ popup_do_filter(int c)
27852796
res = TRUE;
27862797
}
27872798

2799+
state = get_real_state();
27882800
while (!res && (wp = find_next_popup(FALSE)) != NULL)
2789-
if (wp->w_filter_cb.cb_name != NULL)
2801+
if (wp->w_filter_cb.cb_name != NULL
2802+
&& (wp->w_filter_mode & state) != 0)
27902803
res = invoke_popup_filter(wp, c);
27912804

27922805
recursive = FALSE;

src/proto/map.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mapblock_T *get_buf_maphash_list(int state, int c);
44
int is_maphash_valid(void);
55
int do_map(int maptype, char_u *arg, int mode, int abbrev);
66
void map_clear_int(buf_T *buf, int mode, int local, int abbr);
7+
int mode_str2flags(char_u *modechars);
78
int map_to_exists(char_u *str, char_u *modechars, int abbr);
89
int map_to_exists_mode(char_u *rhs, int mode, int abbr);
910
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);

src/structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3054,6 +3054,7 @@ struct window_S
30543054
// computed
30553055
callback_T w_close_cb; // popup close callback
30563056
callback_T w_filter_cb; // popup filter callback
3057+
int w_filter_mode; // mode when filter callback is used
30573058

30583059
win_T *w_popup_curwin; // close popup if curwin differs
30593060
linenr_T w_popup_lnum; // close popup if cursor not on this line

src/testdir/test_popupwin.vim

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,6 +1892,72 @@ func Test_popupwin_garbage_collect()
18921892
delfunc MyPopupFilter
18931893
endfunc
18941894

1895+
func Test_popupwin_filter_mode()
1896+
func MyPopupFilter(winid, c)
1897+
let s:typed = a:c
1898+
if a:c == ':' || a:c == "\r" || a:c == 'v'
1899+
" can start cmdline mode, get out, and start/stop Visual mode
1900+
return 0
1901+
endif
1902+
return 1
1903+
endfunc
1904+
1905+
" Normal, Visual and Insert mode
1906+
let winid = popup_create('something', #{filter: 'MyPopupFilter', filtermode: 'nvi'})
1907+
redraw
1908+
call feedkeys('x', 'xt')
1909+
call assert_equal('x', s:typed)
1910+
1911+
call feedkeys(":let g:foo = 'foo'\<CR>", 'xt')
1912+
call assert_equal(':', s:typed)
1913+
call assert_equal('foo', g:foo)
1914+
1915+
let @x = 'something'
1916+
call feedkeys('v$"xy', 'xt')
1917+
call assert_equal('y', s:typed)
1918+
call assert_equal('something', @x) " yank command is filtered out
1919+
call feedkeys('v', 'xt') " end Visual mode
1920+
1921+
call popup_close(winid)
1922+
1923+
" only Normal mode
1924+
let winid = popup_create('something', #{filter: 'MyPopupFilter', filtermode: 'n'})
1925+
redraw
1926+
call feedkeys('x', 'xt')
1927+
call assert_equal('x', s:typed)
1928+
1929+
call feedkeys(":let g:foo = 'foo'\<CR>", 'xt')
1930+
call assert_equal(':', s:typed)
1931+
call assert_equal('foo', g:foo)
1932+
1933+
let @x = 'something'
1934+
call feedkeys('v$"xy', 'xt')
1935+
call assert_equal('v', s:typed)
1936+
call assert_notequal('something', @x)
1937+
1938+
call popup_close(winid)
1939+
1940+
" default: all modes
1941+
let winid = popup_create('something', #{filter: 'MyPopupFilter'})
1942+
redraw
1943+
call feedkeys('x', 'xt')
1944+
call assert_equal('x', s:typed)
1945+
1946+
let g:foo = 'bar'
1947+
call feedkeys(":let g:foo = 'foo'\<CR>", 'xt')
1948+
call assert_equal("\r", s:typed)
1949+
call assert_equal('bar', g:foo)
1950+
1951+
let @x = 'something'
1952+
call feedkeys('v$"xy', 'xt')
1953+
call assert_equal('y', s:typed)
1954+
call assert_equal('something', @x) " yank command is filtered out
1955+
call feedkeys('v', 'xt') " end Visual mode
1956+
1957+
call popup_close(winid)
1958+
delfunc MyPopupFilter
1959+
endfunc
1960+
18951961
func Test_popupwin_with_buffer()
18961962
call writefile(['some text', 'in a buffer'], 'XsomeFile')
18971963
let buf = bufadd('XsomeFile')

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,8 @@ static char *(features[]) =
761761

762762
static int included_patches[] =
763763
{ /* Add new patch number below this line */
764+
/**/
765+
1969,
764766
/**/
765767
1968,
766768
/**/

src/vim.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
680680
#define CONFIRM 0x800 // ":confirm" prompt
681681
#define SELECTMODE 0x1000 // Select mode, only for mappings
682682
#define TERMINAL 0x2000 // Terminal mode
683+
#define MODE_ALL 0xffff
683684

684685
// all mode bits used for mapping
685686
#define MAP_ALL_MODES (0x3f | SELECTMODE | TERMINAL)

0 commit comments

Comments
 (0)