From de45ec0146486c49719ff6f6dcceb4914b471c7a Mon Sep 17 00:00:00 2001 From: ZyX Date: Thu, 30 Nov 2017 02:01:49 +0300 Subject: [PATCH] keymap: Do not use vim_isIDc in keymap.c Note: there are three changes to ascii_isident. Reverting first two (in find_special_key and first in get_special_key_code) normally fails the new test with empty &isident, but reverting the third does not. Hence adding `>` to &isident. Ref vim/vim#2389. --- src/nvim/ascii.h | 13 +++++++++++++ src/nvim/keymap.c | 6 +++--- src/nvim/viml/parser/expressions.c | 9 +++------ test/functional/ex_cmds/map_spec.lua | 21 +++++++++++++++++++++ test/symbolic/klee/nvim/charset.c | 5 ----- test/symbolic/klee/nvim/keymap.c | 7 ++++--- 6 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 test/functional/ex_cmds/map_spec.lua diff --git a/src/nvim/ascii.h b/src/nvim/ascii.h index adde91f9ec..9ccb70764d 100644 --- a/src/nvim/ascii.h +++ b/src/nvim/ascii.h @@ -3,6 +3,7 @@ #include +#include "nvim/macros.h" #include "nvim/func_attr.h" #include "nvim/os/os_defs.h" @@ -98,6 +99,10 @@ static inline bool ascii_isxdigit(int) REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE; +static inline bool ascii_isident(int) + REAL_FATTR_CONST + REAL_FATTR_ALWAYS_INLINE; + static inline bool ascii_isbdigit(int) REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE; @@ -138,6 +143,14 @@ static inline bool ascii_isxdigit(int c) || (c >= 'A' && c <= 'F'); } +/// Checks if `c` is an “identifier” character +/// +/// That is, whether it is alphanumeric character or underscore. +static inline bool ascii_isident(const int c) +{ + return ASCII_ISALNUM(c) || c == '_'; +} + /// Checks if `c` is a binary digit, that is, 0-1. /// /// @see {ascii_isdigit} diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index aca21c20a5..0eb5a41b1e 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -567,7 +567,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, // Find end of modifier list last_dash = src; - for (bp = src + 1; bp <= end && (*bp == '-' || vim_isIDc(*bp)); bp++) { + for (bp = src + 1; bp <= end && (*bp == '-' || ascii_isident(*bp)); bp++) { if (*bp == '-') { last_dash = bp; if (bp + 1 <= end) { @@ -721,12 +721,12 @@ int get_special_key_code(const char_u *name) for (int i = 0; key_names_table[i].name != NULL; i++) { const char *const table_name = key_names_table[i].name; int j; - for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++) { + for (j = 0; ascii_isident(name[j]) && table_name[j] != NUL; j++) { if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j])) { break; } } - if (!vim_isIDc(name[j]) && table_name[j] == NUL) { + if (!ascii_isident(name[j]) && table_name[j] == NUL) { return key_names_table[i].key; } } diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c index 9773e60bbd..cfcde6bb38 100644 --- a/src/nvim/viml/parser/expressions.c +++ b/src/nvim/viml/parser/expressions.c @@ -386,13 +386,11 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) } #define ISWORD_OR_AUTOLOAD(x) \ - (ASCII_ISALNUM(x) || (x) == AUTOLOAD_CHAR || (x) == '_') -#define ISWORD(x) \ - (ASCII_ISALNUM(x) || (x) == '_') + (ascii_isident(x) || (x) == AUTOLOAD_CHAR) // Environment variable. case '$': { - CHARREG(kExprLexEnv, ISWORD); + CHARREG(kExprLexEnv, ascii_isident); break; } @@ -408,7 +406,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) case '_': { ret.data.var.scope = 0; ret.data.var.autoload = false; - CHARREG(kExprLexPlainIdentifier, ISWORD); + CHARREG(kExprLexPlainIdentifier, ascii_isident); // "is" and "isnot" operators. if (!(flags & kELFlagIsNotCmp) && ((ret.len == 2 && memcmp(pline.data, "is", 2) == 0) @@ -445,7 +443,6 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) break; } -#undef ISWORD #undef ISWORD_OR_AUTOLOAD #undef CHARREG diff --git a/test/functional/ex_cmds/map_spec.lua b/test/functional/ex_cmds/map_spec.lua new file mode 100644 index 0000000000..b46f83405e --- /dev/null +++ b/test/functional/ex_cmds/map_spec.lua @@ -0,0 +1,21 @@ +local helpers = require("test.functional.helpers")(after_each) + +local eq = helpers.eq +local feed = helpers.feed +local meths = helpers.meths +local clear = helpers.clear +local command = helpers.command + +describe(':*map', function() + before_each(clear) + + it('are not affected by &isident', function() + meths.set_var('counter', 0) + command('nnoremap :let counter+=1') + meths.set_option('isident', ('%u'):format(('>'):byte())) + command('nnoremap :let counter+=1') + -- &isident used to disable keycode parsing here as well + feed('\24\25') + eq(4, meths.get_var('counter')) + end) +end) diff --git a/test/symbolic/klee/nvim/charset.c b/test/symbolic/klee/nvim/charset.c index 77f690f08d..95853a6834 100644 --- a/test/symbolic/klee/nvim/charset.c +++ b/test/symbolic/klee/nvim/charset.c @@ -6,11 +6,6 @@ #include "nvim/eval/typval.h" #include "nvim/vim.h" -bool vim_isIDc(int c) -{ - return ASCII_ISALNUM(c); -} - int hex2nr(int c) { if ((c >= 'a') && (c <= 'f')) { diff --git a/test/symbolic/klee/nvim/keymap.c b/test/symbolic/klee/nvim/keymap.c index ff5e46e75b..a341a73689 100644 --- a/test/symbolic/klee/nvim/keymap.c +++ b/test/symbolic/klee/nvim/keymap.c @@ -2,6 +2,7 @@ #include "nvim/types.h" #include "nvim/keymap.h" +#include "nvim/ascii.h" #include "nvim/eval/typval.h" #define MOD_KEYS_ENTRY_SIZE 5 @@ -294,12 +295,12 @@ int get_special_key_code(const char_u *name) for (int i = 0; key_names_table[i].name != NULL; i++) { const char *const table_name = key_names_table[i].name; int j; - for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++) { + for (j = 0; ascii_isident(name[j]) && table_name[j] != NUL; j++) { if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j])) { break; } } - if (!vim_isIDc(name[j]) && table_name[j] == NUL) { + if (!ascii_isident(name[j]) && table_name[j] == NUL) { return key_names_table[i].key; } } @@ -386,7 +387,7 @@ int find_special_key(const char_u **srcp, const size_t src_len, int *const modp, // Find end of modifier list last_dash = src; - for (bp = src + 1; bp <= end && (*bp == '-' || vim_isIDc(*bp)); bp++) { + for (bp = src + 1; bp <= end && (*bp == '-' || ascii_isident(*bp)); bp++) { if (*bp == '-') { last_dash = bp; if (bp + 1 <= end) {