0
0
mirror of https://github.com/vim/vim.git synced 2025-09-27 04:14:06 -04:00

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)
This commit is contained in:
Yegappan Lakshmanan
2022-01-29 13:06:40 +00:00
committed by Bram Moolenaar
parent 97c554d514
commit 4dc0dd8699
14 changed files with 400 additions and 65 deletions

View File

@@ -19,7 +19,6 @@ static int VIsual_mode_orig = NUL; // saved Visual mode
#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;
// Include the lookuptable generated by create_nvcmdidx.vim.
#include "nv_cmdidxs.h"
#if defined(FEAT_EVAL) || defined(PROTO)
/*
* 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.
* Return the command character for the given command index. This function is
* used to auto-generate nv_cmd_idx[].
*/
void
init_normal_cmds(void)
f_internal_get_nv_cmdchar(typval_T *argvars, typval_T *rettv)
{
int i;
int idx;
int cmd_char;
// Fill the index table with a one to one relation.
for (i = 0; i < (int)NV_CMDS_SIZE; ++i)
nv_cmd_idx[i] = i;
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = -1;
// Sort the commands by the command character.
qsort((void *)&nv_cmd_idx, (size_t)NV_CMDS_SIZE, sizeof(short), nv_compare);
if (check_for_number_arg(argvars, 0) == FAIL)
return;
// 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;
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.