On Saturday, November 9, 2013 5:19:29 PM UTC-6, Edward K. Ream wrote:
A big collapse in complexity just happened.
>
> The data structure above should be the *result* of user arguments, not a
> transliteration of the actual arguments. This makes a huge difference!
>
Indeed it did.
Leo now has a leoVim.py module (not used by Leo's core) containing the
VimCommands class. vc for short.
vc.create_dicts and its four helpers computes 4 dictionaries to be used by
the commands scanner. These methods parse the following four @data nodes.
These are, imo, pretty accurate descriptions of vim's commands::
===== @data vim-command-tails
char F
char T
char f
char r
char t
letter m
letter q
motion <
motion >
motion c
motion d
motion gU
motion gq
motion gu
motion g~
motion y
pattern /
pattern ?
===== @data vim-motion-tails
char F
char T
char f
char t
===== @data vim-motions
# CR
# Ctrl-End
# Ctrl-Home
# Ctrl-Left
# Ctrl-M
# Ctrl-N
# Ctrl-P
# Ctrl-Right
# End
# Home
# Shift-Left
# Shift-Right
(
)
{
}
[[
[]
][
]]
$
^
+
,
-
;
_
0
B
E
F
G
T
W
b
e
f
g$
g^
g0
gE
# gEnd
# gHome
ge
gg
h
j
k
t
w
===== @data vim-commands
vim_0 0
vim_tilda ~
vim_plus +
vim_underscore _
vim_minus -
vim_comma ,
vim_dot .
vim_semicolon ;
vim_lparen (
vim_rparen )
vim_lcurly {
vim_rcurly }
vim_vertical |
vim_backtick `
vim_dollar $
vim_caret ^
vim_percent %
vim_langle <
vim_langle <<
vim_rangle >
vim_langle >>
vim_pound #
vim_star *
vim_slash /\\n
vim_slash /
vim_question ?\\n
vim_question ?
vim_at @
vim_at @@
vim_dquote "
vim_lsquare [#
vim_lsquare [(
vim_lsquare [*
vim_lsquare [[
vim_lsquare []
vim_lsquare [p
vim_lsquare [{
vim_rsquare ]#
vim_rsquare ])
vim_rsquare ]*
vim_rsquare ][
vim_rsquare ]]
vim_rsquare ]p
vim_rsquare ]}
vim_A A
vim_B B
vim_C C
vim_D D
vim_E E
vim_F F
vim_G G
vim_H H
vim_I I
vim_J J
vim_K K
vim_M M
vim_L L
vim_N N
vim_O O
vim_P P
vim_R R
vim_S S
vim_T T
vim_U U
vim_V V
vim_W W
vim_X X
vim_Y Y
vim_Z ZQ
vim_Z ZZ
vim_a a
vim_b b
vim_c c
vim_d dd
vim_d d
vim_g g~
vim_g g^
vim_g g#
vim_g g$
vim_g g*
vim_g g0
vim_g gD
vim_g gE
vim_g gI
vim_g gU
vim_g ga
vim_g gd
vim_g ge
vim_g gf
vim_g gg
vim_g gj
vim_g gk
vim_g gq
vim_g gs
vim_g gu
vim_g gv
vim_h h
vim_i i
vim_j j
vim_k k
vim_l l
vim_n n
vim_m m
vim_o o
vim_p p
vim_q q
vim_r r
vim_s s
vim_t t
vim_u u
vim_v v
vim_w w
vim_x x
vim_y y
vim_y yy
vim_z z-
vim_z z.
vim_z z<CR>
vim_z zb
vim_z zh
vim_z zl
vim_z zt
vim_z zz
===== And here is the dump of the resulting dictionaries::
QQQQQ
Dump of command_tails_d
/ pattern
< motion
> motion
? pattern
F char
T char
c motion
d motion
f char
gU motion
gq motion
gu motion
g~ motion
m letter
q letter
r char
t char
y motion
Dump of motion_tails_d
F char
T char
f char
t char
Dump of motions_d
$
(
)
+
,
-
0
;
B
E
F char
G
T char
W
[[
[]
][
]]
^
_
b
e
f char
g$
g0
gE
g^
ge
gg
h
j
k
t char
w
{
}
Dump of command_d
"
ch "
tail_chars None
#
ch #
tail_chars None
$
ch $
tail_chars None
%
ch %
tail_chars None
(
ch (
tail_chars None
)
ch )
tail_chars None
*
ch *
tail_chars None
+
ch +
tail_chars None
,
ch ,
tail_chars None
-
ch -
tail_chars None
.
ch .
tail_chars None
/
ch /
tail_chars \\n,None
tail_pattern pattern
0
ch 0
tail_chars None
;
ch ;
tail_chars None
<
ch <
tail_chars None,<
tail_pattern motion
>
ch >
tail_chars None,>
tail_pattern motion
?
ch ?
tail_chars \\n,None
tail_pattern pattern
@
ch @
tail_chars None,@
A
ch A
tail_chars None
B
ch B
tail_chars None
C
ch C
tail_chars None
D
ch D
tail_chars None
E
ch E
tail_chars None
F
ch F
tail_chars None
tail_pattern char
G
ch G
tail_chars None
H
ch H
tail_chars None
I
ch I
tail_chars None
J
ch J
tail_chars None
K
ch K
tail_chars None
L
ch L
tail_chars None
M
ch M
tail_chars None
N
ch N
tail_chars None
O
ch O
tail_chars None
P
ch P
tail_chars None
R
ch R
tail_chars None
S
ch S
tail_chars None
T
ch T
tail_chars None
tail_pattern char
U
ch U
tail_chars None
V
ch V
tail_chars None
W
ch W
tail_chars None
X
ch X
tail_chars None
Y
ch Y
tail_chars None
Z
ch Z
tail_chars Q,Z
[
ch [
tail_chars #,(,*,[,],p,{
]
ch ]
tail_chars #,),*,[,],p,}
^
ch ^
tail_chars None
_
ch _
tail_chars None
`
ch `
tail_chars None
a
ch a
tail_chars None
b
ch b
tail_chars None
c
ch c
tail_chars None
tail_pattern motion
d
ch d
tail_chars d,None
tail_pattern motion
g
ch g
tail_chars ~,^,#,$,*,0,D,E,I,U,a,d,e,f,g,j,k,q,s,u,v
h
ch h
tail_chars None
i
ch i
tail_chars None
j
ch j
tail_chars None
k
ch k
tail_chars None
l
ch l
tail_chars None
m
ch m
tail_chars None
tail_pattern letter
n
ch n
tail_chars None
o
ch o
tail_chars None
p
ch p
tail_chars None
q
ch q
tail_chars None
tail_pattern letter
r
ch r
tail_chars None
tail_pattern char
s
ch s
tail_chars None
t
ch t
tail_chars None
tail_pattern char
u
ch u
tail_chars None
v
ch v
tail_chars None
w
ch w
tail_chars None
x
ch x
tail_chars None
y
ch y
tail_chars None,y
tail_pattern motion
z
ch z
tail_chars -,.,<CR>,b,h,l,t,z
{
ch {
tail_chars None
|
ch |
tail_chars None
}
ch }
tail_chars None
~
ch ~
tail_chars None
.
----------------------------------------------------------------------
Ran 1 test in 0.126s
OK
QQQQQ
Here are the key points of this scheme:
1. The @data nodes are an extremely simple representation of vim's commands.
2. The corresponding dictionaries are the simplest thing that could
possibly work.
3. It will be straightforward to scan commands (and their prefixes!) using
these dicts.
The commands dict is the heart of the matter. It will be used to determine
valid inputs.
For example, lets take a look at the dump for the entry for d::
d
ch d
tail_chars d,None
tail_pattern motion
That is commands_dict.get('d') is *another* dictionary, say d2.
d2['ch'] = 'd'
d2['tail_chars'] = ['d',None]
d2['tail_pattern' = 'motion'
There was a lot of design work behind this structure!
As you can see, the tail_chars entry (in d2) is a list of two items.
The first item, 'd', represents the dd command. The command is formed by
concatenating the first item with the 'ch' entry in d2 (also 'd').
The second item is None. If the 'tail_pattern' entry is empty, this entry
represents the command whose name is simply the 'ch' entry in d2.
But in this case, the 'tail_pattern' value is 'motion'. This tells the
scanner that one of the entries represented by the motions_d dictionary
must follow the initial 'd'.
The result is that the scanner will look for one of two patterns:
dd
or
d motion
The scanner uses the motions_d dict in a similar manner to scan the motion
part of the pattern.
One more detail: the 'char', 'letter' and 'pattern' patterns used in @data
command-tails @data motion-tails are hard-coded into vc. I don't see much
reason to generalize them, but they could be if needed.
That's all there is to it!
The next step will be to write the scanner, and test it (with a unit test)
on hundreds of inputs.
Edward
--
You received this message because you are subscribed to the Google Groups
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/groups/opt_out.