0
0
mirror of https://github.com/vim/vim.git synced 2025-10-07 05:54:16 -04:00

patch 8.1.1553: not easy to change the text in a popup window

Problem:    Not easy to change the text in a popup window.
Solution:   Add popup_settext(). (Ben Jackson, closes #4549)
            Also display a space for an empty popup.
This commit is contained in:
Bram Moolenaar
2019-06-16 15:32:14 +02:00
parent f85e40afc2
commit dc2ce58b5a
12 changed files with 192 additions and 34 deletions

View File

@@ -104,15 +104,18 @@ TODO:
incomplete cell. incomplete cell.
- Can the buffer be re-used, to avoid using up lots of buffer numbers? - Can the buffer be re-used, to avoid using up lots of buffer numbers?
- Use a popup window for the "info" item of completion instead of using a - Use a popup window for the "info" item of completion instead of using a
preview window. preview window. Ideas in issue #4544.
How to add highlighting?
- When the lines do not fit show a scrollbar (like in the popup menu).
Use the mouse wheel for scrolling.
- Implement: - Implement:
popup_filter_menu({id}, {key}) popup_filter_menu({id}, {key})
popup_menu({text}, {options}) popup_menu({text}, {options})
popup_setoptions({id}, {options}) popup_setoptions({id}, {options})
flip option
hidden option hidden option
tabpage option with number tabpage option with number
title option title option
flip option
transparent text property transparent text property
@@ -134,6 +137,7 @@ Manipulating a popup window:
|popup_show()| show a previously hidden popup |popup_show()| show a previously hidden popup
|popup_move()| change the position and size of a popup |popup_move()| change the position and size of a popup
|popup_setoptions()| override options of a popup |popup_setoptions()| override options of a popup
|popup_settext()| replace the popup buffer contents
Closing popup windows: Closing popup windows:
|popup_close()| close one popup |popup_close()| close one popup
@@ -330,6 +334,11 @@ popup_setoptions({id}, {options}) *popup_setoptions()*
{not implemented yet} {not implemented yet}
Override options in popup {id} with entries in {options}. Override options in popup {id} with entries in {options}.
popup_settext({id}, {text}) *popup_settext()*
Set the text of the buffer in poup win {id}. {text} is the
same as supplied to |popup_create()|.
Does not change the window size or position, other than caused
by the different text.
POPUP BUFFER AND WINDOW *popup-buffer* POPUP BUFFER AND WINDOW *popup-buffer*
@@ -365,8 +374,9 @@ need them.
POPUP_CREATE() ARGUMENTS *popup_create-usage* POPUP_CREATE() ARGUMENTS *popup_create-usage*
The first argument of |popup_create()| specifies the text to be displayed, and The first argument of |popup_create()| (and the second argument to
optionally text properties. It is in one of three forms: |popup_setttext()|) specifies the text to be displayed, and optionally text
properties. It is in one of three forms:
- a string - a string
- a list of strings - a list of strings
- a list of dictionaries, where each dictionary has these entries: - a list of dictionaries, where each dictionary has these entries:
@@ -404,7 +414,9 @@ The second argument of |popup_create()| is a dictionary with options:
flip When TRUE (the default) and the position is relative flip When TRUE (the default) and the position is relative
to the cursor, flip to below or above the cursor to to the cursor, flip to below or above the cursor to
avoid overlap with the |popupmenu-completion| or avoid overlap with the |popupmenu-completion| or
another popup with a higher "zindex". another popup with a higher "zindex". When there is
no space above/below the cursor then show the popup to
the side of the popup or popup menu.
{not implemented yet} {not implemented yet}
maxheight Maximum height of the contents, excluding border and maxheight Maximum height of the contents, excluding border and
padding. padding.
@@ -434,7 +446,9 @@ The second argument of |popup_create()| is a dictionary with options:
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 at the border. Has no effect if the
popup does not have a border. popup does not have a border. As soon as dragging
starts and "pos" is "center" it is changed to
"topleft".
highlight Highlight group name to use for the text, stored in highlight Highlight group name to use for the text, stored in
the 'wincolor' option. the 'wincolor' option.
padding List with numbers, defining the padding padding List with numbers, defining the padding

View File

@@ -822,6 +822,7 @@ static struct fst
{"popup_hide", 1, 1, f_popup_hide}, {"popup_hide", 1, 1, f_popup_hide},
{"popup_move", 2, 2, f_popup_move}, {"popup_move", 2, 2, f_popup_move},
{"popup_notification", 2, 2, f_popup_notification}, {"popup_notification", 2, 2, f_popup_notification},
{"popup_settext", 2, 2, f_popup_settext},
{"popup_show", 1, 1, f_popup_show}, {"popup_show", 1, 1, f_popup_show},
#endif #endif
#ifdef FEAT_FLOAT #ifdef FEAT_FLOAT

View File

@@ -601,8 +601,10 @@ popup_adjust_position(win_T *wp)
wp->w_topline = wp->w_buffer->b_ml.ml_line_count; wp->w_topline = wp->w_buffer->b_ml.ml_line_count;
// Compute width based on longest text line and the 'wrap' option. // Compute width based on longest text line and the 'wrap' option.
// Use a minimum width of one, so that something shows when there is no
// text.
// TODO: more accurate wrapping // TODO: more accurate wrapping
wp->w_width = 0; wp->w_width = 1;
for (lnum = wp->w_topline; lnum <= wp->w_buffer->b_ml.ml_line_count; ++lnum) for (lnum = wp->w_topline; lnum <= wp->w_buffer->b_ml.ml_line_count; ++lnum)
{ {
int len = vim_strsize(ml_get_buf(wp->w_buffer, lnum, FALSE)); int len = vim_strsize(ml_get_buf(wp->w_buffer, lnum, FALSE));
@@ -703,6 +705,48 @@ typedef enum
TYPE_DIALOG TYPE_DIALOG
} create_type_T; } create_type_T;
/*
* Make "buf" empty and set the contents to "text".
* Used by popup_create() and popup_settext().
*/
static void
popup_set_buffer_text(buf_T *buf, typval_T text)
{
int lnum;
// Clear the buffer, then replace the lines.
curbuf = buf;
for (lnum = buf->b_ml.ml_line_count; lnum > 0; --lnum)
ml_delete(lnum, FALSE);
curbuf = curwin->w_buffer;
// Add text to the buffer.
if (text.v_type == VAR_STRING)
{
// just a string
ml_append_buf(buf, 0, text.vval.v_string, (colnr_T)0, TRUE);
}
else
{
list_T *l = text.vval.v_list;
if (l->lv_len > 0)
{
if (l->lv_first->li_tv.v_type == VAR_STRING)
// list of strings
add_popup_strings(buf, l);
else
// list of dictionaries
add_popup_dicts(buf, l);
}
}
// delete the line that was in the empty buffer
curbuf = buf;
ml_delete(buf->b_ml.ml_line_count, FALSE);
curbuf = curwin->w_buffer;
}
/* /*
* popup_create({text}, {options}) * popup_create({text}, {options})
* popup_atcursor({text}, {options}) * popup_atcursor({text}, {options})
@@ -789,31 +833,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
// TODO: find tab page "nr" // TODO: find tab page "nr"
emsg("Not implemented yet"); emsg("Not implemented yet");
// Add text to the buffer. popup_set_buffer_text(buf, argvars[0]);
if (argvars[0].v_type == VAR_STRING)
{
// just a string
ml_append_buf(buf, 0, argvars[0].vval.v_string, (colnr_T)0, TRUE);
}
else
{
list_T *l = argvars[0].vval.v_list;
if (l->lv_len > 0)
{
if (l->lv_first->li_tv.v_type == VAR_STRING)
// list of strings
add_popup_strings(buf, l);
else
// list of dictionaries
add_popup_dicts(buf, l);
}
}
// Delete the line of the empty buffer.
curbuf = buf;
ml_delete(buf->b_ml.ml_line_count, FALSE);
curbuf = curwin->w_buffer;
if (type == TYPE_ATCURSOR) if (type == TYPE_ATCURSOR)
{ {
@@ -1112,6 +1132,22 @@ f_popup_show(typval_T *argvars, typval_T *rettv UNUSED)
} }
} }
/*
* popup_settext({id}, {text})
*/
void
f_popup_settext(typval_T *argvars, typval_T *rettv UNUSED)
{
int id = (int)tv_get_number(&argvars[0]);
win_T *wp = find_popup_win(id);
if (wp != NULL)
{
popup_set_buffer_text(wp->w_buffer, argvars[1]);
popup_adjust_position(wp);
}
}
static void static void
popup_free(win_T *wp) popup_free(win_T *wp)
{ {

View File

@@ -14,6 +14,7 @@ void f_popup_notification(typval_T *argvars, typval_T *rettv);
void f_popup_close(typval_T *argvars, typval_T *rettv); void f_popup_close(typval_T *argvars, typval_T *rettv);
void f_popup_hide(typval_T *argvars, typval_T *rettv); void f_popup_hide(typval_T *argvars, typval_T *rettv);
void f_popup_show(typval_T *argvars, typval_T *rettv); void f_popup_show(typval_T *argvars, typval_T *rettv);
void f_popup_settext(typval_T *argvars, typval_T *rettv);
void popup_close(int id); void popup_close(int id);
void popup_close_tabpage(tabpage_T *tp, int id); void popup_close_tabpage(tabpage_T *tp, int id);
void close_all_popups(void); void close_all_popups(void);

View File

@@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @73
|~| @28|t+0#0000001#ffd7ff255|h|i|s| |i|s| |a| |t|e|x|t| +0#4040ff13#ffffff0@30
|~| @73
|~| @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
|~| @73
|~| @35| +0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
|~| @73
|~| @73
|~| @73
|~| @73
|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|p|,| |'@1|)| @30|0|,|0|-|1| @8|A|l@1|

View File

@@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @35|a+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
|~| @35|b+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
|~| @35|c+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
|~| @73
|~| @73
|~| @73
|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|p|,| |[|'|a|'|,|'|b|'|,|'|c|'|]|)| @19|0|,|0|-|1| @8|A|l@1|

View File

@@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @73
|~| @35|a+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
|~| @73
|~| @73
|~| @73
|~| @73
|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|p|,| |[|'|a|'|]|)| @27|0|,|0|-|1| @8|A|l@1|

View File

@@ -0,0 +1,10 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @73
|~| @35| +0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
|~| @73
|~| @73
|~| @73
|~| @73
|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|p|,| |[|]|)| @30|0|,|0|-|1| @8|A|l@1|

View File

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

View File

@@ -916,13 +916,13 @@ func Test_popup_empty()
let winid = popup_create('', {'padding': [2,2,2,2]}) let winid = popup_create('', {'padding': [2,2,2,2]})
redraw redraw
let pos = popup_getpos(winid) let pos = popup_getpos(winid)
call assert_equal(4, pos.width) call assert_equal(5, pos.width)
call assert_equal(5, pos.height) call assert_equal(5, pos.height)
let winid = popup_create([], {'border': []}) let winid = popup_create([], {'border': []})
redraw redraw
let pos = popup_getpos(winid) let pos = popup_getpos(winid)
call assert_equal(2, pos.width) call assert_equal(3, pos.width)
call assert_equal(3, pos.height) call assert_equal(3, pos.height)
endfunc endfunc
@@ -1231,3 +1231,47 @@ func Test_notifications()
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
call delete('XtestNotifications') call delete('XtestNotifications')
endfunc endfunc
function Test_popup_settext()
if !CanRunVimInTerminal()
throw 'Skipped: cannot make screendumps'
endif
let lines =<< trim END
let opts = {'wrap': 0}
let p = popup_create('test', opts)
call popup_settext(p, 'this is a text')
END
call writefile( lines, 'XtestPopupSetText' )
let buf = RunVimInTerminal('-S XtestPopupSetText', {'rows': 10})
call VerifyScreenDump(buf, 'Test_popup_settext_01', {})
" Setting to empty string clears it
call term_sendkeys(buf, ":call popup_settext(p, '')\<CR>")
call VerifyScreenDump(buf, 'Test_popup_settext_02', {})
" Setting a list
call term_sendkeys(buf, ":call popup_settext(p, ['a','b','c'])\<CR>")
call VerifyScreenDump(buf, 'Test_popup_settext_03', {})
" Shrinking with a list
call term_sendkeys(buf, ":call popup_settext(p, ['a'])\<CR>")
call VerifyScreenDump(buf, 'Test_popup_settext_04', {})
" Growing with a list
call term_sendkeys(buf, ":call popup_settext(p, ['a','b','c'])\<CR>")
call VerifyScreenDump(buf, 'Test_popup_settext_03', {})
" Empty list clears
call term_sendkeys(buf, ":call popup_settext(p, [])\<CR>")
call VerifyScreenDump(buf, 'Test_popup_settext_05', {})
" Dicts
call term_sendkeys(buf, ":call popup_settext(p, [{'text': 'aaaa'}, {'text': 'bbbb'}, {'text': 'cccc'}])\<CR>")
call VerifyScreenDump(buf, 'Test_popup_settext_06', {})
" clean up
call StopVimInTerminal(buf)
call delete('XtestPopupSetText')
endfunction

View File

@@ -777,6 +777,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 */
/**/
1553,
/**/ /**/
1552, 1552,
/**/ /**/