diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2025-02-05 23:09:29 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2025-02-05 23:09:29 +0000 |
commit | d5f194ce780c95821a855aca3c19426576d28ae0 (patch) | |
tree | d45f461b19f9118ad2bb1f440a7a08973ad18832 /src/nvim/getchar.c | |
parent | c5d770d311841ea5230426cc4c868e8db27300a8 (diff) | |
parent | 44740e561fc93afe3ebecfd3618bda2d2abeafb0 (diff) | |
download | rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.tar.gz rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.tar.bz2 rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.zip |
Diffstat (limited to 'src/nvim/getchar.c')
-rw-r--r-- | src/nvim/getchar.c | 106 |
1 files changed, 77 insertions, 29 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 82abd2888a..0817d40bb8 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2,7 +2,6 @@ // file, manipulations with redo buffer and stuff buffer. #include <assert.h> -#include <lauxlib.h> #include <limits.h> #include <stdbool.h> #include <stddef.h> @@ -11,6 +10,7 @@ #include <stdlib.h> #include <string.h> +#include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" @@ -29,6 +29,7 @@ #include "nvim/ex_cmds.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" +#include "nvim/ex_getln_defs.h" #include "nvim/garray.h" #include "nvim/garray_defs.h" #include "nvim/getchar.h" @@ -38,6 +39,7 @@ #include "nvim/insexpand.h" #include "nvim/keycodes.h" #include "nvim/lua/executor.h" +#include "nvim/macros_defs.h" #include "nvim/main.h" #include "nvim/mapping.h" #include "nvim/mapping_defs.h" @@ -45,6 +47,7 @@ #include "nvim/mbyte_defs.h" #include "nvim/memline.h" #include "nvim/memory.h" +#include "nvim/memory_defs.h" #include "nvim/message.h" #include "nvim/mouse.h" #include "nvim/move.h" @@ -53,6 +56,7 @@ #include "nvim/ops.h" #include "nvim/option_vars.h" #include "nvim/os/fileio.h" +#include "nvim/os/fileio_defs.h" #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/os_defs.h" @@ -471,7 +475,7 @@ void beep_flush(void) { if (emsg_silent == 0) { flush_buffers(FLUSH_MINIMAL); - vim_beep(BO_ERROR); + vim_beep(kOptBoFlagError); } } @@ -1513,7 +1517,7 @@ int merge_modifiers(int c_arg, int *modifiers) int c = c_arg; if (*modifiers & MOD_MASK_CTRL) { - if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_')) { + if (c >= '@' && c <= 0x7f) { c &= 0x1f; if (c == NUL) { c = K_ZERO; @@ -1862,29 +1866,73 @@ bool char_avail(void) return retval != NUL; } +static int no_reduce_keys = 0; ///< Do not apply modifiers to the key. + /// "getchar()" and "getcharstr()" functions -static void getchar_common(typval_T *argvars, typval_T *rettv) +static void getchar_common(typval_T *argvars, typval_T *rettv, bool allow_number) FUNC_ATTR_NONNULL_ALL { - varnumber_T n; + varnumber_T n = 0; + const int called_emsg_start = called_emsg; bool error = false; + bool simplify = true; + char cursor_flag = NUL; + + if (argvars[0].v_type != VAR_UNKNOWN + && tv_check_for_opt_dict_arg(argvars, 1) == FAIL) { + return; + } + + if (argvars[0].v_type != VAR_UNKNOWN && argvars[1].v_type == VAR_DICT) { + dict_T *d = argvars[1].vval.v_dict; + + if (allow_number) { + allow_number = tv_dict_get_bool(d, "number", true); + } else if (tv_dict_has_key(d, "number")) { + semsg(_(e_invarg2), "number"); + } + + simplify = tv_dict_get_bool(d, "simplify", true); + + const char *cursor_str = tv_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_invargNval), "cursor", cursor_str); + } else { + cursor_flag = cursor_str[0]; + } + } + } + + if (called_emsg != called_emsg_start) { + return; + } + + if (cursor_flag == 'h') { + ui_busy_start(); + } no_mapping++; allow_keys++; + if (!simplify) { + no_reduce_keys++; + } while (true) { - if (msg_col > 0) { - // Position the cursor. Needed after a message that ends in a space. + if (cursor_flag == 'm' || (cursor_flag == NUL && msg_col > 0)) { ui_cursor_goto(msg_row, msg_col); } - if (argvars[0].v_type == VAR_UNKNOWN) { + if (argvars[0].v_type == VAR_UNKNOWN + || (argvars[0].v_type == VAR_NUMBER && argvars[0].vval.v_number == -1)) { // getchar(): blocking wait. // TODO(bfredl): deduplicate shared logic with state_enter ? if (!char_avail()) { // Flush screen updates before blocking. ui_flush(); input_get(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events); - if (!multiqueue_empty(main_loop.events)) { + if (!input_available() && !multiqueue_empty(main_loop.events)) { state_handle_k_event(); continue; } @@ -1912,14 +1960,20 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) } no_mapping--; allow_keys--; + if (!simplify) { + no_reduce_keys--; + } + + if (cursor_flag == 'h') { + ui_busy_stop(); + } set_vim_var_nr(VV_MOUSE_WIN, 0); set_vim_var_nr(VV_MOUSE_WINID, 0); set_vim_var_nr(VV_MOUSE_LNUM, 0); set_vim_var_nr(VV_MOUSE_COL, 0); - rettv->vval.v_number = n; - if (n != 0 && (IS_SPECIAL(n) || mod_mask != 0)) { + if (n != 0 && (!allow_number || IS_SPECIAL(n) || mod_mask != 0)) { char temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1 int i = 0; @@ -1966,35 +2020,23 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) set_vim_var_nr(VV_MOUSE_COL, col + 1); } } + } else if (!allow_number) { + rettv->v_type = VAR_STRING; + } else { + rettv->vval.v_number = n; } } /// "getchar()" function void f_getchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - getchar_common(argvars, rettv); + getchar_common(argvars, rettv, true); } /// "getcharstr()" function void f_getcharstr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - getchar_common(argvars, rettv); - - if (rettv->v_type != VAR_NUMBER) { - return; - } - - char temp[7]; // mbyte-char: 6, NUL: 1 - const varnumber_T n = rettv->vval.v_number; - int i = 0; - - if (n != 0) { - i += utf_char2bytes((int)n, temp); - } - assert(i < 7); - temp[i] = NUL; - rettv->v_type = VAR_STRING; - rettv->vval.v_string = xmemdupz(temp, (size_t)i); + getchar_common(argvars, rettv, false); } /// "getcharmod()" function @@ -2052,6 +2094,12 @@ static bool at_ins_compl_key(void) /// @return the length of the replaced bytes, 0 if nothing changed, -1 for error. static int check_simplify_modifier(int max_offset) { + // We want full modifiers in Terminal mode so that the key can be correctly + // encoded + if ((State & MODE_TERMINAL) || no_reduce_keys > 0) { + return 0; + } + for (int offset = 0; offset < max_offset; offset++) { if (offset + 3 >= typebuf.tb_len) { break; |