patch 9.1.1070: Cannot control cursor positioning of getchar() Commit: https://github.com/vim/vim/commit/edf0f7db28f87611368e158210e58ed30f673098 Author: zeertzjq <zeert...@outlook.com> Date: Sun Feb 2 19:01:01 2025 +0100
patch 9.1.1070: Cannot control cursor positioning of getchar() Problem: Cannot control cursor positioning of getchar(). Solution: Add "cursor" flag to {opts}, with possible values "hide", "keep" and "msg". related: #10603 closes: #16569 Signed-off-by: zeertzjq <zeert...@outlook.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 46c3ba855..39ff14e5f 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -3953,6 +3953,13 @@ getchar([{expr} [, {opts}]]) *getchar()* The optional argument {opts} is a Dict and supports the following items: + cursor A String specifying cursor behavior + when waiting for a character. + "hide": hide the cursor. + "keep": keep current cursor unchanged. + "msg": move cursor to message area. + (default: "msg") + number If |TRUE|, return a Number when getting a single character. If |FALSE|, the return value is always diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 2d48cc974..5338b8b0a 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 9.1. Last change: 2025 Jan 16 +*todo.txt* For Vim version 9.1. Last change: 2025 Feb 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -467,9 +467,6 @@ IDEA: when drawing the text, store the text byte index in ScreenLinesIdx[]. When converting screen column to text position use this. The line number can be obtained from win->w_lines[]. -Version of getchar() that does not move the cursor - #10603 Use a separate -argument for the new flag. - test_arglist func Test_all_not_allowed_from_cmdwin() hangs on MS-Windows. Can we add highlighting to ":echowindow"? diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 010a0cbad..68287d3e2 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -41636,6 +41636,8 @@ Changed~ - add |dist#vim9#Launch()| and |dist#vim9#Open()| to the |vim-script-library| and decouple it from |netrw| - new digraph "APPROACHES THE LIMIT" using ".=" +- Add the optional {opts} |Dict| argument to |getchar()| to control: cursor + behaviour, return type and whether or not to simplify the returned key *added-9.2* Added ~ diff --git a/src/getchar.c b/src/getchar.c index 06f4ad435..83a9861ec 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -2386,9 +2386,11 @@ char_avail(void) static void getchar_common(typval_T *argvars, typval_T *rettv, int allow_number) { - varnumber_T n; + varnumber_T n = 0; + int called_emsg_start = called_emsg; int error = FALSE; int simplify = TRUE; + char_u cursor_flag = 'm'; if ((in_vim9script() && check_for_opt_bool_or_number_arg(argvars, 0) == FAIL) @@ -2399,18 +2401,31 @@ getchar_common(typval_T *argvars, typval_T *rettv, int allow_number) if (argvars[0].v_type != VAR_UNKNOWN && argvars[1].v_type == VAR_DICT) { dict_T *d = argvars[1].vval.v_dict; + char_u *cursor_str; if (allow_number) allow_number = dict_get_bool(d, "number", TRUE); else if (dict_has_key(d, "number")) - { semsg(_(e_invalid_argument_str), "number"); - error = TRUE; - } simplify = dict_get_bool(d, "simplify", TRUE); + + cursor_str = dict_get_string(d, "cursor", FALSE); + if (cursor_str != NULL) + { + if (STRCMP(cursor_str, "hide") != 0 + && STRCMP(cursor_str, "keep") != 0 + && STRCMP(cursor_str, "msg") != 0) + semsg(_(e_invalid_value_for_argument_str_str), "cursor", + cursor_str); + else + cursor_flag = cursor_str[0]; + } } + if (called_emsg != called_emsg_start) + return; + #ifdef MESSAGE_QUEUE // vpeekc() used to check for messages, but that caused problems, invoking // a callback where it was not expected. Some plugins use getchar(1) in a @@ -2418,14 +2433,16 @@ getchar_common(typval_T *argvars, typval_T *rettv, int allow_number) parse_queued_messages(); #endif - // Position the cursor. Needed after a message that ends in a space. - windgoto(msg_row, msg_col); + if (cursor_flag == 'h') + cursor_sleep(); + else if (cursor_flag == 'm') + windgoto(msg_row, msg_col); ++no_mapping; ++allow_keys; if (!simplify) ++no_reduce_keys; - while (!error) + for (;;) { if (argvars[0].v_type == VAR_UNKNOWN || (argvars[0].v_type == VAR_NUMBER @@ -2453,6 +2470,9 @@ getchar_common(typval_T *argvars, typval_T *rettv, int allow_number) if (!simplify) --no_reduce_keys; + if (cursor_flag == 'h') + cursor_unsleep(); + set_vim_var_nr(VV_MOUSE_WIN, 0); set_vim_var_nr(VV_MOUSE_WINID, 0); set_vim_var_nr(VV_MOUSE_LNUM, 0); diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 4672fc0c4..5783c7a8e 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -2628,6 +2628,14 @@ func Test_getchar() call assert_fails('call getchar(1, 1)', 'E1206:') call assert_fails('call getcharstr(1, 1)', 'E1206:') + call assert_fails('call getchar(1, #{cursor: "foo"})', 'E475:') + call assert_fails('call getcharstr(1, #{cursor: "foo"})', 'E475:') + call assert_fails('call getchar(1, #{cursor: 0z})', 'E976:') + call assert_fails('call getcharstr(1, #{cursor: 0z})', 'E976:') + call assert_fails('call getchar(1, #{simplify: 0z})', 'E974:') + call assert_fails('call getcharstr(1, #{simplify: 0z})', 'E974:') + call assert_fails('call getchar(1, #{number: []})', 'E745:') + call assert_fails('call getchar(1, #{number: {}})', 'E728:') call assert_fails('call getcharstr(1, #{number: v:true})', 'E475:') call assert_fails('call getcharstr(1, #{number: v:false})', 'E475:') @@ -2646,6 +2654,57 @@ func Test_getchar() enew! endfunc +func Test_getchar_cursor_position() + CheckRunVimInTerminal + + let lines =<< trim END + call setline(1, ['foobar', 'foobar', 'foobar']) + call cursor(3, 6) + nnoremap <F1> <Cmd>echo 1234<Bar>call getchar()<CR> + nnoremap <F2> <Cmd>call getchar()<CR> + nnoremap <F3> <Cmd>call getchar(-1, {})<CR> + nnoremap <F4> <Cmd>call getchar(-1, #{cursor: 'msg'})<CR> + nnoremap <F5> <Cmd>call getchar(-1, #{cursor: 'keep'})<CR> + nnoremap <F6> <Cmd>call getchar(-1, #{cursor: 'hide'})<CR> + END + call writefile(lines, 'XgetcharCursorPos', 'D') + let buf = RunVimInTerminal('-S XgetcharCursorPos', {'rows': 6}) + call WaitForAssert({-> assert_equal([3, 6], term_getcursor(buf)[0:1])}) + + call term_sendkeys(buf, "\<F1>") + call WaitForAssert({-> assert_equal([6, 5], term_getcursor(buf)[0:1])}) + call assert_true(term_getcursor(buf)[2].visible) + call term_sendkeys(buf, 'a') + call WaitForAssert({-> assert_equal([3, 6], term_getcursor(buf)[0:1])}) + call assert_true(term_getcursor(buf)[2].visible) + + for key in ["\<F2>", "\<F3>", "\<F4>"] + call term_sendkeys(buf, key) + call WaitForAssert({-> assert_equal([6, 1], term_getcursor(buf)[0:1])}) + call assert_true(term_getcursor(buf)[2].visible) + call term_sendkeys(buf, 'a') + call WaitForAssert({-> assert_equal([3, 6], term_getcursor(buf)[0:1])}) + call assert_true(term_getcursor(buf)[2].visible) + endfor + + call term_sendkeys(buf, "\<F5>") + call TermWait(buf, 50) + call assert_equal([3, 6], term_getcursor(buf)[0:1]) + call assert_true(term_getcursor(buf)[2].visible) + call term_sendkeys(buf, 'a') + call TermWait(buf, 50) + call assert_equal([3, 6], term_getcursor(buf)[0:1]) + call assert_true(term_getcursor(buf)[2].visible) + + call term_sendkeys(buf, "\<F6>") + call WaitForAssert({-> assert_false(term_getcursor(buf)[2].visible)}) + call term_sendkeys(buf, 'a') + call WaitForAssert({-> assert_true(term_getcursor(buf)[2].visible)}) + call assert_equal([3, 6], term_getcursor(buf)[0:1]) + + call StopVimInTerminal(buf) +endfunc + func Test_libcall_libcallnr() CheckFeature libcall diff --git a/src/version.c b/src/version.c index f9d99a5dc..5ed5bcf31 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1070, /**/ 1069, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1teeUp-001KuT-Ut%40256bit.org.