changeset 35461:5301104f466a v9.1.0500

patch 9.1.0500: cannot switch buffer in a popup Commit: https://github.com/vim/vim/commit/fbc37f138a5d70f1b212b9de9959a0816481edcf Author: Christian Brabandt <cb@256bit.org> Date: Tue Jun 18 20:50:58 2024 +0200 patch 9.1.0500: cannot switch buffer in a popup Problem: cannot switch buffer in a popup (Yggdroot) Solution: add popup_setbuf() function fixes: #15006 closes: #15026 Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Tue, 18 Jun 2024 21:15:03 +0200
parents c7d7393301d3
children 24fbfda19203
files runtime/doc/builtin.txt runtime/doc/popup.txt runtime/doc/tags runtime/doc/usr_41.txt runtime/doc/version9.txt src/evalfunc.c src/popupwin.c src/proto/popupwin.pro src/testdir/dumps/Test_popup_setbuf_01.dump src/testdir/dumps/Test_popup_setbuf_02.dump src/testdir/dumps/Test_popup_setbuf_03.dump src/testdir/dumps/Test_popup_setbuf_04.dump src/testdir/dumps/Test_popup_setbuf_05.dump src/testdir/dumps/Test_popup_setbuf_06.dump src/testdir/test_popupwin.vim src/testdir/test_vim9_builtin.vim src/version.c
diffstat 17 files changed, 224 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -153,8 +153,8 @@ diff_filler({lnum})		Number	diff filler 
 diff_hlID({lnum}, {col})	Number	diff highlighting at {lnum}/{col}
 digraph_get({chars})		String	get the |digraph| of {chars}
 digraph_getlist([{listall}])	List	get all |digraph|s
-digraph_set({chars}, {digraph})	Boolean	register |digraph|
-digraph_setlist({digraphlist})	Boolean	register multiple |digraph|s
+digraph_set({chars}, {digraph})	Bool	register |digraph|
+digraph_setlist({digraphlist})	Bool	register multiple |digraph|s
 echoraw({expr})			none	output {expr} as-is
 empty({expr})			Number	|TRUE| if {expr} is empty
 environ()			Dict	return environment variables
@@ -429,6 +429,7 @@ popup_menu({what}, {options})	Number	cre
 popup_move({id}, {options})	none	set position of popup window {id}
 popup_notification({what}, {options})
 				Number	create a notification popup window
+popup_setbuf({id}, {buf})	Bool	set the buffer for the popup window {id}
 popup_setoptions({id}, {options})
 				none	set options for popup window {id}
 popup_settext({id}, {text})	none	set the text of popup window {id}
--- a/runtime/doc/popup.txt
+++ b/runtime/doc/popup.txt
@@ -1,4 +1,4 @@
-*popup.txt*  For Vim version 9.1.  Last change: 2024 Jun 08
+*popup.txt*  For Vim version 9.1.  Last change: 2024 Jun 16
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -186,6 +186,7 @@ Manipulating a popup window:
 	|popup_move()|		change the position and size of a popup
 	|popup_setoptions()|	override options of a popup
 	|popup_settext()|	replace the popup buffer contents
+	|popup_setbuf()|	set the buffer for the popup window
 
 Closing popup windows:
 	|popup_close()|		close one popup
@@ -574,6 +575,18 @@ popup_notification({what}, {options})			
 		Return type: |Number|
 
 
+popup_setbuf({id}, {buf})				*popup_setbuf()*
+		Set buffer {buf} to be displayed in popup win {id}.  For the
+		use of {buf}, see |bufname()| function.
+		May change window size or position to adjust for the size
+		of the buffer text.
+
+		Can also be used as a |method|: >
+			GetPopup()->popup_setbuf(bufnr('foobar'))
+<
+		Return type: |vim9-boolean|
+
+
 popup_setoptions({id}, {options})			*popup_setoptions()*
 		Override options in popup {id} with entries in {options}.
 		These options can be set:
@@ -613,9 +626,8 @@ popup_setoptions({id}, {options})			*pop
 
 
 popup_settext({id}, {text})				*popup_settext()*
-		Set the text of the buffer in popup win {id}. {text} is the
-		same as supplied to |popup_create()|, except that a buffer
-		number is not allowed.
+		Set the text of the buffer in popup win {id}. {text} is
+		a string or a list of strings to be displayed in the popup.
 		Does not change the window size or position, other than caused
 		by the different text.
 
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -9433,6 +9433,7 @@ popup_menu()	popup.txt	/*popup_menu()*
 popup_menu-shortcut-example	popup.txt	/*popup_menu-shortcut-example*
 popup_move()	popup.txt	/*popup_move()*
 popup_notification()	popup.txt	/*popup_notification()*
+popup_setbuf()	popup.txt	/*popup_setbuf()*
 popup_setoptions()	popup.txt	/*popup_setoptions()*
 popup_settext()	popup.txt	/*popup_settext()*
 popup_show()	popup.txt	/*popup_show()*
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -1319,6 +1319,7 @@ Popup window:					*popup-window-function
 	popup_move()		change the position and size of a popup
 	popup_setoptions()	override options of a popup
 	popup_settext()		replace the popup buffer contents
+	popup_setbuf()		set the popup buffer
 	popup_close()		close one popup
 	popup_clear()		close all popups
 	popup_filter_menu()	select from a list of items
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2024 Jun 17
+*version9.txt*  For Vim version 9.1.  Last change: 2024 Jun 18
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41586,6 +41586,7 @@ Functions: ~
 |getregionpos()|	get a list of positions for a region
 |matchbufline()|	all the matches of a pattern in a buffer
 |matchstrlist()|	all the matches of a pattern in a List of strings
+|popup_setbuf()|	switch to a different buffer in a popup
 
 
 Autocommands: ~
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -1133,6 +1133,7 @@ static argcheck_T arg2_number_bool[] = {
 static argcheck_T arg2_number_dict_any[] = {arg_number, arg_dict_any};
 static argcheck_T arg2_number_list[] = {arg_number, arg_list_any};
 static argcheck_T arg2_number_string[] = {arg_number, arg_string};
+static argcheck_T arg2_number_buffer[] = {arg_number, arg_buffer};
 static argcheck_T arg2_number_string_or_list[] = {arg_number, arg_string_or_list_any};
 static argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any};
 static argcheck_T arg2_string[] = {arg_string, arg_string};
@@ -2421,6 +2422,8 @@ static funcentry_T global_functions[] =
 			ret_void,	    PROP_FUNC(f_popup_move)},
     {"popup_notification", 2, 2, FEARG_1,   arg2_str_or_nr_or_list_dict,
 			ret_number,	    PROP_FUNC(f_popup_notification)},
+    {"popup_setbuf",	2, 2, FEARG_1,	    arg2_number_buffer,
+			ret_number_bool,    PROP_FUNC(f_popup_setbuf)},
     {"popup_setoptions", 2, 2, FEARG_1,	    arg2_number_dict_any,
 			ret_void,	    PROP_FUNC(f_popup_setoptions)},
     {"popup_settext",	2, 2, FEARG_1,	    arg2_number_string_or_list,
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -2844,6 +2844,54 @@ f_popup_settext(typval_T *argvars, typva
     popup_adjust_position(wp);
 }
 
+/*
+ * popup_setbuf({id}, {bufnr})
+ */
+    void
+f_popup_setbuf(typval_T *argvars, typval_T *rettv UNUSED)
+{
+    int		id;
+    win_T	*wp;
+    buf_T	*buf;
+
+    rettv->v_type = VAR_BOOL;
+    rettv->vval.v_number = VVAL_FALSE;
+
+    if (check_for_number_arg(argvars, 0) == FAIL
+		|| check_for_buffer_arg(argvars, 1) == FAIL)
+	return;
+
+    id = (int)tv_get_number(&argvars[0]);
+    wp = find_popup_win(id);
+    if (wp == NULL)
+	return;
+
+    buf = tv_get_buf_from_arg(&argvars[1]);
+
+    if (buf == NULL)
+	return;
+#ifdef FEAT_TERMINAL
+    if (buf->b_term != NULL && popup_terminal_exists())
+    {
+	emsg(_(e_cannot_open_second_popup_with_terminal));
+	return;
+    }
+#endif
+
+    if (wp->w_buffer != buf)
+    {
+	wp->w_buffer->b_nwindows--;
+	win_init_popup_win(wp, buf);
+	set_local_options_default(wp, FALSE);
+	swap_exists_action = SEA_READONLY;
+	buffer_ensure_loaded(buf);
+	swap_exists_action = SEA_NONE;
+	redraw_win_later(wp, UPD_NOT_VALID);
+	popup_adjust_position(wp);
+    }
+    rettv->vval.v_number = VVAL_TRUE;
+}
+
     static void
 popup_free(win_T *wp)
 {
--- a/src/proto/popupwin.pro
+++ b/src/proto/popupwin.pro
@@ -34,6 +34,7 @@ void f_popup_hide(typval_T *argvars, typ
 void popup_show(win_T *wp);
 void f_popup_show(typval_T *argvars, typval_T *rettv);
 void f_popup_settext(typval_T *argvars, typval_T *rettv);
+void f_popup_setbuf(typval_T *argvars, typval_T *rettv);
 int error_if_popup_window(int also_with_term);
 int popup_close(int id, int force);
 int popup_close_tabpage(tabpage_T *tp, int id, int force);
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_popup_setbuf_01.dump
@@ -0,0 +1,10 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @33|t+0#0000001#ffd7ff255|e|s|t| +0#4040ff13#ffffff0@35
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| 
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_popup_setbuf_02.dump
@@ -0,0 +1,10 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @33|t+0#0000001#ffd7ff255|e|s|t| +0#4040ff13#ffffff0@35
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t|b|u|f|(|p|,| |'|f|o@1|b|a|r|.|t|x|t|'|)| @21|0|,|0|-|1| @8|A|l@1| 
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_popup_setbuf_03.dump
@@ -0,0 +1,10 @@
+|~+0#4040ff13#ffffff0| @73
+|~| @73
+|~| @73
+|~| @33|t+0#0000001#ffd7ff255|e|s|t| +0#4040ff13#ffffff0@35
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|E+0#ffffff16#e000002|1|2@1|0|:| |S|t|r|i|n|g| |o|r| |N|u|m|b|e|r| |r|e|q|u|i|r|e|d| |f|o|r| |a|r|g|u|m|e|n|t| |2| +0#0000000#ffffff0@27
+|P+0#00e0003&|r|e|s@1| |E|N|T|E|R| |o|r| |t|y|p|e| |c|o|m@1|a|n|d| |t|o| |c|o|n|t|i|n|u|e> +0#0000000&@35
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_popup_setbuf_04.dump
@@ -0,0 +1,10 @@
+>*+0#ffffff16#ffd7ff255|h+0#e000002&|e|l|p|.|t|x|t|*+0#ffffff16&| +0#0000001&@5|F|o|r| |V+0#00e0e07&|i|m| |v|e|r|s|i|o|n| |9|.|1|.| +0#0000001&@1|L|a|s|t| |c|h|a|n|g|e|:| |2|0|2|4| |M|a|y| |2|7| @11| +0#0000000#0000001
+| +0#0000001#ffd7ff255@73| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@23|V|I|M| |-| |m|a|i|n| |h|e|l|p| |f|i|l|e| @29| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@72|k| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@5|M|o|v|e| |a|r|o|u|n|d|:| @1|U|s|e| |t|h|e| |c|u|r|s|o|r| |k|e|y|s|,| |o|r| |"|h|"| |t|o| |g|o| |l|e|f|t|,| @11|h| @1| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255|l| @71| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@19|"|j|"| |t|o| |g|o| |d|o|w|n|,| |"|k|"| |t|o| |g|o| |u|p|,| |"|l|"| |t|o| |g|o| |r|i|g|h|t|.| @6|j| +0#0000000#a8a8a8255
+|C+0#0000001#ffd7ff255|l|o|s|e| |t|h|i|s| |w|i|n|d|o|w|:| @1|U|s|e| |"|:|q|<+0#e000e06&|E|n|t|e|r|>|"+0#0000001&|.| @37| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@2|G|e|t| |o|u|t| |o|f| |V|i|m|:| @1|U|s|e| |"|:|q|a|!|<+0#e000e06&|E|n|t|e|r|>|"+0#0000001&| |(|c|a|r|e|f|u|l|,| |a|l@1| |c|h|a|n|g|e|s| |a|r|e| |l|o|s|t|!|)|.| @2| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@73| +0#0000000#a8a8a8255
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_popup_setbuf_05.dump
@@ -0,0 +1,10 @@
+>h+0#e000002#ffffff0|e|l|p|.|t|x|t| +0#0000000&@7|F|o|r| |V+0#00e0e07&|i|m| |v|e|r|s|i|o|n| |9|.|1|.| +0#0000000&@1|L|a|s|t| |c|h|a|n|g|e|:| |2|0|2|4| |M|a|y| |2|7| @12
+@75
+@24|V|I|M| |-| |m|a|i|n| |h|e|l|p| |f|i|l|e| @30
+@73|k| 
+@6|M|o|v|e| |a|r|o|u|n|d|:| @1|U|s|e| |t|h|e| |c|u|r|s|o|r| |k|e| +0#0000001#ffd7ff255|s+0#0000000#ffffff0|,| |o|r| |"|h|"| |t|o| |g|o| |l|e|f|t|,| @11|h| @2
+|l| @73
+|h+3&&|e|l|p|.|t|x|t| |[|H|e|l|p|]|[|R|O|]| @37|1|,|1| @11|T|o|p
+| +0&&@74
+|[+1&&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1
+| +0&&@74
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_popup_setbuf_06.dump
@@ -0,0 +1,10 @@
+>*+0#ffffff16#ffd7ff255|h+0#e000002&|e|l|p|.|t|x|t|*+0#ffffff16&| +0#0000001&@5|F|o|r| |V+0#00e0e07&|i|m| |v|e|r|s|i|o|n| |9|.|1|.| +0#0000001&@1|L|a|s|t| |c|h|a|n|g|e|:| |2|0|2|4| |M|a|y| |2|7| @11| +0#0000000#0000001
+| +0#0000001#ffd7ff255@73| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@23|V|I|M| |-| |m|a|i|n| |h|e|l|p| |f|i|l|e| @29| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@72|k| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@5|M|o|v|e| |a|r|o|u|n|d|:| @1|U|s|e| |t|h|e| |c|u|r|s|o|r| |k|e|y|s|,| |o|r| |"|h|"| |t|o| |g|o| |l|e|f|t|,| @11|h| @1| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255|l| @71| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@19|"|j|"| |t|o| |g|o| |d|o|w|n|,| |"|k|"| |t|o| |g|o| |u|p|,| |"|l|"| |t|o| |g|o| |r|i|g|h|t|.| @6|j| +0#0000000#a8a8a8255
+|C+0#0000001#ffd7ff255|l|o|s|e| |t|h|i|s| |w|i|n|d|o|w|:| @1|U|s|e| |"|:|q|<+0#e000e06&|E|n|t|e|r|>|"+0#0000001&|.| @37| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@2|G|e|t| |o|u|t| |o|f| |V|i|m|:| @1|U|s|e| |"|:|q|a|!|<+0#e000e06&|E|n|t|e|r|>|"+0#0000001&| |(|c|a|r|e|f|u|l|,| |a|l@1| |c|h|a|n|g|e|s| |a|r|e| |l|o|s|t|!|)|.| @2| +0#0000000#a8a8a8255
+| +0#0000001#ffd7ff255@73| +0#0000000#a8a8a8255
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -2499,6 +2499,88 @@ func Test_popup_settext_null()
   call popup_close(id)
 endfunc
 
+func Test_popup_setbuf()
+  CheckScreendump
+
+  let lines =<< trim END
+    let opts = #{wrap: 0}
+    let p = popup_create('test', opts)
+    let buf = bufnr('%')
+  END
+
+  call writefile(lines, 'XtestPopupSetBuf', 'D')
+  let buf = RunVimInTerminal('-S XtestPopupSetBuf', #{rows: 10})
+  call VerifyScreenDump(buf, 'Test_popup_setbuf_01', {})
+
+  " Setting to an non-existing buffer doesn't do anything
+  call term_sendkeys(buf, ":call popup_setbuf(p, 'foobar.txt')\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_setbuf_02', {})
+
+  " Error
+  call term_sendkeys(buf, ":call popup_setbuf(p, ['a','b','c'])\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_setbuf_03', {})
+
+  " Set to help window
+  call term_sendkeys(buf, ":help\<CR>")
+  call term_sendkeys(buf, ":call popup_setbuf(p, 'help.txt')\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_setbuf_04', {})
+
+  " Setting back to original buffer
+  call term_sendkeys(buf, ":call popup_setbuf(p, buf)\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_setbuf_05', {})
+
+  " use method
+  call term_sendkeys(buf, ":echo p->popup_setbuf('help.txt')\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_setbuf_06', {})
+
+  call term_sendkeys(buf, ":echo p->popup_setbuf(buf)\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_setbuf_05', {})
+
+  " clean up
+  call StopVimInTerminal(buf)
+endfunc
+
+func Test_popup_setbuf_terminal()
+  CheckFeature terminal
+
+  " Check Terminal Feature
+  let termbuf = term_start(&shell, #{hidden: 1})
+  " Wait for shell to start
+  call WaitForAssert({-> assert_equal("run", job_status(term_getjob(termbuf)))})
+
+  let popup = popup_create('test', {})
+  call assert_true(popup->popup_setbuf(termbuf))
+  call popup_close(popup)
+
+  let popup1 = popup_create(termbuf, #{minwidth: 40, minheight: 10, border: []})
+
+  let popup = popup_create('test', {})
+  try
+    call assert_fails(call popup_setbuf(popup, termbuf))
+  catch
+  endtry
+  call popup_close(popup)
+  call popup_close(popup1)
+  call assert_equal([], popup_list())
+  " Close the terminal
+  call term_sendkeys(termbuf, "exit\<CR>")
+  " Wait for shell to exit
+  call WaitForAssert({-> assert_equal("dead", job_status(term_getjob(termbuf)))})
+endfunc
+
+func Test_popup_setbuf_null()
+  let id = popup_create('', {})
+  call assert_false(popup_setbuf(id, -1))
+  call popup_close(id)
+
+  let id = popup_create('', {})
+  call assert_true(popup_setbuf(id, test_null_string()))
+  call assert_true(popup_setbuf(id, ''))
+  call popup_close(id)
+
+  call assert_false(popup_setbuf(id, 0))
+endfunc
+
 func Test_popup_hidden()
   new
 
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -3152,6 +3152,11 @@ def Test_popup_settext()
   v9.CheckSourceDefAndScriptFailure(['popup_settext(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1222: String or List required for argument 2'])
 enddef
 
+def Test_popup_setbuf()
+  v9.CheckSourceDefAndScriptFailure(['popup_setbuf([], "abc")'], ['E1013: Argument 1: type mismatch, expected number but got list<any>', 'E1210: Number required for argument 1'])
+  v9.CheckSourceDefAndScriptFailure(['popup_setbuf(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 2'])
+enddef
+
 def Test_popup_show()
   v9.CheckSourceDefAndScriptFailure(['popup_show("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1'])
   v9.CheckSourceDefAndScriptFailure(['popup_show(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1'])
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    500,
+/**/
     499,
 /**/
     498,