xref: /vim-8.2.3635/src/create_cmdidxs.vim (revision dabfde04)
1" This script generates the tables cmdidxs1[] and cmdidxs2[][] which,
2" given a Ex command, determine the first value to probe to find
3" a matching command in cmdnames[] based on the first character
4" and the first 2 characters of the command.
5" This is used to speed up lookup in cmdnames[].
6"
7" Script should be run every time new Ex commands are added in Vim,
8" from the src/vim directory, since it reads commands from "ex_cmds.h".
9
10let cmds = []
11let skipped_cmds = 0
12
13let lines = readfile('ex_cmds.h')
14let idx = 0
15while idx < len(lines)
16  let line = lines[idx]
17  if line =~ '^EX(CMD_'
18    let m = matchlist(line, '^EX(CMD_\S*,\s*"\([a-z][^"]*\)"')
19    if len(m) >= 2
20      let cmds += [ m[1] ]
21    else
22      let skipped_cmds += 1
23    endif
24
25    let idx += 1
26    let flags = lines[idx]
27    let idx += 1
28    let addr_type = lines[idx]
29
30    if flags =~ '\<RANGE\>'
31      if addr_type =~ 'ADDR_NONE'
32	echoerr 'ex_cmds.h:' .. (idx - 1) .. ': Using RANGE with ADDR_NONE: ' .. line
33      endif
34    else
35      if addr_type !~ 'ADDR_NONE'
36	echoerr 'ex_cmds.h:' .. (idx - 1) .. ': Missing ADDR_NONE: ' .. line
37      endif
38    endif
39
40    if flags =~ '\<DFLALL\>' && (addr_type =~ 'ADDR_OTHER' || addr_type =~ 'ADDR_NONE')
41      echoerr 'ex_cmds.h:' .. (idx - 1) .. ': Missing misplaced DFLALL: ' .. line
42    endif
43  endif
44  let idx += 1
45endwhile
46
47let cmdidxs1 = {}
48let cmdidxs2 = {}
49
50for i in range(len(cmds) - 1, 0, -1)
51  let cmd = cmds[i]
52  let c1 = cmd[0] " First character of command
53  let c2 = cmd[1] " Second character of command (if any)
54
55  let cmdidxs1{c1} = i
56  if c2 >= 'a' && c2 <= 'z'
57    let cmdidxs2{c1}{c2} = i
58  endif
59endfor
60
61let output =  [ '/* Automatically generated code by create_cmdidxs.vim' ]
62let output += [ ' *' ]
63let output += [ ' * Table giving the index of the first command in cmdnames[] to lookup' ]
64let output += [ ' * based on the first letter of a command.' ]
65let output += [ ' */' ]
66let output += [ 'static const unsigned short cmdidxs1[26] =' ]
67let output += [ '{' ]
68
69let a_to_z = map(range(char2nr('a'), char2nr('z')), 'nr2char(v:val)')
70for c1 in a_to_z
71  let line = '  /* ' . c1 . ' */ ' . cmdidxs1{c1} . ((c1 == 'z') ? '' : ',')
72  let output += [ line ]
73endfor
74let output += [ '};' ]
75let output += [ '' ]
76let output += [ '/*' ]
77let output += [ ' * Table giving the index of the first command in cmdnames[] to lookup' ]
78let output += [ ' * based on the first 2 letters of a command.' ]
79let output += [ ' * Values in cmdidxs2[c1][c2] are relative to cmdidxs1[c1] so that they' ]
80let output += [ ' * fit in a byte.' ]
81let output += [ ' */' ]
82let output += [ 'static const unsigned char cmdidxs2[26][26] =' ]
83let output += [ '{ /*         a   b   c   d   e   f   g   h   i   j   k   l   m   n   o   p   q   r   s   t   u   v   w   x   y   z */' ]
84
85for c1 in a_to_z
86  let line = '  /* ' . c1 . ' */ {'
87  for c2 in a_to_z
88    if exists('cmdidxs2{c1}{c2}')
89      let line .= printf('%3d', cmdidxs2{c1}{c2} - cmdidxs1{c1})
90    else
91      let line .= '  0'
92    endif
93    let line .= (c2 == 'z') ? '' : ','
94  endfor
95  let line .= ' }' . ((c1 == 'z') ? '' : ',')
96  let output += [ line ]
97endfor
98
99let output += [ '};' ]
100let output += [ '' ]
101let output += [ 'static const int command_count = ' . (len(cmds) + skipped_cmds) . ';' ]
102
103call writefile(output, "ex_cmdidxs.h")
104quit
105