summaryrefslogtreecommitdiffstats
path: root/src/create_cmdidxs.vim
diff options
context:
space:
mode:
Diffstat (limited to 'src/create_cmdidxs.vim')
-rw-r--r--src/create_cmdidxs.vim104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/create_cmdidxs.vim b/src/create_cmdidxs.vim
new file mode 100644
index 0000000..2f8ad1f
--- /dev/null
+++ b/src/create_cmdidxs.vim
@@ -0,0 +1,104 @@
+" This script generates the tables cmdidxs1[] and cmdidxs2[][] which,
+" given a Ex command, determine the first value to probe to find
+" a matching command in cmdnames[] based on the first character
+" and the first 2 characters of the command.
+" This is used to speed up lookup in cmdnames[].
+"
+" Script should be run every time new Ex commands are added in Vim,
+" from the src/vim directory, since it reads commands from "ex_cmds.h".
+
+let cmds = []
+let skipped_cmds = 0
+
+let lines = readfile('ex_cmds.h')
+let idx = 0
+while idx < len(lines)
+ let line = lines[idx]
+ if line =~ '^EXCMD(CMD_'
+ let m = matchlist(line, '^EXCMD(CMD_\S*,\s*"\([a-z][^"]*\)"')
+ if len(m) >= 2
+ let cmds += [ m[1] ]
+ else
+ let skipped_cmds += 1
+ endif
+
+ let idx += 1
+ let flags = lines[idx]
+ let idx += 1
+ let addr_type = lines[idx]
+
+ if flags =~ '\<EX_RANGE\>'
+ if addr_type =~ 'ADDR_NONE'
+ echoerr 'ex_cmds.h:' .. (idx - 1) .. ': Using EX_RANGE with ADDR_NONE: ' .. line
+ endif
+ else
+ if addr_type !~ 'ADDR_NONE'
+ echoerr 'ex_cmds.h:' .. (idx - 1) .. ': Missing ADDR_NONE: ' .. line
+ endif
+ endif
+
+ if flags =~ '\<EX_DFLALL\>' && (addr_type =~ 'ADDR_OTHER' || addr_type =~ 'ADDR_NONE')
+ echoerr 'ex_cmds.h:' .. (idx - 1) .. ': Missing misplaced EX_DFLALL: ' .. line
+ endif
+ endif
+ let idx += 1
+endwhile
+
+let cmdidxs1 = {}
+let cmdidxs2 = {}
+
+for i in range(len(cmds) - 1, 0, -1)
+ let cmd = cmds[i]
+ let c1 = cmd[0] " First character of command
+ let c2 = cmd[1] " Second character of command (if any)
+
+ let cmdidxs1{c1} = i
+ if c2 >= 'a' && c2 <= 'z'
+ let cmdidxs2{c1}{c2} = i
+ endif
+endfor
+
+let output = [ '/* Automatically generated code by create_cmdidxs.vim' ]
+let output += [ ' *' ]
+let output += [ ' * Table giving the index of the first command in cmdnames[] to lookup' ]
+let output += [ ' * based on the first letter of a command.' ]
+let output += [ ' */' ]
+let output += [ 'static const unsigned short cmdidxs1[26] =' ]
+let output += [ '{' ]
+
+let a_to_z = map(range(char2nr('a'), char2nr('z')), 'nr2char(v:val)')
+for c1 in a_to_z
+ let line = ' /* ' . c1 . ' */ ' . cmdidxs1{c1} . ((c1 == 'z') ? '' : ',')
+ let output += [ line ]
+endfor
+let output += [ '};' ]
+let output += [ '' ]
+let output += [ '/*' ]
+let output += [ ' * Table giving the index of the first command in cmdnames[] to lookup' ]
+let output += [ ' * based on the first 2 letters of a command.' ]
+let output += [ ' * Values in cmdidxs2[c1][c2] are relative to cmdidxs1[c1] so that they' ]
+let output += [ ' * fit in a byte.' ]
+let output += [ ' */' ]
+let output += [ 'static const unsigned char cmdidxs2[26][26] =' ]
+let 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 */' ]
+
+for c1 in a_to_z
+ let line = ' /* ' . c1 . ' */ {'
+ for c2 in a_to_z
+ if exists('cmdidxs2{c1}{c2}')
+ let line .= printf('%3d', cmdidxs2{c1}{c2} - cmdidxs1{c1})
+ else
+ let line .= ' 0'
+ endif
+ let line .= (c2 == 'z') ? '' : ','
+ endfor
+ let line .= ' }' . ((c1 == 'z') ? '' : ',')
+ let output += [ line ]
+endfor
+
+let output += [ '};' ]
+let output += [ '' ]
+let output += [ 'static const int command_count = ' . (len(cmds) + skipped_cmds) . ';' ]
+
+call writefile(output, "ex_cmdidxs.h")
+quit