Mercurial > vim
diff src/normal.c @ 27447:4050f0554902 v8.2.4252
patch 8.2.4252: generating the normal command table at runtime is inefficient
Commit: https://github.com/vim/vim/commit/4dc0dd869972ddafc7d9ee5ea765645b818a6dc9
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Sat Jan 29 13:06:40 2022 +0000
patch 8.2.4252: generating the normal command table at runtime is inefficient
Problem: Generating the normal command table at runtime is inefficient.
Solution: Generate the table with a Vim script and put it in a header file.
(Yegappan Lakshmanan, closes #9648)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 29 Jan 2022 14:15:04 +0100 |
parents | 3f8a57b8c7d8 |
children | ee1019e59bef |
line wrap: on
line diff
--- a/src/normal.c +++ b/src/normal.c @@ -19,7 +19,6 @@ static int VIsual_mode_orig = NUL; // s #ifdef FEAT_EVAL static void set_vcount_ca(cmdarg_T *cap, int *set_prevcount); #endif -static int nv_compare(const void *s1, const void *s2); static void unshift_special(cmdarg_T *cap); #ifdef FEAT_CMDL_INFO static void del_from_showcmd(int); @@ -128,6 +127,34 @@ static void nv_drop(cmdarg_T *cap); #endif static void nv_cursorhold(cmdarg_T *cap); +#ifdef FEAT_GUI +#define NV_VER_SCROLLBAR nv_ver_scrollbar +#define NV_HOR_SCROLLBAR nv_hor_scrollbar +#else +#define NV_VER_SCROLLBAR nv_error +#define NV_HOR_SCROLLBAR nv_error +#endif + +#ifdef FEAT_GUI_TABLINE +#define NV_TABLINE nv_tabline +#define NV_TABMENU nv_tabmenu +#else +#define NV_TABLINE nv_error +#define NV_TABMENU nv_error +#endif + +#ifdef FEAT_NETBEANS_INTG +#define NV_NBCMD nv_nbcmd +#else +#define NV_NBCMD nv_error +#endif + +#ifdef FEAT_DND +#define NV_DROP nv_drop +#else +#define NV_DROP nv_error +#endif + /* * Function to be called for a Normal or Visual mode command. * The argument is a cmdarg_T. @@ -159,8 +186,14 @@ typedef void (*nv_func_T)(cmdarg_T *cap) /* * This table contains one entry for every Normal or Visual mode command. - * The order doesn't matter, init_normal_cmds() will create a sorted index. + * The order doesn't matter, this will be sorted by the create_nvcmdidx.vim + * script to generate the nv_cmd_idx[] lookup table. * It is faster when all keys from zero to '~' are present. + * + * After changing the "nv_cmds" table: + * 1. Build Vim with "make" + * 2. Run "make nvcmdidxs" to re-generate the nv_cmdidxs.h file. + * 3. Build Vim with "make" to use the newly generated index table. */ static const struct nv_cmd { @@ -193,8 +226,6 @@ static const struct nv_cmd {Ctrl_T, nv_tagpop, NV_NCW, 0}, {Ctrl_U, nv_halfpage, 0, 0}, {Ctrl_V, nv_visual, 0, FALSE}, - {'V', nv_visual, 0, FALSE}, - {'v', nv_visual, 0, FALSE}, {Ctrl_W, nv_window, 0, 0}, {Ctrl_X, nv_addsub, 0, 0}, {Ctrl_Y, nv_scroll_line, 0, FALSE}, @@ -258,6 +289,7 @@ static const struct nv_cmd {'S', nv_subst, NV_KEEPREG, 0}, {'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD}, {'U', nv_Undo, 0, 0}, + {'V', nv_visual, 0, FALSE}, {'W', nv_wordcmd, 0, TRUE}, {'X', nv_abbrev, NV_KEEPREG, 0}, {'Y', nv_abbrev, NV_KEEPREG, 0}, @@ -289,6 +321,7 @@ static const struct nv_cmd {'s', nv_subst, NV_KEEPREG, 0}, {'t', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD}, {'u', nv_undo, 0, 0}, + {'v', nv_visual, 0, FALSE}, {'w', nv_wordcmd, 0, FALSE}, {'x', nv_abbrev, NV_KEEPREG, 0}, {'y', nv_operator, 0, 0}, @@ -356,20 +389,12 @@ static const struct nv_cmd {K_F1, nv_help, NV_NCW, 0}, {K_XF1, nv_help, NV_NCW, 0}, {K_SELECT, nv_select, 0, 0}, -#ifdef FEAT_GUI - {K_VER_SCROLLBAR, nv_ver_scrollbar, 0, 0}, - {K_HOR_SCROLLBAR, nv_hor_scrollbar, 0, 0}, -#endif -#ifdef FEAT_GUI_TABLINE - {K_TABLINE, nv_tabline, 0, 0}, - {K_TABMENU, nv_tabmenu, 0, 0}, -#endif -#ifdef FEAT_NETBEANS_INTG - {K_F21, nv_nbcmd, NV_NCH_ALW, 0}, -#endif -#ifdef FEAT_DND - {K_DROP, nv_drop, NV_STS, 0}, -#endif + {K_VER_SCROLLBAR, NV_VER_SCROLLBAR, 0, 0}, + {K_HOR_SCROLLBAR, NV_HOR_SCROLLBAR, 0, 0}, + {K_TABLINE, NV_TABLINE, 0, 0}, + {K_TABMENU, NV_TABMENU, 0, 0}, + {K_F21, NV_NBCMD, NV_NCH_ALW, 0}, + {K_DROP, NV_DROP, NV_STS, 0}, {K_CURSORHOLD, nv_cursorhold, NV_KEEPREG, 0}, {K_PS, nv_edit, 0, 0}, {K_COMMAND, nv_colon, 0, 0}, @@ -379,55 +404,42 @@ static const struct nv_cmd // Number of commands in nv_cmds[]. #define NV_CMDS_SIZE ARRAY_LENGTH(nv_cmds) -#ifndef PROTO // cproto doesn't like this -// Sorted index of commands in nv_cmds[]. -static short nv_cmd_idx[NV_CMDS_SIZE]; -#endif - -// The highest index for which -// nv_cmds[idx].cmd_char == nv_cmd_idx[nv_cmds[idx].cmd_char] -static int nv_max_linear; - -/* - * Compare functions for qsort() below, that checks the command character - * through the index in nv_cmd_idx[]. - */ - static int -nv_compare(const void *s1, const void *s2) -{ - int c1, c2; - - // The commands are sorted on absolute value. - c1 = nv_cmds[*(const short *)s1].cmd_char; - c2 = nv_cmds[*(const short *)s2].cmd_char; - if (c1 < 0) - c1 = -c1; - if (c2 < 0) - c2 = -c2; - return c1 - c2; -} - -/* - * Initialize the nv_cmd_idx[] table. +// Include the lookuptable generated by create_nvcmdidx.vim. +#include "nv_cmdidxs.h" + +#if defined(FEAT_EVAL) || defined(PROTO) +/* + * Return the command character for the given command index. This function is + * used to auto-generate nv_cmd_idx[]. */ void -init_normal_cmds(void) -{ - int i; - - // Fill the index table with a one to one relation. - for (i = 0; i < (int)NV_CMDS_SIZE; ++i) - nv_cmd_idx[i] = i; - - // Sort the commands by the command character. - qsort((void *)&nv_cmd_idx, (size_t)NV_CMDS_SIZE, sizeof(short), nv_compare); - - // Find the first entry that can't be indexed by the command character. - for (i = 0; i < (int)NV_CMDS_SIZE; ++i) - if (i != nv_cmds[nv_cmd_idx[i]].cmd_char) - break; - nv_max_linear = i - 1; -} +f_internal_get_nv_cmdchar(typval_T *argvars, typval_T *rettv) +{ + int idx; + int cmd_char; + + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = -1; + + if (check_for_number_arg(argvars, 0) == FAIL) + return; + + idx = tv_get_number(&argvars[0]); + if (idx < 0 || idx >= (int)NV_CMDS_SIZE) + return; + + cmd_char = nv_cmds[idx].cmd_char; + + // We use the absolute value of the character. Special keys have a + // negative value, but are sorted on their absolute value. + if (cmd_char < 0) + cmd_char = -cmd_char; + + rettv->vval.v_number = cmd_char; + + return; +} +#endif /* * Search for a command in the commands table.