1
0
forked from aniani/vim

patch 8.1.1713: highlighting cursor line only works with popup_menu()

Problem:    Highlighting cursor line only works with popup_menu().
Solution:   Add the "cursorline" property. (Naruhiko Nishino, closes #4671)
This commit is contained in:
Bram Moolenaar 2019-07-18 13:46:42 +02:00
parent d6bcff4577
commit df9c6cad8c
15 changed files with 339 additions and 29 deletions

View File

@ -303,7 +303,7 @@ popup_getoptions({id}) *popup_getoptions()*
zero. When all values are one then an empty list is included.
"borderhighlight" is not included when all values are empty.
"scrollbarhighlight" and "thumbhighlight" are onlu included
"scrollbarhighlight" and "thumbhighlight" are only included
when set.
"tabpage" will be -1 for a global popup, zero for a popup on
@ -345,7 +345,7 @@ popup_hide({id}) *popup_hide()*
popup_locate({row}, {col}) *popup_locate()*
Return the |window-ID| of the popup at screen positoin {row}
Return the |window-ID| of the popup at screen position {row}
and {col}. If there are multiple popups the one with the
highest zindex is returned. If there are no popups at this
position then zero is returned.
@ -362,6 +362,7 @@ popup_menu({what}, {options}) *popup_menu()*
\ drag: 1,
\ wrap: 0,
\ border: [],
\ cursorline: 1,
\ padding: [0,1,0,1],
\ filter: 'popup_filter_menu',
\ })
@ -429,6 +430,7 @@ popup_setoptions({id}, {options}) *popup_setoptions()*
callback
close
drag
cursorline
filter
firstline
flip
@ -598,6 +600,11 @@ The second argument of |popup_create()| is a dictionary with options:
{start} or after {end}
The popup also closes if the cursor moves to another
line or to another window.
cursorline non-zero: Highlight the cursor line. Also scrolls the
text to show this line (only works properly
when 'wrap' is off).
zero: Do not highlight the cursor line.
Default is zero, except for |popup_menu()|.
filter A callback that can filter typed characters, see
|popup-filter|.
callback A callback that is called when the popup closes, e.g.
@ -695,8 +702,8 @@ If the text does not fit in the popup a scrollbar is displayed on the right of
the window. This can be disabled by setting the "scrollbar" option to zero.
When the scrollbar is displayed mouse scroll events, while the mouse pointer
is on the popup, will cause the text to scroll up or down as you would expect.
A click in the upper halve of the scrollbar will scroll the text one line
down. A click in the lower halve wil scroll the text one line up. However,
A click in the upper half of the scrollbar will scroll the text one line
down. A click in the lower half wil scroll the text one line up. However,
this is limited so that the popup does not get smaller.
@ -709,7 +716,7 @@ list has four numbers:
leftmost, negative for counting from the right, -1 for
rightmost
endcol last column, like "col"
line start line, positive for conting from the top, 1 for top,
line start line, positive for counting from the top, 1 for top,
negative for counting from the bottom, -1 for bottom
endline end line, like "line"

View File

@ -441,6 +441,34 @@ check_highlight(dict_T *dict, char *name, char_u **pval)
}
}
/*
* Highlight the line with the cursor.
* Also scrolls the text to put the cursor line in view.
*/
static void
popup_highlight_curline(win_T *wp)
{
int id;
char buf[100];
match_delete(wp, 1, FALSE);
if ((wp->w_popup_flags & POPF_CURSORLINE) != 0)
{
// Scroll to show the line with the cursor. This assumes lines don't
// wrap.
while (wp->w_topline + wp->w_height - 1 < wp->w_cursor.lnum)
wp->w_topline++;
while (wp->w_cursor.lnum < wp->w_topline)
wp->w_topline--;
id = syn_name2id((char_u *)"PopupSelected");
vim_snprintf(buf, sizeof(buf), "\\%%%dl.*", (int)wp->w_cursor.lnum);
match_add(wp, (char_u *)(id == 0 ? "PmenuSel" : "PopupSelected"),
(char_u *)buf, 10, 1, NULL, NULL);
}
}
/*
* Shared between popup_create() and f_popup_setoptions().
*/
@ -635,6 +663,20 @@ apply_general_options(win_T *wp, dict_T *dict)
handle_moved_argument(wp, di, TRUE);
}
di = dict_find(dict, (char_u *)"cursorline", -1);
if (di != NULL)
{
if (di->di_tv.v_type == VAR_NUMBER)
{
if (di->di_tv.vval.v_number != 0)
wp->w_popup_flags |= POPF_CURSORLINE;
else
wp->w_popup_flags &= ~POPF_CURSORLINE;
}
else
semsg(_(e_invargval), "cursorline");
}
di = dict_find(dict, (char_u *)"filter", -1);
if (di != NULL)
{
@ -662,6 +704,7 @@ apply_general_options(win_T *wp, dict_T *dict)
/*
* Go through the options in "dict" and apply them to popup window "wp".
* Only used when creating a new popup window.
*/
static void
apply_options(win_T *wp, dict_T *dict)
@ -679,6 +722,7 @@ apply_options(win_T *wp, dict_T *dict)
}
popup_mask_refresh = TRUE;
popup_highlight_curline(wp);
}
/*
@ -1313,6 +1357,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
set_callback(&wp->w_filter_cb, &callback);
wp->w_p_wrap = 0;
wp->w_popup_flags |= POPF_CURSORLINE;
}
for (i = 0; i < 4; ++i)
@ -1502,26 +1547,6 @@ filter_handle_drag(win_T *wp, int c, typval_T *rettv)
rettv->vval.v_number = 0;
}
static void
popup_highlight_curline(win_T *wp)
{
int id;
char buf[100];
match_delete(wp, 1, FALSE);
// Scroll to show the line with the cursor. This assumes lines don't wrap.
while (wp->w_topline + wp->w_height - 1 < wp->w_cursor.lnum)
wp->w_topline++;
while (wp->w_cursor.lnum < wp->w_topline)
wp->w_topline--;
id = syn_name2id((char_u *)"PopupSelected");
vim_snprintf(buf, sizeof(buf), "\\%%%dl.*", (int)wp->w_cursor.lnum);
match_add(wp, (char_u *)(id == 0 ? "PmenuSel" : "PopupSelected"),
(char_u *)buf, 10, 1, NULL, NULL);
}
/*
* popup_filter_menu({text}, {options})
*/
@ -1630,10 +1655,7 @@ f_popup_dialog(typval_T *argvars, typval_T *rettv)
void
f_popup_menu(typval_T *argvars, typval_T *rettv)
{
win_T *wp = popup_create(argvars, rettv, TYPE_MENU);
if (wp != NULL)
popup_highlight_curline(wp);
popup_create(argvars, rettv, TYPE_MENU);
}
/*
@ -1858,6 +1880,7 @@ f_popup_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
if (old_firstline != wp->w_firstline)
redraw_win_later(wp, NOT_VALID);
popup_mask_refresh = TRUE;
popup_highlight_curline(wp);
popup_adjust_position(wp);
}
@ -2047,6 +2070,7 @@ f_popup_getoptions(typval_T *argvars, typval_T *rettv)
dict_add_string(dict, "title", wp->w_popup_title);
dict_add_number(dict, "wrap", wp->w_p_wrap);
dict_add_number(dict, "drag", wp->w_popup_drag);
dict_add_number(dict, "cursorline", (wp->w_popup_flags & POPF_CURSORLINE) != 0);
dict_add_string(dict, "highlight", wp->w_p_wcr);
if (wp->w_scrollbar_highlight != NULL)
dict_add_string(dict, "scrollbarhighlight",
@ -2181,6 +2205,7 @@ invoke_popup_filter(win_T *wp, int c)
int dummy;
typval_T argv[3];
char_u buf[NUMBUFLEN];
linenr_T old_lnum = wp->w_cursor.lnum;
// Emergency exit: CTRL-C closes the popup.
if (c == Ctrl_C)
@ -2205,6 +2230,9 @@ invoke_popup_filter(win_T *wp, int c)
// NOTE: The callback might close the popup, thus make "wp" invalid.
call_callback(&wp->w_filter_cb, -1,
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
if (old_lnum != wp->w_cursor.lnum)
popup_highlight_curline(wp);
res = tv_get_number(&rettv);
vim_free(argv[1].vval.v_string);
clear_tv(&rettv);

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @34|1+0#0000001#ffd7ff255@2| +0#4040ff13#ffffff0@35
|~| @34|2+0#0000001#ffd7ff255@2| +0#4040ff13#ffffff0@35
|~| @34|3+0#0000001#ffd7ff255@2| +0#4040ff13#ffffff0@35
|~| @73
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @34|1+0#0000001#e0e0e08@2| +0#4040ff13#ffffff0@35
|~| @34|2+0#0000001#ffd7ff255@2| +0#4040ff13#ffffff0@35
|~| @34|3+0#0000001#ffd7ff255@2| +0#4040ff13#ffffff0@35
|~| @73
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @32|╔+0#0000001#ffd7ff255|═@5|╗| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |1@2| | +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |2@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|╚+0#0000001#ffd7ff255|═@5|╝| +0#4040ff13#ffffff0@32
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @32|╔+0#0000001#ffd7ff255|═@5|╗| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |2@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |3@2| | +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|╚+0#0000001#ffd7ff255|═@5|╝| +0#4040ff13#ffffff0@32
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @32|╔+0#0000001#ffd7ff255|═@5|╗| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |1+0&#e0e0e08@2| +0&#ffd7ff255| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |2@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|╚+0#0000001#ffd7ff255|═@5|╝| +0#4040ff13#ffffff0@32
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @32|╔+0#0000001#ffd7ff255|═@5|╗| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |2@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |3+0&#e0e0e08@2| +0&#ffd7ff255| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|╚+0#0000001#ffd7ff255|═@5|╝| +0#4040ff13#ffffff0@32
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @32|╔+0#0000001#ffd7ff255|═@5|╗| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |1@2| | +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |2+0&#e0e0e08@2| +0&#ffd7ff255| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |3@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|╚+0#0000001#ffd7ff255|═@5|╝| +0#4040ff13#ffffff0@32
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @32|╔+0#0000001#ffd7ff255|═@5|╗| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |1+0&#e0e0e08@2| +0&#ffd7ff255| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |2@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |3@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|╚+0#0000001#ffd7ff255|═@5|╝| +0#4040ff13#ffffff0@32
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @32|╔+0#0000001#ffd7ff255|═@5|╗| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |7@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |8@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |9+0&#e0e0e08@2| +0&#ffd7ff255| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|╚+0#0000001#ffd7ff255|═@5|╝| +0#4040ff13#ffffff0@32
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @32|╔+0#0000001#ffd7ff255|═@5|╗| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |1+0&#e0e0e08@2| +0&#ffd7ff255| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |2@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|║+0#0000001#ffd7ff255| |3@2| | +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@32
|~| @32|╚+0#0000001#ffd7ff255|═@5|╝| +0#4040ff13#ffffff0@32
|~| @73
|~| @73
| +0#0000000&@56|0|,|0|-|1| @8|A|l@1|

View File

@ -1921,4 +1921,176 @@ func Test_popup_menu_with_scrollbar()
call delete('XtestPopupMenuScroll')
endfunc
func Test_popup_menu_filter()
if !CanRunVimInTerminal()
throw 'Skipped: cannot make screendumps'
endif
let lines =<< trim END
function! MyFilter(winid, key) abort
if a:key == "0"
call win_execute(a:winid, "call setpos('.', [0, 1, 1, 0])")
return 1
endif
if a:key == "G"
call win_execute(a:winid, "call setpos('.', [0, line('$'), 1, 0])")
return 1
endif
if a:key == "j"
call win_execute(a:winid, "call setpos('.', [0, line('.') + 1, 1, 0])")
return 1
endif
if a:key == "k"
call win_execute(a:winid, "call setpos('.', [0, line('.') - 1, 1, 0])")
return 1
endif
if a:key == 'x'
call popup_close(a:winid)
return 1
endif
return 0
endfunction
call popup_menu(['111', '222', '333', '444', '555', '666', '777', '888', '999'], #{
\ maxheight : 3,
\ filter : 'MyFilter'
\ })
END
call writefile(lines, 'XtestPopupMenuFilter')
let buf = RunVimInTerminal('-S XtestPopupMenuFilter', #{rows: 10})
call term_sendkeys(buf, "j")
call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_1', {})
call term_sendkeys(buf, "k")
call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_2', {})
call term_sendkeys(buf, "G")
call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_3', {})
call term_sendkeys(buf, "0")
call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_4', {})
call term_sendkeys(buf, "x")
" clean up
call StopVimInTerminal(buf)
call delete('XtestPopupMenuFilter')
endfunc
func Test_popup_cursorline()
if !CanRunVimInTerminal()
throw 'Skipped: cannot make screendumps'
endif
let winid = popup_create('some text', {})
call assert_equal(0, popup_getoptions(winid).cursorline)
call popup_close(winid)
let winid = popup_create('some text', #{ cursorline: 1, })
call assert_equal(1, popup_getoptions(winid).cursorline)
call popup_close(winid)
let winid = popup_create('some text', #{ cursorline: 0, })
call assert_equal(0, popup_getoptions(winid).cursorline)
call popup_close(winid)
let winid = popup_menu('some text', {})
call assert_equal(1, popup_getoptions(winid).cursorline)
call popup_close(winid)
let winid = popup_menu('some text', #{ cursorline: 1, })
call assert_equal(1, popup_getoptions(winid).cursorline)
call popup_close(winid)
let winid = popup_menu('some text', #{ cursorline: 0, })
call assert_equal(0, popup_getoptions(winid).cursorline)
call popup_close(winid)
" ---------
" Pattern 1
" ---------
let lines =<< trim END
call popup_create(['111', '222', '333'], #{ cursorline : 0 })
END
call writefile(lines, 'XtestPopupCursorLine')
let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10})
call VerifyScreenDump(buf, 'Test_popupwin_cursorline_1', {})
call term_sendkeys(buf, ":call popup_clear()\<cr>")
call StopVimInTerminal(buf)
" ---------
" Pattern 2
" ---------
let lines =<< trim END
call popup_create(['111', '222', '333'], #{ cursorline : 1 })
END
call writefile(lines, 'XtestPopupCursorLine')
let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10})
call VerifyScreenDump(buf, 'Test_popupwin_cursorline_2', {})
call term_sendkeys(buf, ":call popup_clear()\<cr>")
call StopVimInTerminal(buf)
" ---------
" Pattern 3
" ---------
let lines =<< trim END
function! MyFilter(winid, key) abort
if a:key == "j"
call win_execute(a:winid, "call setpos('.', [0, line('.') + 1, 1, 0]) | redraw")
return 1
endif
if a:key == 'x'
call popup_close(a:winid)
return 1
endif
return 0
endfunction
call popup_menu(['111', '222', '333'], #{
\ cursorline : 0,
\ maxheight : 2,
\ filter : 'MyFilter',
\ })
END
call writefile(lines, 'XtestPopupCursorLine')
let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10})
call VerifyScreenDump(buf, 'Test_popupwin_cursorline_3', {})
call term_sendkeys(buf, "j")
call term_sendkeys(buf, "j")
call VerifyScreenDump(buf, 'Test_popupwin_cursorline_4', {})
call term_sendkeys(buf, "x")
call StopVimInTerminal(buf)
" ---------
" Pattern 4
" ---------
let lines =<< trim END
function! MyFilter(winid, key) abort
if a:key == "j"
call win_execute(a:winid, "call setpos('.', [0, line('.') + 1, 1, 0]) | redraw")
return 1
endif
if a:key == 'x'
call popup_close(a:winid)
return 1
endif
return 0
endfunction
call popup_menu(['111', '222', '333'], #{
\ cursorline : 1,
\ maxheight : 2,
\ filter : 'MyFilter',
\ })
END
call writefile(lines, 'XtestPopupCursorLine')
let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10})
call VerifyScreenDump(buf, 'Test_popupwin_cursorline_5', {})
call term_sendkeys(buf, "j")
call term_sendkeys(buf, "j")
call VerifyScreenDump(buf, 'Test_popupwin_cursorline_6', {})
call term_sendkeys(buf, "x")
call StopVimInTerminal(buf)
call delete('XtestPopupCursorLine')
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

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

View File

@ -617,6 +617,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define POPF_IS_POPUP 1 // this is a popup window
#define POPF_HIDDEN 2 // popup is not displayed
#define POPF_HANDLED 4 // popup was just redrawn or filtered
#define POPF_CURSORLINE 8 // popup is highlighting at the cursorline
#ifdef FEAT_TEXT_PROP
# define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0)
#else