diff options
| author | zeertzjq <zeertzjq@outlook.com> | 2022-06-23 21:17:11 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-23 21:17:11 +0800 |
| commit | 7718b758461265d8966468c104ce5454538471e2 (patch) | |
| tree | c58cec1a66defb6c84c113cb76c03e759db47feb | |
| parent | 05ca14a8810555495c309b8add3002773c77123d (diff) | |
| download | rneovim-7718b758461265d8966468c104ce5454538471e2.tar.gz rneovim-7718b758461265d8966468c104ce5454538471e2.tar.bz2 rneovim-7718b758461265d8966468c104ce5454538471e2.zip | |
refactor: move some mapping-related code to a separate file (#19061)
This marks the following Vim patches as ported:
vim-patch:8.1.1785: map functionality mixed with character input
Problem: Map functionality mixed with character input.
Solution: Move the map functionality to a separate file. (Yegappan
Lakshmanan, closes vim/vim#4740) Graduate the +localmap feature.
https://github.com/vim/vim/commit/b66bab381c8ba71fd6e92327d1d34c6f8a65f2a7
vim-patch:8.2.3643: header for source file is outdated
Problem: Header for source file is outdated.
Solution: Make the header more accurate. (closes vim/vim#9186)
https://github.com/vim/vim/commit/a3f83feb63eae5464a620ae793c002eb45f7a838
Also cherry-pick a change for <unique> mappings from patch 8.2.0807.
Rename map_clear_mode() to do_mapclear().
| -rwxr-xr-x | scripts/vim-patch.sh | 4 | ||||
| -rw-r--r-- | src/nvim/api/buffer.c | 1 | ||||
| -rw-r--r-- | src/nvim/api/private/helpers.c | 189 | ||||
| -rw-r--r-- | src/nvim/api/vim.c | 1 | ||||
| -rw-r--r-- | src/nvim/buffer.c | 1 | ||||
| -rw-r--r-- | src/nvim/digraph.c | 1 | ||||
| -rw-r--r-- | src/nvim/edit.c | 29 | ||||
| -rw-r--r-- | src/nvim/eval.c | 51 | ||||
| -rw-r--r-- | src/nvim/eval/funcs.c | 96 | ||||
| -rw-r--r-- | src/nvim/ex_docmd.c | 57 | ||||
| -rw-r--r-- | src/nvim/ex_getln.c | 1 | ||||
| -rw-r--r-- | src/nvim/ex_session.c | 2 | ||||
| -rw-r--r-- | src/nvim/getchar.c | 2034 | ||||
| -rw-r--r-- | src/nvim/getchar.h | 44 | ||||
| -rw-r--r-- | src/nvim/keycodes.c | 72 | ||||
| -rw-r--r-- | src/nvim/main.c | 2 | ||||
| -rw-r--r-- | src/nvim/mapping.c | 2553 | ||||
| -rw-r--r-- | src/nvim/mapping.h | 54 | ||||
| -rw-r--r-- | src/nvim/normal.c | 1 | ||||
| -rw-r--r-- | src/nvim/option.c | 170 | ||||
| -rw-r--r-- | src/nvim/window.c | 1 |
21 files changed, 2705 insertions, 2659 deletions
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 472b79cbf4..d5424f51ab 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -233,6 +233,10 @@ preprocess_patch() { LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/userfunc\.c/\1\/eval\/userfunc\.c/g' \ "$file" > "$file".tmp && mv "$file".tmp "$file" + # Rename map.c to mapping.c + LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/map\(\.[ch]\)/\1\/mapping\2/g' \ + "$file" > "$file".tmp && mv "$file".tmp "$file" + # Rename session.c to ex_session.c LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/session\(\.[ch]\)/\1\/ex_session\2/g' \ "$file" > "$file".tmp && mv "$file".tmp "$file" diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 9dc95de243..0810d155f6 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -22,6 +22,7 @@ #include "nvim/ex_docmd.h" #include "nvim/extmark.h" #include "nvim/lua/executor.h" +#include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/memline.h" #include "nvim/memory.h" diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 9cadef0385..436bcd5212 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -21,7 +21,6 @@ #include "nvim/ex_cmds_defs.h" #include "nvim/extmark.h" #include "nvim/fileio.h" -#include "nvim/getchar.h" #include "nvim/highlight_group.h" #include "nvim/lib/kvec.h" #include "nvim/lua/executor.h" @@ -441,142 +440,6 @@ Array string_to_array(const String input, bool crlf) return ret; } -/// Set, tweak, or remove a mapping in a mode. Acts as the implementation for -/// functions like @ref nvim_buf_set_keymap. -/// -/// Arguments are handled like @ref nvim_set_keymap unless noted. -/// @param buffer Buffer handle for a specific buffer, or 0 for the current -/// buffer, or -1 to signify global behavior ("all buffers") -/// @param is_unmap When true, removes the mapping that matches {lhs}. -void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mode, String lhs, - String rhs, Dict(keymap) *opts, Error *err) -{ - LuaRef lua_funcref = LUA_NOREF; - bool global = (buffer == -1); - if (global) { - buffer = 0; - } - buf_T *target_buf = find_buffer_by_handle(buffer, err); - - if (!target_buf) { - return; - } - - const sctx_T save_current_sctx = api_set_sctx(channel_id); - - if (opts != NULL && opts->callback.type == kObjectTypeLuaRef) { - lua_funcref = opts->callback.data.luaref; - opts->callback.data.luaref = LUA_NOREF; - } - MapArguments parsed_args = MAP_ARGUMENTS_INIT; - if (opts) { -#define KEY_TO_BOOL(name) \ - parsed_args.name = api_object_to_bool(opts->name, #name, false, err); \ - if (ERROR_SET(err)) { \ - goto fail_and_free; \ - } - - KEY_TO_BOOL(nowait); - KEY_TO_BOOL(noremap); - KEY_TO_BOOL(silent); - KEY_TO_BOOL(script); - KEY_TO_BOOL(expr); - KEY_TO_BOOL(unique); -#undef KEY_TO_BOOL - } - parsed_args.buffer = !global; - - set_maparg_lhs_rhs(lhs.data, lhs.size, - rhs.data, rhs.size, lua_funcref, - CPO_TO_CPO_FLAGS, &parsed_args); - if (opts != NULL && opts->desc.type == kObjectTypeString) { - parsed_args.desc = string_to_cstr(opts->desc.data.string); - } else { - parsed_args.desc = NULL; - } - if (parsed_args.lhs_len > MAXMAPLEN || parsed_args.alt_lhs_len > MAXMAPLEN) { - api_set_error(err, kErrorTypeValidation, "LHS exceeds maximum map length: %s", lhs.data); - goto fail_and_free; - } - - if (mode.size > 1) { - api_set_error(err, kErrorTypeValidation, "Shortname is too long: %s", mode.data); - goto fail_and_free; - } - int mode_val; // integer value of the mapping mode, to be passed to do_map() - char *p = (mode.size) ? mode.data : "m"; - if (STRNCMP(p, "!", 2) == 0) { - mode_val = get_map_mode(&p, true); // mapmode-ic - } else { - mode_val = get_map_mode(&p, false); - if (mode_val == (MODE_VISUAL | MODE_SELECT | MODE_NORMAL | MODE_OP_PENDING) && mode.size > 0) { - // get_map_mode() treats unrecognized mode shortnames as ":map". - // This is an error unless the given shortname was empty string "". - api_set_error(err, kErrorTypeValidation, "Invalid mode shortname: \"%s\"", p); - goto fail_and_free; - } - } - - if (parsed_args.lhs_len == 0) { - api_set_error(err, kErrorTypeValidation, "Invalid (empty) LHS"); - goto fail_and_free; - } - - bool is_noremap = parsed_args.noremap; - assert(!(is_unmap && is_noremap)); - - if (!is_unmap && lua_funcref == LUA_NOREF - && (parsed_args.rhs_len == 0 && !parsed_args.rhs_is_noop)) { - if (rhs.size == 0) { // assume that the user wants RHS to be a <Nop> - parsed_args.rhs_is_noop = true; - } else { - abort(); // should never happen - } - } else if (is_unmap && (parsed_args.rhs_len || parsed_args.rhs_lua != LUA_NOREF)) { - if (parsed_args.rhs_len) { - api_set_error(err, kErrorTypeValidation, - "Gave nonempty RHS in unmap command: %s", parsed_args.rhs); - } else { - api_set_error(err, kErrorTypeValidation, "Gave nonempty RHS for unmap"); - } - goto fail_and_free; - } - - // buf_do_map() reads noremap/unmap as its own argument. - int maptype_val = 0; - if (is_unmap) { - maptype_val = 1; - } else if (is_noremap) { - maptype_val = 2; - } - - switch (buf_do_map(maptype_val, &parsed_args, mode_val, 0, target_buf)) { - case 0: - break; - case 1: - api_set_error(err, kErrorTypeException, (char *)e_invarg, 0); - goto fail_and_free; - case 2: - api_set_error(err, kErrorTypeException, (char *)e_nomap, 0); - goto fail_and_free; - case 5: - api_set_error(err, kErrorTypeException, - "E227: mapping already exists for %s", parsed_args.lhs); - goto fail_and_free; - default: - assert(false && "Unrecognized return code!"); - goto fail_and_free; - } // switch - - parsed_args.rhs_lua = LUA_NOREF; // don't clear ref on success -fail_and_free: - current_sctx = save_current_sctx; - NLUA_CLEAR_REF(parsed_args.rhs_lua); - xfree(parsed_args.rhs); - xfree(parsed_args.orig_rhs); - XFREE_CLEAR(parsed_args.desc); -} - /// Collects `n` buffer lines into array `l`, optionally replacing newlines /// with NUL. /// @@ -930,58 +793,6 @@ void api_set_error(Error *err, ErrorType errType, const char *format, ...) err->type = errType; } -/// Get an array containing dictionaries describing mappings -/// based on mode and buffer id -/// -/// @param mode The abbreviation for the mode -/// @param buf The buffer to get the mapping array. NULL for global -/// @param from_lua Whether it is called from internal lua api. -/// @returns Array of maparg()-like dictionaries describing mappings -ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua) -{ - Array mappings = ARRAY_DICT_INIT; - dict_T *const dict = tv_dict_alloc(); - - // Convert the string mode to the integer mode - // that is stored within each mapblock - char *p = mode.data; - int int_mode = get_map_mode(&p, 0); - - // Determine the desired buffer value - long buffer_value = (buf == NULL) ? 0 : buf->handle; - - for (int i = 0; i < MAX_MAPHASH; i++) { - for (const mapblock_T *current_maphash = get_maphash(i, buf); - current_maphash; - current_maphash = current_maphash->m_next) { - if (current_maphash->m_simplified) { - continue; - } - // Check for correct mode - if (int_mode & current_maphash->m_mode) { - mapblock_fill_dict(dict, current_maphash, buffer_value, false); - Object api_dict = vim_to_object((typval_T[]) { { .v_type = VAR_DICT, - .vval.v_dict = dict } }); - if (from_lua) { - Dictionary d = api_dict.data.dictionary; - for (size_t j = 0; j < d.size; j++) { - if (strequal("callback", d.items[j].key.data)) { - d.items[j].value.type = kObjectTypeLuaRef; - d.items[j].value.data.luaref = api_new_luaref((LuaRef)d.items[j].value.data.integer); - break; - } - } - } - ADD(mappings, api_dict); - tv_dict_clear(dict); - } - } - } - tv_dict_free(dict); - - return mappings; -} - /// Force obj to bool. /// If it fails, returns false and sets err /// @param obj The object to coerce to a boolean diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index b7df1398f5..c5881dbc5f 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -38,6 +38,7 @@ #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/lua/executor.h" +#include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/memline.h" #include "nvim/memory.h" diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index f13f6e35ea..85e34e910d 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -53,6 +53,7 @@ #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/main.h" +#include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memory.h" diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index b461082be0..99e99a8a9e 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -18,6 +18,7 @@ #include "nvim/ex_getln.h" #include "nvim/garray.h" #include "nvim/getchar.h" +#include "nvim/mapping.h" #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 8f7ba03b14..e0717ef8bc 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -31,6 +31,7 @@ #include "nvim/indent_c.h" #include "nvim/keycodes.h" #include "nvim/main.h" +#include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" @@ -6768,34 +6769,6 @@ void free_last_insert(void) #endif -/// Add character "c" to buffer "s" -/// -/// Escapes the special meaning of K_SPECIAL, handles multi-byte -/// characters. -/// -/// @param[in] c Character to add. -/// @param[out] s Buffer to add to. Must have at least MB_MAXBYTES + 1 bytes. -/// -/// @return Pointer to after the added bytes. -char_u *add_char2buf(int c, char_u *s) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT -{ - char_u temp[MB_MAXBYTES + 1]; - const int len = utf_char2bytes(c, (char *)temp); - for (int i = 0; i < len; i++) { - c = (uint8_t)temp[i]; - // Need to escape K_SPECIAL like in the typeahead buffer. - if (c == K_SPECIAL) { - *s++ = K_SPECIAL; - *s++ = KS_SPECIAL; - *s++ = KE_FILLER; - } else { - *s++ = (char_u)c; - } - } - return s; -} - /* * move cursor to start of line * if flags & BL_WHITE move to first non-white diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 43d6ed558f..be2df9488e 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6791,57 +6791,6 @@ char **tv_to_argv(typval_T *cmd_tv, const char **cmd, bool *executable) return argv; } -/// Fill a dictionary with all applicable maparg() like dictionaries -/// -/// @param dict The dictionary to be filled -/// @param mp The maphash that contains the mapping information -/// @param buffer_value The "buffer" value -/// @param compatible True for compatible with old maparg() dict -void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, long buffer_value, - bool compatible) - FUNC_ATTR_NONNULL_ALL -{ - char *const lhs = str2special_save((const char *)mp->m_keys, - compatible, !compatible); - char *const mapmode = map_mode_to_chars(mp->m_mode); - varnumber_T noremap_value; - - if (compatible) { - // Keep old compatible behavior - // This is unable to determine whether a mapping is a <script> mapping - noremap_value = !!mp->m_noremap; - } else { - // Distinguish between <script> mapping - // If it's not a <script> mapping, check if it's a noremap - noremap_value = mp->m_noremap == REMAP_SCRIPT ? 2 : !!mp->m_noremap; - } - - if (mp->m_luaref != LUA_NOREF) { - tv_dict_add_nr(dict, S_LEN("callback"), mp->m_luaref); - } else { - if (compatible) { - tv_dict_add_str(dict, S_LEN("rhs"), (const char *)mp->m_orig_str); - } else { - tv_dict_add_allocated_str(dict, S_LEN("rhs"), - str2special_save((const char *)mp->m_str, false, - true)); - } - } - if (mp->m_desc != NULL) { - tv_dict_add_allocated_str(dict, S_LEN("desc"), xstrdup(mp->m_desc)); - } - tv_dict_add_allocated_str(dict, S_LEN("lhs"), lhs); - tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value); - tv_dict_add_nr(dict, S_LEN("script"), mp->m_noremap == REMAP_SCRIPT ? 1 : 0); - tv_dict_add_nr(dict, S_LEN("expr"), mp->m_expr ? 1 : 0); - tv_dict_add_nr(dict, S_LEN("silent"), mp->m_silent ? 1 : 0); - tv_dict_add_nr(dict, S_LEN("sid"), (varnumber_T)mp->m_script_ctx.sc_sid); - tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)mp->m_script_ctx.sc_lnum); - tv_dict_add_nr(dict, S_LEN("buffer"), (varnumber_T)buffer_value); - tv_dict_add_nr(dict, S_LEN("nowait"), mp->m_nowait ? 1 : 0); - tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode); -} - void return_register(int regname, typval_T *rettv) { char buf[2] = { (char)regname, 0 }; diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8e49d1b9a8..f7d6b016fd 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -38,6 +38,7 @@ #include "nvim/input.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" +#include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/match.h" #include "nvim/math.h" @@ -5647,89 +5648,6 @@ static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = (varnumber_T)time(NULL); } -static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) -{ - char *keys_buf = NULL; - char_u *alt_keys_buf = NULL; - bool did_simplify = false; - char_u *rhs; - LuaRef rhs_lua; - int mode; - int abbr = FALSE; - int get_dict = FALSE; - mapblock_T *mp; - int buffer_local; - int flags = REPTERM_FROM_PART | REPTERM_DO_LT; - - // Return empty string for failure. - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - - char *keys = (char *)tv_get_string(&argvars[0]); - if (*keys == NUL) { - return; - } - - char buf[NUMBUFLEN]; - const char *which; - if (argvars[1].v_type != VAR_UNKNOWN) { - which = tv_get_string_buf_chk(&argvars[1], buf); - if (argvars[2].v_type != VAR_UNKNOWN) { - abbr = tv_get_number(&argvars[2]); - if (argvars[3].v_type != VAR_UNKNOWN) { - get_dict = tv_get_number(&argvars[3]); - } - } - } else { - which = ""; - } - if (which == NULL) { - return; - } - - mode = get_map_mode((char **)&which, 0); - - char_u *keys_simplified - = (char_u *)replace_termcodes(keys, - STRLEN(keys), &keys_buf, flags, &did_simplify, - CPO_TO_CPO_FLAGS); - rhs = check_map(keys_simplified, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); - if (did_simplify) { - // When the lhs is being simplified the not-simplified keys are - // preferred for printing, like in do_map(). - (void)replace_termcodes(keys, - STRLEN(keys), - (char **)&alt_keys_buf, flags | REPTERM_NO_SIMPLIFY, NULL, - CPO_TO_CPO_FLAGS); - rhs = check_map(alt_keys_buf, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); - } - - if (!get_dict) { - // Return a string. - if (rhs != NULL) { - if (*rhs == NUL) { - rettv->vval.v_string = xstrdup("<Nop>"); - } else { - rettv->vval.v_string = str2special_save((char *)rhs, false, false); - } - } else if (rhs_lua != LUA_NOREF) { - size_t msglen = 100; - char *msg = (char *)xmalloc(msglen); - snprintf(msg, msglen, "<Lua function %d>", mp->m_luaref); - rettv->vval.v_string = msg; - } - } else { - tv_dict_alloc_ret(rettv); - if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) { - // Return a dictionary. - mapblock_fill_dict(rettv->vval.v_dict, mp, buffer_local, true); - } - } - - xfree(keys_buf); - xfree(alt_keys_buf); -} - /// luaeval() function implementation static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL @@ -5748,18 +5666,6 @@ static void f_map(typval_T *argvars, typval_T *rettv, FunPtr fptr) filter_map(argvars, rettv, TRUE); } -/// "maparg()" function -static void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - get_maparg(argvars, rettv, TRUE); -} - -/// "mapcheck()" function -static void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - get_maparg(argvars, rettv, FALSE); -} - static void find_some_match(typval_T *const argvars, typval_T *const rettv, const SomeMatchType type) { diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 49db5c3716..53a05ccc04 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -44,6 +44,7 @@ #include "nvim/keycodes.h" #include "nvim/lua/executor.h" #include "nvim/main.h" +#include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/match.h" #include "nvim/mbyte.h" @@ -5256,45 +5257,6 @@ theend: return tab_number; } -/// ":abbreviate" and friends. -static void ex_abbreviate(exarg_T *eap) -{ - do_exmap(eap, TRUE); // almost the same as mapping -} - -/// ":map" and friends. -static void ex_map(exarg_T *eap) -{ - /* - * If we are sourcing .exrc or .vimrc in current directory we - * print the mappings for security reasons. - */ - if (secure) { - secure = 2; - msg_outtrans((char_u *)eap->cmd); - msg_putchar('\n'); - } - do_exmap(eap, FALSE); -} - -/// ":unmap" and friends. -static void ex_unmap(exarg_T *eap) -{ - do_exmap(eap, FALSE); -} - -/// ":mapclear" and friends. -static void ex_mapclear(exarg_T *eap) -{ - map_clear_mode((char_u *)eap->cmd, (char_u *)eap->arg, eap->forceit, false); -} - -/// ":abclear" and friends. -static void ex_abclear(exarg_T *eap) -{ - map_clear_mode((char_u *)eap->cmd, (char_u *)eap->arg, true, true); -} - static void ex_autocmd(exarg_T *eap) { // Disallow autocommands from .exrc and .vimrc in current @@ -8381,23 +8343,6 @@ void do_sleep(long msec) } } -static void do_exmap(exarg_T *eap, int isabbrev) -{ - int mode; - char *cmdp = eap->cmd; - mode = get_map_mode(&cmdp, eap->forceit || isabbrev); - - switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'), - (char_u *)eap->arg, mode, isabbrev)) { - case 1: - emsg(_(e_invarg)); - break; - case 2: - emsg(isabbrev ? _(e_noabbr) : _(e_nomap)); - break; - } -} - /// ":winsize" command (obsolete). static void ex_winsize(exarg_T *eap) { diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 211eeff45e..e442c907b3 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -46,6 +46,7 @@ #include "nvim/log.h" #include "nvim/lua/executor.h" #include "nvim/main.h" +#include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 3b6f7b90bf..e60be80923 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -25,9 +25,9 @@ #include "nvim/file_search.h" #include "nvim/fileio.h" #include "nvim/fold.h" -#include "nvim/getchar.h" #include "nvim/globals.h" #include "nvim/keycodes.h" +#include "nvim/mapping.h" #include "nvim/move.h" #include "nvim/option.h" #include "nvim/os/input.h" diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 57d25e5c45..4426f52353 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1,14 +1,8 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -/* - * getchar.c - * - * functions related with getting a character from the user/mapping/redo/... - * - * manipulations with redo buffer and stuff buffer - * mappings and abbreviations - */ +// getchar.c: Code related to getting a character from the user or a script +// file, manipulations with redo buffer and stuff buffer. #include <assert.h> #include <inttypes.h> @@ -22,18 +16,15 @@ #include "nvim/charset.h" #include "nvim/cursor.h" #include "nvim/edit.h" -#include "nvim/eval.h" #include "nvim/event/loop.h" -#include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" -#include "nvim/ex_session.h" -#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/input.h" #include "nvim/keycodes.h" #include "nvim/lua/executor.h" #include "nvim/main.h" +#include "nvim/mapping.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -46,7 +37,6 @@ #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/plines.h" -#include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/state.h" #include "nvim/strings.h" @@ -91,26 +81,6 @@ static int typeahead_char = 0; // typeahead char that's not flushed */ static int block_redo = FALSE; -// Make a hash value for a mapping. -// "mode" is the lower 4 bits of the State for the mapping. -// "c1" is the first character of the "lhs". -// Returns a value between 0 and 255, index in maphash. -// Put Normal/Visual mode mappings mostly separately from Insert/Cmdline mode. -#define MAP_HASH(mode, \ - c1) (((mode) & \ - (MODE_NORMAL | MODE_VISUAL | MODE_SELECT | \ - MODE_OP_PENDING | MODE_TERMINAL)) ? (c1) : ((c1) ^ 0x80)) - -// Each mapping is put in one of the MAX_MAPHASH hash lists, -// to speed up finding it. -static mapblock_T *(maphash[MAX_MAPHASH]); -static bool maphash_valid = false; - -/* - * List used for abbreviations. - */ -static mapblock_T *first_abbr = NULL; // first entry in abbrlist - static int KeyNoremap = 0; // remapping flags /* @@ -837,18 +807,10 @@ static void init_typebuf(void) } } -void init_default_mappings(void) +/// @return true when keys cannot be remapped. +bool noremap_keys(void) { - add_map((char_u *)"Y y$", MODE_NORMAL, true); - - // Use normal! <C-L> to prevent inserting raw <C-L> when using i_<C-O> - // See https://github.com/neovim/neovim/issues/17473 - add_map((char_u *)"<C-L> <Cmd>nohlsearch<Bar>diffupdate<Bar>normal! <C-L><CR>", - MODE_NORMAL, true); - add_map((char_u *)"<C-U> <C-G>u<C-U>", MODE_INSERT, true); - add_map((char_u *)"<C-W> <C-G>u<C-W>", MODE_INSERT, true); - add_map((char_u *)"* y/\\\\V<C-R>\"<CR>", MODE_VISUAL, true); - add_map((char_u *)"# y?\\\\V<C-R>\"<CR>", MODE_VISUAL, true); + return KeyNoremap & (RM_NONE|RM_SCRIPT); } // Insert a string in position 'offset' in the typeahead buffer (for "@r" @@ -1860,7 +1822,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth) // - waiting for a char with --more-- // - in Ctrl-X mode, and we get a valid char for that mode tb_c1 = typebuf.tb_buf[typebuf.tb_off]; - if (no_mapping == 0 && maphash_valid + if (no_mapping == 0 && is_maphash_valid() && (no_zero_mapping == 0 || tb_c1 != '0') && (typebuf.tb_maplen == 0 || is_plug_map || (!(typebuf.tb_noremap[typebuf.tb_off] & (RM_NONE|RM_ABBR)))) @@ -1877,8 +1839,8 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth) nolmaplen = 0; } // First try buffer-local mappings. - mp = curbuf->b_maphash[MAP_HASH(local_State, tb_c1)]; - mp2 = maphash[MAP_HASH(local_State, tb_c1)]; + mp = get_buf_maphash_list(local_State, tb_c1); + mp2 = get_maphash_list(local_State, tb_c1); if (mp == NULL) { // There are no buffer-local mappings. mp = mp2; @@ -2816,1970 +2778,6 @@ int fix_input_buffer(char_u *buf, int len) return len; } -/// Replace termcodes in the given LHS and RHS and store the results into the -/// `lhs` and `rhs` of the given @ref MapArguments struct. -/// -/// `rhs` and `orig_rhs` will both point to new allocated buffers. `orig_rhs` -/// will hold a copy of the given `orig_rhs`. -/// -/// The `*_len` variables will be set appropriately. If the length of -/// the final `lhs` exceeds `MAXMAPLEN`, `lhs_len` will be set equal to the -/// original larger length and `lhs` will be truncated. -/// -/// If RHS should be <Nop>, `rhs` will be an empty string, `rhs_len` will be -/// zero, and `rhs_is_noop` will be set to true. -/// -/// Any memory allocated by @ref replace_termcodes is freed before this function -/// returns. -/// -/// @param[in] orig_lhs Original mapping LHS, with characters to replace. -/// @param[in] orig_lhs_len `strlen` of orig_lhs. -/// @param[in] orig_rhs Original mapping RHS, with characters to replace. -/// @param[in] rhs_lua Lua reference for Lua maps. -/// @param[in] orig_rhs_len `strlen` of orig_rhs. -/// @param[in] cpo_flags See param docs for @ref replace_termcodes. -/// @param[out] mapargs MapArguments struct holding the replaced strings. -void set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs_len, - const char *const orig_rhs, const size_t orig_rhs_len, const LuaRef rhs_lua, - const int cpo_flags, MapArguments *const mapargs) -{ - char *lhs_buf = NULL; - char *alt_lhs_buf = NULL; - char *rhs_buf = NULL; - - // If mapping has been given as ^V<C_UP> say, then replace the term codes - // with the appropriate two bytes. If it is a shifted special key, unshift - // it too, giving another two bytes. - // - // replace_termcodes() may move the result to allocated memory, which - // needs to be freed later (*lhs_buf and *rhs_buf). - // replace_termcodes() also removes CTRL-Vs and sometimes backslashes. - // If something like <C-H> is simplified to 0x08 then mark it as simplified. - bool did_simplify = false; - const int flags = REPTERM_FROM_PART | REPTERM_DO_LT; - char *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &lhs_buf, flags, &did_simplify, - cpo_flags); - mapargs->lhs_len = STRLEN(replaced); - STRLCPY(mapargs->lhs, replaced, sizeof(mapargs->lhs)); - if (did_simplify) { - replaced = replace_termcodes(orig_lhs, orig_lhs_len, &alt_lhs_buf, flags | REPTERM_NO_SIMPLIFY, - NULL, cpo_flags); - mapargs->alt_lhs_len = STRLEN(replaced); - STRLCPY(mapargs->alt_lhs, replaced, sizeof(mapargs->alt_lhs)); - } else { - mapargs->alt_lhs_len = 0; - } - - mapargs->rhs_lua = rhs_lua; - - if (rhs_lua == LUA_NOREF) { - mapargs->orig_rhs_len = orig_rhs_len; - mapargs->orig_rhs = xcalloc(mapargs->orig_rhs_len + 1, sizeof(char_u)); - STRLCPY(mapargs->orig_rhs, orig_rhs, mapargs->orig_rhs_len + 1); - - if (STRICMP(orig_rhs, "<nop>") == 0) { // "<Nop>" means nothing - mapargs->rhs = xcalloc(1, sizeof(char_u)); // single null-char - mapargs->rhs_len = 0; - mapargs->rhs_is_noop = true; - } else { - replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, REPTERM_DO_LT, NULL, - cpo_flags); - mapargs->rhs_len = STRLEN(replaced); - // XXX: replace_termcodes may produce an empty string even if orig_rhs is non-empty - // (e.g. a single ^V, see :h map-empty-rhs) - mapargs->rhs_is_noop = orig_rhs_len != 0 && mapargs->rhs_len == 0; - mapargs->rhs = xcalloc(mapargs->rhs_len + 1, sizeof(char_u)); - STRLCPY(mapargs->rhs, replaced, mapargs->rhs_len + 1); - } - } else { - char tmp_buf[64]; - // orig_rhs is not used for Lua mappings, but still needs to be a string. - mapargs->orig_rhs = xcalloc(1, sizeof(char_u)); - mapargs->orig_rhs_len = 0; - // stores <lua>ref_no<cr> in map_str - mapargs->rhs_len = (size_t)vim_snprintf(S_LEN(tmp_buf), "%c%c%c%d\r", K_SPECIAL, - (char_u)KS_EXTRA, KE_LUA, rhs_lua); - mapargs->rhs = vim_strsave((char_u *)tmp_buf); - } - - xfree(lhs_buf); - xfree(alt_lhs_buf); - xfree(rhs_buf); -} - -/// Parse a string of |:map-arguments| into a @ref MapArguments struct. -/// -/// Termcodes, backslashes, CTRL-V's, etc. inside the extracted {lhs} and -/// {rhs} are replaced by @ref set_maparg_lhs_rhs. -/// -/// rhs and orig_rhs in the returned mapargs will be set to null or a pointer -/// to allocated memory and should be freed even on error. |