changeset 17149:c90fdb999393 v8.1.1574

patch 8.1.1574: tabpage option not yet implemented for popup window commit https://github.com/vim/vim/commit/a3fce62c911c204ae144b55018f6dc9295088850 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jun 20 02:31:49 2019 +0200 patch 8.1.1574: tabpage option not yet implemented for popup window Problem: Tabpage option not yet implemented for popup window. Solution: Implement tabpage option, also for popup_getoptions().
author Bram Moolenaar <Bram@vim.org>
date Thu, 20 Jun 2019 02:45:05 +0200
parents 34404b7bbde7
children 96373bb9c0eb
files runtime/doc/popup.txt src/popupwin.c src/testdir/test_popupwin.vim src/version.c
diffstat 4 files changed, 118 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/popup.txt
+++ b/runtime/doc/popup.txt
@@ -88,12 +88,17 @@ that it is in.
 
 TODO:
 - Why does 'nrformats' leak from the popup window buffer???
+- When the lines do not fit show a scrollbar (like in the popup menu).
+  Use the mouse wheel for scrolling.
 - Disable commands, feedkeys(), CTRL-W, etc. in a popup window.
   Use ERROR_IF_POPUP_WINDOW for more commands.
 - Add 'balloonpopup': instead of showing text, let the callback open a popup
   window and return the window ID.   The popup will then be closed when the
   mouse moves, except when it moves inside the popup.
 - For the "moved" property also include mouse movement?
+- Can the buffer be re-used, to avoid using up lots of buffer numbers?
+- Have an option to attach the popup to a text position, like text properties
+  do. (#4560)
 - Make redrawing more efficient and avoid flicker:
     - put popup menu also put in popup_mask?
 - Invoke filter with character before mapping?
@@ -102,17 +107,12 @@ TODO:
     if wrapping inserts indent
 - When drawing on top half a double-wide character, display ">" or "<" in the
   incomplete cell.
-- 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
   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:
-	tabpage option with number
 	flip option
-	transparent text property
-
+	transparent area, to minimize covering text.  Define rectangles?
 
 ==============================================================================
 2. Functions						*popup-functions*
@@ -123,7 +123,7 @@ Creating a popup window:
 	|popup_create()|	centered in the screen
 	|popup_atcursor()|	just above the cursor position, closes when
 				the cursor moves away
-	|popup_notifiation()|	show a notification for three seconds
+	|popup_notification()|	show a notification for three seconds
 	|popup_dialog()|	centered with padding and border
 	|popup_menu()|		prompt for selecting an item from a list
 
@@ -163,7 +163,7 @@ popup_atcursor({text}, {options})			 *po
 
 							*popup_clear()*
 popup_clear()	Emergency solution to a misbehaving plugin: close all popup
-		windows.
+		windows for the current tab and global popups.
 
 
 popup_close({id} [, {result}])				*popup_close()*
@@ -216,7 +216,7 @@ popup_dialog({text}, {options})				*popu
 
 popup_filter_menu({id}, {key})				*popup_filter_menu()*
 		Filter that can be used for a popup. These keys can be used:
-		    j <Down>	select item below
+		    j <Down>		select item below
 		    k <Up>		select item above
 		    <Space> <Enter>	accept current selection
 		    x Esc CTRL-C	cancel the menu
@@ -230,6 +230,9 @@ popup_filter_menu({id}, {key})				*popup
 		the second argument.  The first entry has index one.
 		Cancelling the menu invokes the callback with -1.
 
+		To add shortcut keys, see the example here:
+		|popup_menu-shortcut-example|
+
 
 popup_filter_yesno({id}, {key})				*popup_filter_yesno()*
 		Filter that can be used for a popup. It handles only the keys
@@ -238,6 +241,7 @@ popup_filter_yesno({id}, {key})				*popu
 		as the second argument.  Pressing Esc and 'x' works like
 		pressing 'n'.  CTRL-C invokes the callback with -1.  Other
 		keys are ignored.
+		See the example here: |popup_dialog-example|
 
 
 popup_getoptions({id})					*popup_getoptions()*
@@ -253,6 +257,10 @@ popup_getoptions({id})					*popup_getopt
 
 		"borderhighlight" is not included when all values are empty.
 
+		"tabpage" will be -1 for a global popup, zero for a popup on
+		the current tabpage and a positive number for a popup on
+		another tabpage.
+
 		If popup window {id} is not found an empty Dict is returned.
 
 
@@ -390,7 +398,7 @@ manipulation is restricted:
 - 'bufhidden' is "hide"
 - 'buflisted' is off
 - 'undolevels' is -1: no undo at all
-- all other buffer-local and window_local options are set to their Vim default
+- all other buffer-local and window-local options are set to their Vim default
   value.
 
 It is possible to change the specifically mentioned options, but anything
@@ -474,8 +482,8 @@ The second argument of |popup_create()| 
 			When 0 (the default): display the popup on the current
 			tab page.
 			Otherwise the number of the tab page the popup is
-			displayed on; when invalid the current tab page is used.
-			{only -1 and 0 are implemented}
+			displayed on; when invalid the popup is not created
+			and an error is given. *E996*
 	title		Text to be displayed above the first item in the
 			popup, on top of any border.  If there is no top
 			border one line of padding is added to put the title
@@ -515,8 +523,8 @@ The second argument of |popup_create()| 
 			When the list has two characters the first is used for
 			the border lines, the second for the corners.
 			By default a double line is used all around when
-			'encoding' is "utf-8", otherwise ASCII characters are
-			used.
+			'encoding' is "utf-8" and 'ambiwidth' is "single,
+			otherwise ASCII characters are used.
 	zindex		Priority for the popup, default 50.  Minimum value is
 			1, maximum value is 32000.
 	time		Time in milliseconds after which the popup will close.
@@ -628,7 +636,7 @@ pressed, the number -1 is passed to the 
 3. Examples						*popup-examples*
 
 TODO
-
+					*popup_dialog-example*
 Prompt the user to press y/Y or n/N: >
 
 	func MyDialogHandler(id, result)
@@ -637,10 +645,37 @@ Prompt the user to press y/Y or n/N: >
 	   endif
 	endfunc
 
-	call popup_create(['Continue? y/n'], {
+	call popup_dialog('Continue? y/n', {
 		\ 'filter': 'popup_filter_yesno',
 		\ 'callback': 'MyDialogHandler',
 		\ })
 <
+					*popup_menu-shortcut-example*
+Extend popup_filter_menu() with shortcut keys: >
+
+	call popup_menu('Save', 'Cancel', 'Discard'], {
+		\ 'filter': 'MyMenuFilter',
+		\ 'callback': 'MyMenuHandler',
+		\ })
+
+	func MyMenuFilter(id, key)
+	  " Handle shortcuts
+	  if a:key == 'S'
+	     call popup_close(a:id, 1)
+	     return 1
+	  endif
+	  if a:key == 'C'
+	     call popup_close(a:id, 2)
+	     return 1
+	  endif
+	  if a:key == 'D'
+	     call popup_close(a:id, 3)
+	     return 1
+	  endif
+
+	  " No shortcut, pass to generic filter
+	  return popup_filter_menu(a:id, a:key)
+	endfunc
+<
 
  vim:tw=78:ts=8:noet:ft=help:norl:
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -827,11 +827,13 @@ popup_set_buffer_text(buf_T *buf, typval
     static win_T *
 popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
 {
-    win_T   *wp;
-    buf_T   *buf;
-    dict_T  *d;
-    int	    nr;
-    int	    i;
+    win_T	*wp;
+    tabpage_T	*tp = NULL;
+    int		tabnr;
+    buf_T	*buf;
+    dict_T	*d;
+    int		nr;
+    int		i;
 
     // Check arguments look OK.
     if (!(argvars[0].v_type == VAR_STRING && argvars[0].vval.v_string != NULL)
@@ -847,6 +849,22 @@ popup_create(typval_T *argvars, typval_T
     }
     d = argvars[1].vval.v_dict;
 
+    if (dict_find(d, (char_u *)"tabpage", -1) != NULL)
+	tabnr = (int)dict_get_number(d, (char_u *)"tabpage");
+    else if (type == TYPE_NOTIFICATION)
+	tabnr = -1;  // notifications are global by default
+    else
+	tabnr = 0;
+    if (tabnr > 0)
+    {
+	tp = find_tabpage(tabnr);
+	if (tp == NULL)
+	{
+	    semsg(_("E996: Tabpage not found: %d"), tabnr);
+	    return NULL;
+	}
+    }
+
     // Create the window and buffer.
     wp = win_alloc_popup_win();
     if (wp == NULL)
@@ -875,20 +893,19 @@ popup_create(typval_T *argvars, typval_T
     // Avoid that 'buftype' is reset when this buffer is entered.
     buf->b_p_initialized = TRUE;
 
-    if (dict_find(d, (char_u *)"tabpage", -1) != NULL)
-	nr = (int)dict_get_number(d, (char_u *)"tabpage");
-    else if (type == TYPE_NOTIFICATION)
-	nr = -1;  // notifications are global by default
-    else
-	nr = 0;
-
-    if (nr == 0)
+    if (tp != NULL)
+    {
+	// popup on specified tab page
+	wp->w_next = tp->tp_first_popupwin;
+	tp->tp_first_popupwin = wp;
+    }
+    else if (tabnr == 0)
     {
 	// popup on current tab page
 	wp->w_next = curtab->tp_first_popupwin;
 	curtab->tp_first_popupwin = wp;
     }
-    else if (nr < 0)
+    else // (tabnr < 0)
     {
 	win_T *prev = first_popupwin;
 
@@ -903,9 +920,6 @@ popup_create(typval_T *argvars, typval_T
 	    prev->w_next = wp;
 	}
     }
-    else
-	// TODO: find tab page "nr"
-	emsg("Not implemented yet");
 
     popup_set_buffer_text(buf, argvars[0]);
 
@@ -1592,6 +1606,7 @@ f_popup_getoptions(typval_T *argvars, ty
     dict_T	*dict;
     int		id = (int)tv_get_number(argvars);
     win_T	*wp = find_popup_win(id);
+    tabpage_T	*tp;
     int		i;
 
     if (rettv_dict_alloc(rettv) == OK)
@@ -1614,6 +1629,25 @@ f_popup_getoptions(typval_T *argvars, ty
 	dict_add_number(dict, "drag", wp->w_popup_drag);
 	dict_add_string(dict, "highlight", wp->w_p_wcr);
 
+	// find the tabpage that holds this popup
+	i = 1;
+	FOR_ALL_TABPAGES(tp)
+	{
+	    win_T *p;
+
+	     for (p = tp->tp_first_popupwin; p != NULL; p = wp->w_next)
+		 if (p->w_id == id)
+		     break;
+	     if (p != NULL)
+		 break;
+	     ++i;
+	}
+	if (tp == NULL)
+	    i = -1;  // must be global
+	else if (tp == curtab)
+	    i = 0;
+	dict_add_number(dict, "tabpage", i);
+
 	get_padding_border(dict, wp->w_popup_padding, "padding");
 	get_padding_border(dict, wp->w_popup_border, "border");
 	get_borderhighlight(dict, wp);
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -398,8 +398,10 @@ func Test_popup_in_tab()
   let winid = popup_create("text", {})
   let bufnr = winbufnr(winid)
   call assert_equal(1, popup_getpos(winid).visible)
+  call assert_equal(0, popup_getoptions(winid).tabpage)
   tabnew
   call assert_equal(0, popup_getpos(winid).visible)
+  call assert_equal(1, popup_getoptions(winid).tabpage)
   quit
   call assert_equal(1, popup_getpos(winid).visible)
 
@@ -411,11 +413,23 @@ func Test_popup_in_tab()
   " global popup is visible in any tab
   let winid = popup_create("text", {'tabpage': -1})
   call assert_equal(1, popup_getpos(winid).visible)
+  call assert_equal(-1, popup_getoptions(winid).tabpage)
   tabnew
   call assert_equal(1, popup_getpos(winid).visible)
+  call assert_equal(-1, popup_getoptions(winid).tabpage)
   quit
   call assert_equal(1, popup_getpos(winid).visible)
   call popup_clear()
+
+  " create popup in other tab
+  tabnew
+  let winid = popup_create("text", {'tabpage': 1})
+  call assert_equal(0, popup_getpos(winid).visible)
+  call assert_equal(1, popup_getoptions(winid).tabpage)
+  quit
+  call assert_equal(1, popup_getpos(winid).visible)
+  call assert_equal(0, popup_getoptions(winid).tabpage)
+  call popup_clear()
 endfunc
 
 func Test_popup_valid_arguments()
--- a/src/version.c
+++ b/src/version.c
@@ -778,6 +778,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1574,
+/**/
     1573,
 /**/
     1572,