-
Notifications
You must be signed in to change notification settings - Fork 0
/
frmGrabKeys.frm
executable file
·703 lines (587 loc) · 23.1 KB
/
frmGrabKeys.frm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
VERSION 5.00
Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} frmGrabKeys
Caption = "Run Vim command"
ClientHeight = 3015
ClientLeft = 120
ClientTop = 465
ClientWidth = 4560
OleObjectBlob = "frmGrabKeys.frx":0000
StartUpPosition = 1 'CenterOwner
End
Attribute VB_Name = "frmGrabKeys"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
' frmGrabKeys: collect keypresses and parse Vim commands
' Copyright (c) 2018--2019 Chris White. All rights reserved.
' See changelog in mVimWord for other changes
' 2018-04-06 chrisw Initial version
' 2018-04-20 chrisw Major expansion/rewrite
' 2018-04-24 chrisw Change "s" to "v" (visual selection)
' 2018-04-26 chrisw Changed regex from hand-generated to re2vba.pl
' 2018-05-02 chrisw Refactored motion code into ProcessMotion_
' 2018-05-07 chrisw Added ninja-feet; refactored regex
' 2018-05-12 chrisw Added x X .
' 2018-06-07 chrisw Added VSpace. Also, changed IsEmpty checks to
' Len>0 checks. I had a situation in which a non-match
' returned "" rather than Empty.
' Added special-case code for 0 after nonempty count2.
' 2018-06-29 chrisw Changed X from `dh` to voDrop.
' `dh` is still available if you need it.
' 2018-07-16 chrisw Added VHas*Count to support G (vmLine)
' 2018-08-18 chrisw Removed VimRegister enum; added register regex and VRegister
' 2018-09-19 chrisw Added vmMSWordSelection
' 2019-06-21 chrisw Added vm[AI]LineDelimBlock
' NOTE: the consolidated reference is in :help normal-index
Option Explicit
Option Base 0
' Vim support
'Public Enum VimRegister ' from :help registers
' vrUndef
' vrUnnamed ' "
' vr0
' vr1
' vr2
' vr3
' vr4
' vr5
' vr6
' vr7
' vr8
' vr9
' vrSmallDelete ' -
' vrA
' vrB
' vrC
' vrD
' vrE
' vrF
' vrG
' vrH
' vrI
' vrJ
' vrK
' vrL
' vrM
' vrN
' vrO
' vrP
' vrQ
' vrR
' vrS
' vrT
' vrU
' vrV
' vrW
' vrX
' vrY
' vrZ
' vrColon
' vrDot
' vrFilename ' %
' vrLastFilename ' #
' vrExpression ' =
' vrClipboard ' * Win clipboard; X selection
' vrPlus ' + Win clipboard; X clipboard
' vrTilde ' dropped text from last drag-and-drop
' vrBlackHole ' underscore
' vrLastPattern ' /
'End Enum 'VimRegister
Public Enum VimCommand ' Intransitive commands
' thanks to https://www.fprintf.net/vimCheatSheet.html and :help change.txt
vcUndef
vcRepeat ' .
' Note: intransitive motions (e.g., 0, ^, $) are handled with a fake operator voGo.
'vcAppend ' a
'vcAppendEOL ' A
'vcInsert ' i
'vcInsertSOT ' I
'vcReplace ' R
'vcOpen ' o
'vcOpenAbove ' O
' TODO D, C, s, S - here, or by remapping.
' TODO implement registers
' Pastes. NOTE: These behave a bit differently from Vim because
' Word puts the cursor between letters instead of on letters.
' PutAfter: Word's paste (paste at cursor; cursor to end of pasted text)
' PutBefore: paste at cursor; leave cursor at start of pasted text
' PutAfterG and PutBeforeG: same, but paste as unformatted text.
vcPutAfter ' p
vcPutBefore ' P
vcPutAfterG 'gp
vcPutBeforeG 'gP
' TODO gp, gP, ]p, [p, ]P, [P
'vcUndo ' u
'vcRedo ' Ctl+R
'vcUndoLine ' U No plans to implement this - I don't think Word gives me the necessary control.
' TODO z., zt, zb, z+, z-
' TODO /, ?
'vcSearchNext ' n
'vcSearchPrev ' N
' *, #, g*, g# Search based on Word's idea of a word
' gW*, gW#, gWg*, gWg# Search based on a WORD (not in Vim).
' In Vim, gW is unused. I am using it by analogy with W.
' However, sometimes gW* === gWg*, and gW# === gWg#, because Word
' doesn't respect SearchWholeWord if the search text has multiple
' words as defined by Word.
vcSearchWholeItemForward ' *, gW*
vcSearchWholeItemBackward ' #, gW#
vcSearchItemForward ' g*, gWg*
vcSearchItemBackward ' g#, gWg#
' TODO J, gJ
End Enum 'VimCommand
Public Enum VimOperator
voUndef
voGo ' Placeholder for motions, which don't have an operator.
'voReplaceChar ' r (more like an operator than anything else) (maybe?)
' TODO m, ', ` here?
' Operators from :help operator
voChange ' c
voDelete ' d
voYank ' y
voSelect ' v Select <motion>.
voDrop ' X (Not in Vim): delete without yanking
'voSwitchCase ' ~/g~ unimpl
' TODO Maybe a custom titlecase on g~?
'voLowercase ' gu unimpl
'voUppercase ' gU unimpl
'voFilter ' ! No plans to implement this.
'voEqualPrg ' = No plans to implement this.
'voFormatLines ' gq No plans to implement this.
'voFormatLinesNoMove ' gw No plans to implement this.
'voROT13 ' g? No plans to implement this.
'voSHR ' > No plans to implement this.
'voSHL ' < No plans to implement this.
'voDefineFold ' zf No plans to implement this.
'voCallFunc ' g@ No plans to implement this.
End Enum 'VimOperator
'Public Enum VimForce ' adverb - No plans to implement this
' vfUndef
' vfCharacterwise
' vfLinewise
'End Enum 'VimForce
Public Enum VimMotion ' Motions/objects/direct objects of transitive operators
vmUndef
' Marks - TODO the rest of :help mark-motions
'vmMark ' '
'vmMarkExact ' `
' Searches
'vmSearchDown ' /
'vmSearchUp ' ?
'vmSearchNext ' n
'vmSearchPrev ' N
' Objects from :help visual-operators
vmAWord ' aw
vmIWord ' iw
vmANonblank ' aW
vmINonblank ' iW
vmASentence ' as
vmISentence ' is
vmAPara ' ap (includes Chr(13))
vmIPara ' ip (not Chr(13))
vmALineDelimBlock ' aB (not in Vim)
vmILineDelimBlock ' iB (not in Vim)
' ab/ib () Not yet implemented
' a{/i{ {} "
' at/it " <tag></tag>
' a</i< <> "
' a[/i[ [] "
' a"/i" " Double-quoted string
' a'/i' " Single-quoted string
' a`/i` " Backtick-quoted string
' Motions from :help left-right-motions
vmLeft ' h
vmRight ' l
vmStartOfParagraph ' 0 Note: using slightly differently than in Vim.
vmStartOfLine ' ^
vmEOL ' $ Note: can take a count, in which case it goes count-1 lines downward inclusive
vmEOParagraph ' g$ Note: using slightly differently than in Vim. Can take a count.
' g_, g0, g^, gm: Not yet implemented.
vmColumn ' |
vmCharForward ' f
vmCharBackward ' F
vmTilForward ' t
vmTilBackward ' T
' TODO? ; ,
' :help up-down-motions
vmUp ' k
vmDown ' j
' gk, gj, -, +: Not yet implemented
vmUnderscore ' for dd, yy, cc === d_, y_, c_
vmLine ' G ' TODO decide how to implement this; implement goto para/page
' gg (G, but not a jump) unimpl
' % (goto percentage), go (byte offset) unimpl
' :help word-motions
vmWordForward ' w exclusive
' TODO: operator+w and last word is at end of line => stop at end of word
vmNonblankForward ' W excl
vmEOWordForward ' e inclusive
vmEONonblankForward ' E incl
vmWordBackward ' b excl
vmNonblankBackward ' B excl
vmEOWordBackward ' ge incl
vmEONonblankBackward ' gE incl
' :help object-motions
vmSentenceForward ' )
vmSentenceBackward ' (
vmParaForward ' }
vmParaBackward ' {
vmSectionForward ' ]] or ][ (NOTE: not distinguishing the two)
vmSectionBackward ' [[ or [] (NOTE: not distinguishing the two)
' :help various-motions
'vmPercent ' %
'vmPrevParen ' [(
'vmPrevBrace ' [{
'vmNextParen ' ])
'vmNextBrace ' ]}
' ]m ]M [m [M next/prev start/END of method
' [# prev #if/#else
' ]# next #else/#endif
' [* [/ ]( ]/ C comment jumps
' H, M, L - move within currently visible text. Count is line number for H and L.
vmScreenTop
vmScreenMiddle
vmScreenBottom
' Custom (not in Vim) (TODO)
'vmRevisionForward
'vmRevisionBackward
'vmARevision
'vmIRevision
vmMSWordSelection ' Chr(13) as a motion, for want of a better choice.
End Enum 'VimMotion
'
Public Enum VimNinja ' https://github.com/tommcdo/vim-ninja-feet
vnUndef
vnLeft ' ninja-feet [
vnRight ' ninja-feet ]
End Enum 'VimNinja
'
' TODO: cw/cW is like ce/cE if cursor is on a non-blank
' TODO implement marks
' TODO implement jumps
Public WasCancelled As Boolean
Public Keys As String
' The parts of the received command
Public VRegister As String ' Note: uppercase registers not yet supported
Public VOperator As VimOperator
Public VCommand As VimCommand
Public VMotion As VimMotion
Public VOperatorCount As Long
Public VHasOperatorCount As Boolean
Public VMotionCount As Long
Public VHasMotionCount As Boolean
Public VArg As String
Public VNinja As VimNinja
Public VSpace As Boolean
Private DotCount_ As Long ' Count on a `.`
' Regexp
Private RE_ACT As VBScript_RegExp_55.RegExp
' Submatch numbers - see vim-regex.txt
Private RESM_REGISTER As Long
Private RESM_SPACEONE As Long
Private RESM_COUNT1 As Long
Private RESM_SPACETWO As Long
Private RESM_IVERB As Long
Private RESM_IMOTION As Long
Private RESM_ITEXT As Long
Private RESM_TVERB As Long
Private RESM_COUNT2 As Long
Private RESM_TARGET As Long
Private RESM_NINJA As Long
Private RESM_TOBJ_RANGE As Long
Private RESM_OBJTYPE As Long
Private RESM_TTEXT As Long
Private RESM_TVERBABBR As Long
Private RE_PAT As String
'
Private Sub UserForm_Initialize()
WasCancelled = False
Keys = vbNullString
VRegister = vbNullString
VOperator = voUndef
VCommand = vcUndef
VMotion = vmUndef
VOperatorCount = 1
VHasOperatorCount = False
VMotionCount = 1
VHasMotionCount = False
VArg = vbNullString
VNinja = vnUndef
VSpace = False
DotCount_ = 1
Dim RE_PAT As String
' === Build up the regex ===
' The following code is from the output of `re2vba.pl vim-regex.txt`.
' DO NOT MODIFY HERE. If you need to change it, modify vim-regex.txt
' and re-run re2vba.pl.
RE_PAT = _
"^((\""([0-9a-z]))?([ ]?)([1-9][0-9]*)?(([ ]?)(([HMLGhjklwbWB" & _
"\x28\x29\x7b\x7d]|g?[eE0\^\$]|\x0d|[fFtT](.))|(gW)?g?[\*#]|g" & _
"?[pP])|([cdyvX])([1-9][0-9]*)?(([\[\]])?([ai])([wWspB])|[fFt" & _
"T](.)|[HMLGhjklwbWB\x28\x29\x7b\x7d]|g?[eE0\^\$]|\x0d)|([x\." & _
"])))$" & _
""
RESM_REGISTER = 2
RESM_SPACEONE = 3
RESM_COUNT1 = 4
RESM_SPACETWO = 6
RESM_IVERB = 7
RESM_IMOTION = 8
RESM_ITEXT = 9
RESM_TVERB = 11
RESM_COUNT2 = 12
RESM_TARGET = 13
RESM_NINJA = 14
RESM_TOBJ_RANGE = 15
RESM_OBJTYPE = 16
RESM_TTEXT = 17
RESM_TVERBABBR = 18
' End of generated code
' =============================
Set RE_ACT = New VBScript_RegExp_55.RegExp
RE_ACT.IgnoreCase = False
RE_ACT.Pattern = RE_PAT
End Sub 'UserForm_Initialize
'
Private Sub btnCancel_Click()
WasCancelled = True
Me.Hide
End Sub
Private Sub UserForm_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If KeyAscii = vbKeyReturn Then
Keys = Keys & Chr(13)
Update
Me.Hide
ElseIf KeyAscii = vbKeyBack Then
If Len(Keys) > 0 Then
Keys = Left(Keys, Len(Keys) - 1)
Update
End If
ElseIf KeyAscii >= 32 And KeyAscii <= 127 Then
Keys = Keys & Chr(KeyAscii)
Update
End If
End Sub 'KeyPress
' Main workers ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Function ProcessMotion_(motion As String) As Boolean
' Return true iff #motion is an understood no-argument motion.
' Sets VMotion on success. Does not handle text objects or motions
' with arguments (fFtT).
ProcessMotion_ = True
Select Case motion
Case "H": VMotion = vmScreenTop
Case "M": VMotion = vmScreenMiddle
Case "L": VMotion = vmScreenBottom
Case "G": VMotion = vmLine
Case "h": VMotion = vmLeft
Case "j": VMotion = vmDown
Case "k": VMotion = vmUp
Case "l": VMotion = vmRight
Case "w": VMotion = vmWordForward
Case "b": VMotion = vmWordBackward
Case "W": VMotion = vmNonblankForward
Case "B": VMotion = vmNonblankBackward
Case ")": VMotion = vmSentenceForward
Case "(": VMotion = vmSentenceBackward
Case "}": VMotion = vmParaForward
Case "{": VMotion = vmParaBackward
Case "e": VMotion = vmEOWordForward
Case "E": VMotion = vmEONonblankForward
Case "ge": VMotion = vmEOWordBackward
Case "gE": VMotion = vmEONonblankBackward
Case "0": VMotion = vmStartOfParagraph
Case "^": VMotion = vmStartOfLine
Case "$": VMotion = vmEOL
'Case "g0": VMotion = vmStartOfParagraph ' TODO decide what this should do
'Case "g^": VMotion = vmStartOfLine ' TODO decide what this should do
Case "g$": VMotion = vmEOParagraph
Case Chr(13): VMotion = vmMSWordSelection
Case Else: ProcessMotion_ = False
End Select
End Function 'ProcessMotion_
'
Private Function ProcessHit_(hit As VBScript_RegExp_55.Match) As Boolean
' Returns true if parse succeeded
ProcessHit_ = False
' Consistent values at the start
VRegister = vbNullString
VOperator = voUndef
VCommand = vcUndef
VMotion = vmUndef
VOperatorCount = 1
VHasOperatorCount = False
VMotionCount = 1
VHasMotionCount = False
VArg = vbNullString
VNinja = vnUndef
VSpace = False
' Don't change DotCount_, which is set by Update()
' Internal variables so we can alias, e.g., `x` to `dl`
Dim tverb As Variant: tverb = hit.SubMatches(RESM_TVERB)
Dim target As Variant: target = hit.SubMatches(RESM_TARGET)
' Special-case "0" in code so that I don't have to special-case it in the
' regex. A non-empty count preceding a "0" command means that the "0"
' should actually be part of the count, so wait for more keys.
If ((Len(hit.SubMatches(RESM_COUNT1)) > 0) And (hit.SubMatches(RESM_IMOTION) = "0")) Or _
((Len(hit.SubMatches(RESM_COUNT2)) > 0) And (hit.SubMatches(RESM_TARGET) = "0")) _
Then ' ^ Empty decays to ""
Exit Function
End If
If (Len(hit.SubMatches(RESM_REGISTER)) > 0) Then
VRegister = hit.SubMatches(RESM_REGISTER)
End If
' Check for <Space> indicators
If (Len(hit.SubMatches(RESM_SPACEONE)) > 0) Or _
(Len(hit.SubMatches(RESM_SPACETWO)) > 0) Then
VSpace = True
End If
' Count before the command, if any
If Len(hit.SubMatches(RESM_COUNT1)) = 0 Then
' Note: works because Len(Empty) returns 0
VOperatorCount = 1
Else
VOperatorCount = CLng(hit.SubMatches(RESM_COUNT1))
VHasOperatorCount = True
End If
If Len(hit.SubMatches(RESM_TVERBABBR)) > 0 Then ' transitive, abbreviated
Select Case hit.SubMatches(RESM_TVERBABBR)
' `.`: succeed early - VCommand and VOperatorCount are the only things that matter
Case ".":
VCommand = vcRepeat
DotCount_ = VOperatorCount
ProcessHit_ = True
Exit Function
' `x`: alias to `dl`
Case "x": tverb = "d": target = "l"
Case Else: Exit Function
End Select
End If
' Apply the dot count, if any
VOperatorCount = VOperatorCount * DotCount_
DotCount_ = 1
If Len(hit.SubMatches(RESM_IVERB)) > 0 Then ' intransitive
'Debug.Print "Intransit.", IIf(Len(hit.SubMatches(RESM_IMOTION)) = 0, "-", hit.SubMatches(RESM_IMOTION)), _
' hit.SubMatches(RESM_IVERB), hit.SubMatches(RESM_ITEXT)
If Len(hit.SubMatches(RESM_IMOTION)) > 0 Then
If ProcessMotion_(hit.SubMatches(RESM_IMOTION)) Then
VOperator = voGo
Else
Select Case Left(hit.SubMatches(RESM_IVERB), 1)
Case "f": VOperator = voGo: VMotion = vmCharForward: VArg = hit.SubMatches(RESM_ITEXT)
Case "F": VOperator = voGo: VMotion = vmCharBackward: VArg = hit.SubMatches(RESM_ITEXT)
Case "t": VOperator = voGo: VMotion = vmTilForward: VArg = hit.SubMatches(RESM_ITEXT)
Case "T": VOperator = voGo: VMotion = vmTilBackward: VArg = hit.SubMatches(RESM_ITEXT)
Case Else: Exit Function
End Select
End If
Else ' Not a motion, so it's a search or a paste
Select Case hit.SubMatches(RESM_IVERB)
' Searches
Case "*": VCommand = vcSearchWholeItemForward: VMotion = vmIWord
Case "#": VCommand = vcSearchWholeItemBackward: VMotion = vmIWord
Case "g*": VCommand = vcSearchItemForward: VMotion = vmIWord
Case "g#": VCommand = vcSearchItemBackward: VMotion = vmIWord
Case "gW*": VCommand = vcSearchWholeItemForward: VMotion = vmINonblank
Case "gW#": VCommand = vcSearchWholeItemBackward: VMotion = vmINonblank
Case "gWg*": VCommand = vcSearchItemForward: VMotion = vmINonblank
Case "gWg#": VCommand = vcSearchItemBackward: VMotion = vmINonblank
' Pastes
Case "p": VCommand = vcPutAfter
Case "P": VCommand = vcPutBefore
Case "gp": VCommand = vcPutAfterG
Case "gP": VCommand = vcPutBeforeG
Case Else: Exit Function
End Select
End If 'a motion else
ElseIf Len(tverb) > 0 Then ' transitive
'Debug.Print "Transitive", tverb, hit.SubMatches(RESM_COUNT2), Left(target, 1), hit.SubMatches(RESM_OBJTYPE), hit.SubMatches(RESM_TTEXT)
' Operator
Select Case tverb
Case "c": VOperator = voChange
Case "d": VOperator = voDelete
Case "y": VOperator = voYank
Case "v": VOperator = voSelect ' V, i.e., visual selection - just like in Vim.
Case "X": VOperator = voDrop ' X, repurposed from Vim.
Case Else: Exit Function
End Select
' Post-operator count
If Len(hit.SubMatches(RESM_COUNT2)) = 0 Then
VMotionCount = 1
Else
VMotionCount = CLng(hit.SubMatches(RESM_COUNT2))
VHasMotionCount = True
End If
' Process the motion
If ProcessMotion_(CStr(target)) Then ' Motion without argument
' Nothing more to do
ElseIf Len(hit.SubMatches(RESM_TOBJ_RANGE)) > 0 Then ' Text object
Select Case hit.SubMatches(RESM_TOBJ_RANGE)
Case "a":
Select Case hit.SubMatches(RESM_OBJTYPE)
Case "w": VMotion = vmAWord
Case "W": VMotion = vmANonblank
Case "s": VMotion = vmASentence
Case "p": VMotion = vmAPara
Case "B": VMotion = vmALineDelimBlock
Case Else: Exit Function
End Select
Case "i":
Select Case hit.SubMatches(RESM_OBJTYPE)
Case "w": VMotion = vmIWord
Case "W": VMotion = vmINonblank
Case "s": VMotion = vmISentence
Case "p": VMotion = vmIPara
Case "B": VMotion = vmILineDelimBlock
Case Else: Exit Function
End Select
Case Else: Exit Function
End Select
If Len(hit.SubMatches(RESM_NINJA)) > 0 Then
VNinja = IIf(hit.SubMatches(RESM_NINJA) = "[", vnLeft, vnRight)
End If
Else ' Not a text object, so it's a motion with argument
Select Case Left(target, 1)
Case "f": VMotion = vmCharForward: VArg = hit.SubMatches(RESM_TTEXT)
Case "F": VMotion = vmCharBackward: VArg = hit.SubMatches(RESM_TTEXT)
Case "t": VMotion = vmTilForward: VArg = hit.SubMatches(RESM_TTEXT)
Case "T": VMotion = vmTilBackward: VArg = hit.SubMatches(RESM_TTEXT)
Case Else: Exit Function
End Select
End If
Else ' Neither intransitive nor transitive
MsgBox "This shouldn't happen - no iverb or tverb. Send a screenshot of this box to Chris White: -" & hit.Value & "-", vbExclamation, "VimWord"
Exit Function
End If 'intransitive else transitive else
ProcessHit_ = True ' If we made it here, the parse was successful
End Function ' ProcessHit_
'
' Update the state based on Keys. Called in response to a keypress.
Private Sub Update()
Dim done As Boolean: done = False
Dim times_through As Long: times_through = 0 'deadman
lblKeys.Caption = Replace(Keys, " ", ChrW(&H2423)) ' Make spaces visible
' parse Vim commands to see if one is done
Dim matches As VBScript_RegExp_55.MatchCollection
Dim hit As VBScript_RegExp_55.Match
DotCount_ = 1 ' In case we have a . this time
Do
'Debug.Print "Checking -" & CStr(Keys) & "-"
times_through = times_through + 1
Set matches = RE_ACT.Execute(Keys)
If matches.count < 1 Then Exit Do
Set hit = matches.Item(0)
If hit.SubMatches.count < 1 Then Exit Do
'Debug.Print "Matched:", hit.Value
done = ProcessHit_(hit) ' Assigns DotCount_ on a `.`
'If done Then Debug.Print vbNullString, "operator count:", VOperatorCount
If done And (VCommand = vcRepeat) And Len(VimLastCommand_) > 0 Then
Keys = VimLastCommand_
done = False ' process it next time through the loop
End If
Loop Until done Or (times_through >= 2)
If done Then
If VCommand <> vcRepeat Then VimLastCommand_ = Keys
Me.Hide
End If
End Sub 'Update