To: vim_dev@googlegroups.com Subject: Patch 8.2.1588 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1588 Problem: Cannot read back the prompt of a prompt buffer. Solution: Add prompt_getprompt(). (Ben Jackson, closes #6851) Files: runtime/doc/channel.txt, runtime/doc/eval.txt, runtime/doc/usr_41.txt, src/channel.c, src/edit.c, src/evalfunc.c, src/proto/channel.pro, src/proto/edit.pro, src/testdir/test_prompt_buffer.vim *** ../vim-8.2.1587/runtime/doc/channel.txt 2020-04-12 17:52:49.421492420 +0200 --- runtime/doc/channel.txt 2020-09-04 16:23:15.259384412 +0200 *************** *** 608,613 **** --- 608,617 ---- after every message, on Unix you can use "tail -f" to see what is going on in real time. + To enable the log very early, to see what is received from a + terminal during startup, use |--cmd|: > + vim --cmd "call ch_logfile('logfile', 'w')" + < This function is not available in the |sandbox|. NOTE: the channel communication is stored in the file, be aware that this may contain confidential and privacy sensitive *************** *** 1235,1242 **** - Use a terminal window. This works well if what you type goes directly to the job and the job output is directly displayed in the window. See |terminal-window|. ! - Use a prompt window. This works well when entering a line for the job in Vim ! while displaying (possibly filtered) output from the job. A prompt buffer is created by setting 'buftype' to "prompt". You would normally only do that in a newly created buffer. --- 1239,1246 ---- - Use a terminal window. This works well if what you type goes directly to the job and the job output is directly displayed in the window. See |terminal-window|. ! - Use a window with a prompt buffer. This works well when entering a line for ! the job in Vim while displaying (possibly filtered) output from the job. A prompt buffer is created by setting 'buftype' to "prompt". You would normally only do that in a newly created buffer. *************** *** 1256,1265 **** mode, use `:startinsert` if you want to enter Insert mode, so that the user can start typing a line. ! The text of the prompt can be set with the |prompt_setprompt()| function. The user can go to Normal mode and navigate through the buffer. This can be ! useful see older output or copy text. The CTRL-W key can be used to start a window command, such as CTRL-W w to switch to the next window. This also works in Insert mode (use Shift-CTRL-W --- 1260,1271 ---- mode, use `:startinsert` if you want to enter Insert mode, so that the user can start typing a line. ! The text of the prompt can be set with the |prompt_setprompt()| function. If ! no prompt is set with |prompt_setprompt()|, "% " is used. You can get the ! effective prompt text for a buffer, with |prompt_getprompt()|. The user can go to Normal mode and navigate through the buffer. This can be ! useful to see older output or copy text. The CTRL-W key can be used to start a window command, such as CTRL-W w to switch to the next window. This also works in Insert mode (use Shift-CTRL-W *************** *** 1270,1274 **** --- 1276,1321 ---- the cursor to the last line. "A" will move to the end of the line, "I" to the start of the line. + Here is an example for Unix. It starts a shell in the background and prompts + for the next shell command. Output from the shell is displayed above the + prompt. > + + " Create a channel log so we can see what happens. + call ch_logfile('logfile', 'w') + + " Function handling a line of text has been typed. + func TextEntered(text) + " Send the text to a shell with Enter appended. + call ch_sendraw(g:shell_job, a:text .. "\n") + endfunc + + " Function handling output from the shell: Added above the prompt. + func GotOutput(channel, msg) + call append(line("$") - 1, "- " . a:msg) + endfunc + + " Function handling the shell exist: close the window. + func JobExit(job, status) + quit! + endfunc + + " Start a shell in the background. + let shell_job = job_start(["/bin/sh"], #{ + \ out_cb: function('GotOutput'), + \ err_cb: function('GotOutput'), + \ exit_cb: function('JobExit'), + \ }) + let shell_ch = job_getchannel(shell_job) + + new + set buftype=prompt + let buf = bufnr('') + call prompt_setcallback(buf, function("TextEntered")) + eval prompt_setprompt(buf, "shell command: ") + + " start accepting shell commands + startinsert + < + vim:tw=78:ts=8:noet:ft=help:norl: *** ../vim-8.2.1587/runtime/doc/eval.txt 2020-08-30 15:49:12.158736328 +0200 --- runtime/doc/eval.txt 2020-09-04 16:23:15.259384412 +0200 *************** *** 2671,2676 **** --- 2684,2690 ---- pow({x}, {y}) Float {x} to the power of {y} prevnonblank({lnum}) Number line nr of non-blank line <= {lnum} printf({fmt}, {expr1}...) String format text + prompt_getprompt({buf}) String get prompt text prompt_setcallback({buf}, {expr}) none set prompt callback function prompt_setinterrupt({buf}, {text}) none set prompt interrupt function prompt_setprompt({buf}, {text}) none set prompt text *************** *** 7789,7794 **** --- 7836,7852 ---- arguments an error is given. Up to 18 arguments can be used. + prompt_getprompt({buf}) *prompt_getprompt()* + Returns the effective prompt text for buffer {buf}. {buf} can + be a buffer name or number. |prompt-buffer|. + + If the buffer doesn't exist or isn't a prompt buffer, an empty + string is returned. + + Can also be used as a |method|: > + GetBuffer()->prompt_getprompt() + + prompt_setcallback({buf}, {expr}) *prompt_setcallback()* Set prompt callback for buffer {buf} to {expr}. When {expr} is an empty string the callback is removed. This has only *************** *** 7844,7850 **** Can also be used as a |method|: > GetBuffer()->prompt_setprompt('command: ') ! prop_ functions are documented here: |text-prop-functions|. pum_getpos() *pum_getpos()* If the popup menu (see |ins-completion-menu|) is not visible, --- 7902,7908 ---- Can also be used as a |method|: > GetBuffer()->prompt_setprompt('command: ') ! prop_ functions are documented here: |text-prop-functions| pum_getpos() *pum_getpos()* If the popup menu (see |ins-completion-menu|) is not visible, *** ../vim-8.2.1587/runtime/doc/usr_41.txt 2020-08-30 15:49:12.158736328 +0200 --- runtime/doc/usr_41.txt 2020-09-04 16:23:15.259384412 +0200 *************** *** 1110,1115 **** --- 1118,1124 ---- settagstack() modify the tag stack of a window Prompt Buffer: *promptbuffer-functions* + prompt_getprompt() get the effective prompt text for a buffer prompt_setcallback() set prompt callback for a buffer prompt_setinterrupt() set interrupt callback for a buffer prompt_setprompt() set the prompt text for a buffer *** ../vim-8.2.1587/src/channel.c 2020-08-30 17:24:34.277662302 +0200 --- src/channel.c 2020-09-04 16:23:15.259384412 +0200 *************** *** 6368,6373 **** --- 6368,6396 ---- set_callback(&buf->b_prompt_interrupt, &callback); } + + /* + * "prompt_getprompt({buffer})" function + */ + void + f_prompt_getprompt(typval_T *argvars, typval_T *rettv) + { + buf_T *buf; + + // return an empty string by default, e.g. it's not a prompt buffer + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + + buf = tv_get_buf_from_arg(&argvars[0]); + if (buf == NULL) + return; + + if (!bt_prompt(buf)) + return; + + rettv->vval.v_string = vim_strsave(buf_prompt_text(buf)); + } + /* * "prompt_setprompt({buffer}, {text})" function */ *** ../vim-8.2.1587/src/edit.c 2020-06-06 22:36:20.464116743 +0200 --- src/edit.c 2020-09-04 16:23:15.259384412 +0200 *************** *** 1682,1697 **** #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) /* * Return the effective prompt for the current buffer. */ char_u * prompt_text(void) { ! if (curbuf->b_prompt_text == NULL) ! return (char_u *)"% "; ! return curbuf->b_prompt_text; } /* * Prepare for prompt mode: Make sure the last line has the prompt text. * Move the cursor to this line. --- 1682,1707 ---- #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) /* + * Return the effective prompt for the specified buffer. + */ + char_u * + buf_prompt_text(buf_T* buf) + { + if (buf->b_prompt_text == NULL) + return (char_u *)"% "; + return buf->b_prompt_text; + } + + /* * Return the effective prompt for the current buffer. */ char_u * prompt_text(void) { ! return buf_prompt_text(curbuf); } + /* * Prepare for prompt mode: Make sure the last line has the prompt text. * Move the cursor to this line. *** ../vim-8.2.1587/src/evalfunc.c 2020-09-02 22:25:31.717607993 +0200 --- src/evalfunc.c 2020-09-04 16:23:15.263384403 +0200 *************** *** 806,811 **** --- 806,812 ---- {"pow", 2, 2, FEARG_1, ret_float, FLOAT_FUNC(f_pow)}, {"prevnonblank", 1, 1, FEARG_1, ret_number, f_prevnonblank}, {"printf", 1, 19, FEARG_2, ret_string, f_printf}, + {"prompt_getprompt", 1, 1, FEARG_1, ret_string, JOB_FUNC(f_prompt_getprompt)}, {"prompt_setcallback", 2, 2, FEARG_1, ret_void, JOB_FUNC(f_prompt_setcallback)}, {"prompt_setinterrupt", 2, 2, FEARG_1,ret_void, JOB_FUNC(f_prompt_setinterrupt)}, {"prompt_setprompt", 2, 2, FEARG_1, ret_void, JOB_FUNC(f_prompt_setprompt)}, *** ../vim-8.2.1587/src/proto/channel.pro 2020-04-12 17:52:49.429492390 +0200 --- src/proto/channel.pro 2020-09-04 16:23:15.263384403 +0200 *************** *** 56,61 **** --- 56,62 ---- int job_stop(job_T *job, typval_T *argvars, char *type); void invoke_prompt_callback(void); int invoke_prompt_interrupt(void); + void f_prompt_getprompt(typval_T *argvars, typval_T *rettv); void f_prompt_setcallback(typval_T *argvars, typval_T *rettv); void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv); void f_prompt_setprompt(typval_T *argvars, typval_T *rettv); *** ../vim-8.2.1587/src/proto/edit.pro 2020-05-01 14:26:17.132949262 +0200 --- src/proto/edit.pro 2020-09-04 16:23:15.263384403 +0200 *************** *** 4,9 **** --- 4,10 ---- void ins_redraw(int ready); int decodeModifyOtherKeys(int c); void edit_putchar(int c, int highlight); + char_u *buf_prompt_text(buf_T* buf); char_u *prompt_text(void); int prompt_curpos_editable(void); void edit_unputchar(void); *** ../vim-8.2.1587/src/testdir/test_prompt_buffer.vim 2020-08-12 18:50:31.883655785 +0200 --- src/testdir/test_prompt_buffer.vim 2020-09-04 16:23:15.263384403 +0200 *************** *** 148,151 **** --- 148,185 ---- call assert_equal(0, prompt_setprompt([], '')) endfunc + func Test_prompt_buffer_getbufinfo() + new + call assert_equal('', prompt_getprompt('%')) + call assert_equal('', prompt_getprompt(bufnr('%'))) + let another_buffer = bufnr('%') + + set buftype=prompt + call assert_equal('% ', prompt_getprompt('%')) + call prompt_setprompt( bufnr( '%' ), 'This is a test: ' ) + call assert_equal('This is a test: ', prompt_getprompt('%')) + + call prompt_setprompt( bufnr( '%' ), '' ) + call assert_equal('', '%'->prompt_getprompt()) + + call prompt_setprompt( bufnr( '%' ), 'Another: ' ) + call assert_equal('Another: ', prompt_getprompt('%')) + let another = bufnr('%') + + new + + call assert_equal('', prompt_getprompt('%')) + call assert_equal('Another: ', prompt_getprompt(another)) + + " Doesn't exist + let buffers_before = len( getbufinfo() ) + call assert_equal('', prompt_getprompt( bufnr('$') + 1)) + call assert_equal(buffers_before, len( getbufinfo())) + + " invalid type + call assert_fails('call prompt_getprompt({})', 'E728:') + + %bwipe! + endfunc + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.1587/src/version.c 2020-09-04 15:37:27.865546317 +0200 --- src/version.c 2020-09-04 16:24:32.255203937 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 1588, /**/ -- Individualists unite! /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///