-
Notifications
You must be signed in to change notification settings - Fork 1
/
TapAutoMod.ahk
108 lines (93 loc) · 2.19 KB
/
TapAutoMod.ahk
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
class TamState
{
__New(wk, keys, max)
{
this.Wk := wk
this.Count := 0
this.Max := max
this.Keys := keys
; this.Timer :=
}
IsMaxCount()
{
return this.Count == this.Max
}
TimerOff()
{
if (this.Timer)
{
oldFunc := this.Timer
SetTimer, % oldFunc, Off
}
this.Timer := ""
}
}
class TapAutoMod
{
__New(timeout := 150)
{
this._map := { 0: [""], 1: [""], 2: ["Ctrl"], 3: ["Alt"], 4: ["Ctrl", "Alt", "Shift"] }
this._state := { }
this._timeout := timeout
}
Tap(wk, keys, max)
{
if (!this._state.HasKey(keys))
{
this._state[keys] := new TamState(wk, keys, max)
}
; todo: is it possible to ignore repeaated key?
state := this._state[keys]
state.Count += 1
this.ResetTimer(state)
this.OnEachTap(state)
}
OnEachTap(state)
{
; when the current tap count == max,
; do the action and reset
if (state.IsMaxCount())
{
this.OnReset(state)
}
}
; reset timer and rebind function
ResetTimer(state)
{
state.TimerOff()
func := ObjBindMethod(this, "OnTimeout", state)
state.Timer := func
; negative for one-time timer
SetTimer, % func, % -this._timeout
}
OnTimeout(state)
{
; on timeout
; do the action and reset
this.OnReset(state)
}
OnReset(state)
{
keys := state.keys
mods := this._map[state.Count]
; wrap the key in all the specified modifiers
For idx, mod in mods {
mod := mods[A_Index]
keys := this.Wrap(keys, mod)
}
keys := this.Wrap(keys, state.Wk)
SendInput % keys
state.Count := 0
state.TimerOff()
}
; wk = wrapping key
Wrap(key, wk)
{
if (wk)
{
return "{" . wk . " down}" . key . "{" . wk . " up}"
} else {
return key
}
}
}