I have written my Word add-in using VBScript regex v5.5 to parse the command. Feedback and contributions welcome! As of 2019-02-15, the add-in works in Word 2007–2016.
I am largely following the model in the grammar @Mass kindly linked to. As of v0.2.9, my regex is:
with zero-based submatch numbers:
1 The initial count
3 Intransitive verb (e.g., 0, w, f<char>)
4 Motion for an intransitive verb
5 The <char> of an f, F, t, or T
7 Transitive verb (e.g., operators d, c, y)
8 The count after the operator
9 The motion or text object ("target")
10 vim-ninja-feet* [ or ]
11 a or i if you are selecting a text object
12 For a and i motions, which type of object is being selected (w, W, s, p)
13 For f, F, t and T motions, which character is being used
Registers are still not supported.
The regex is complicated enough that I wrote a Perl script to generate the regex from a text description of it. That description is below. Run
./re2vba.pl vim-regex.txt to generate the regex and submatch-number assignments on stdout.
In the description,
(?<name>...) represents a named submatch, and
(?<=piece-name) pulls in a named piece of the regex. Comments (
(?#...)) and trailing whitespace (after stripping comments) are ignored.
# Main pattern
main ^( (?# Note: registers not yet implemented)
# Motions that don't take arguments (although they may take counts).
# A motion of "0" is special-cased in the parsing code to keep the regex
# clean. This regex, after backtracking, matches "10" as a count of "1"
# followed by a "0" motion. We special-case rather than handling that here.
(?# 28/29 are parens, move sentence )
(?# 7b/7d are braces, move paragraph )
g?[eE0\^\$] (?# gw, gb, etc. are not motions.)
(?# ^ Note: 0 is special-cased in the parsing code.)
# Intransitive, including motions. These can take a count, namely ?<count1>.
(?<imotion> (?# motions)
(gW)?g?[\*#]| (?# searches)
g?[pP] (?# pastes)
# IVERB: what to do
# ITEXT: character to jump to
# Text-object selection ([ai][something])
textobj (?<ninja>[\[\]])? (?# Ninja-feet marker)
(?<tobj_range>[ai]) (?# Introducer)
(?<objtype>[wWsp]) (?# Type of text object)
# Transitive: verb, count, object, object type, text
trans (?<tverb>[cdyv]) (?# TVERB: what to do)
(?<count2>[1-9][0-9]*)? (?# Count after the operator)
(?<target> (?# What to work on)
(?<=textobj)| (?# Text objects)
[fFtT](?<ttext>.)| (?# Motions with an argument)
Note 1: Just like in Vim,
v selects the text moved over. However, Word is essentially always in a combination of normal and visual modes, so
v doesn't leave you in any special mode.
Note 2: I don't need the
c intransitive verb for one-offs, since you are back in Word (i.e., insert mode) after a
d. However, I am working on a loop version that will leave you in Normal mode after a
d but not after a