-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAutoCommand.ahk
More file actions
369 lines (330 loc) · 9.87 KB
/
AutoCommand.ahk
File metadata and controls
369 lines (330 loc) · 9.87 KB
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
#SingleInstance, force
#Include lib/string-similarity.ahk
#Include lib/ACHelpers.ahk
Menu, Tray, Icon, black.ico, , 1
;RunAsAdmin() ;Added if ever needed to try to escalate to admin
Initialize()
Return
;What happens after you select a command
ProcessCommand(cmd) {
global ubbPath, lastCmd := cmd ;Store command
;Use UtilityBeltBroadcast if available
if(ubbPath && FileExist(ubbPath)) {
cmd := ubbPath . " " . cmd
Run, %cmd%,,hide
}
else {
;Store clipboard, pastes to chat, then restores the previous clipboard
oldClip := Clipboard
Clipboard := cmd
Send {enter}
Sleep 100
Send {ctrl down}v{ctrl up}
Sleep 100
Send {enter}
Clipboard := oldClip
}
}
;Filter on KeyUp (required vs OnChar to include backspace?)
FilterCommands(hook, char){
global minLength, x, y
display := hook.Input . ":" ;Menu of commands
;Check if enough has been typed to start narrowing the list
if(StrLen(hook.Input) >= minLength)
GetMenu(hook.Input, display)
;Specify location of tooltip
if(x)
ToolTip , % display, x, y
;Follow cursor
else
ToolTip , % display
}
;After finishing filtering choose a command using the menu made during filtering
ChooseCommand(hook){
global menu
if(menu.Count() == 1)
FillTemplateInput(menu[1])
else if (menu.Count() > 1) {
Input, selection, L1, {enter}, 1,2,3,4,5,6,7,8,9
if(selection > 0 && selection <= menu.Count())
FillTemplateInput(menu[selection])
}
ToolTip
}
FillTemplateInput(byref cmd) {
global templateExpression
;Fill in template parameters if enabled/while they exist
originalCmd := cmd
while(templateExpression) {
ToolTip, Templating: %originalcmd%`n%cmd%
paramStart := InStr(cmd, templateExpression)
if(paramStart <= 0)
break
Input, param,,{Enter}
cmd := StrReplace(cmd, templateExpression, param,,1)
}
;Process command after optional templating
ProcessCommand(cmd)
ToolTip
}
GetMenu(input, byref display){
global
menu := Array()
if(filterMode == 3) {
results := stringSimilarity.findBestMatch(input, commands)
for i, e in results.ratings
{
;Check for sufficient results or min rating
if(i >= maxResults || e.rating <= minRatingToMatch)
break
menu.Push(e.Target)
if(includeRating)
display := display . "`n" . i . " (" . e.Rating . "): " . e.target
else
display := display . "`n" . i . ": " . e.target
}
}
else {
menuIndex := 0
for i, e in commands
{
;Stop if max results already hit
if(menuIndex >= maxResults)
break
;True while command matches input
match := true
;Regex search
if(filterMode == 2)
match := RegExMatch(e, regexOptions . ")" . Input)
;Search terms split by whitespace
else if(useSplitTerms) {
for j, t in StrSplit(input, ["`n", A_Space, A_Tab]) {
if(!InStr(e, t)) {
match := false
break
}
}
}
;Default search
else
match := InStr(e, input)
;Add command if it's a match
if(match)
{
menu.Push(e) ;Store the command
display := display . "`n" . ++menuIndex . ": " . e
}
}
}
return menu
}
;Adds a command if it doesn't already exist/have newlines/is too large
AddCommand(cmd) {
global
if(StrLen(cmd) < 1 || StrLen(cmd) > 1000)
return
else if(InStr(cmd, "`n"))
return
else if(HasVal(commands, cmd))
return
FileAppend, `n%cmd%, %commandPath%
commands.Push(cmd)
}
;Trimming whitespace version
HasVal(haystack, needle) {
for i, e in haystack
{
if(needle == RegExReplace(e, "\s+$")) { ;Had issues with whitespace at the end and Trim wasn't picking it up with my known omission list
return i
}
}
return 0
}
Initialize() {
global
;;Settings
IniRead, maxResults, Config.ini, Settings, MaxResults, 5
if(maxResults > 9 || maxResults < 1) {
MsgBox For now menu results are constrained to 1-9. Setting to 5
maxResults := 5
}
IniRead, minLength, Config.ini, Settings, MinCharacters, 1
;Set tooltip position
x := -1, y := -1
IniRead, position, Config.ini, Settings, TooltipPosition, -1
pos := StrSplit(position,",")
if (pos[1] > 0 && pos[1] < A_ScreenWidth && pos[2] > 0 && pos[2] < A_ScreenHeight) {
x := Trim(pos[1]), y := Trim(pos[2])
}
;Set/use UBB
IniRead, ubbPath, Config.ini, Settings, UBBroadcastPath, -1
;Read in commands
IniRead, commandPath, Config.ini, Settings, CommandPath, Commands.txt
FileRead, commandFile, %commandPath%
commands := StrSplit(commandFile, ["`n"])
commandFile := "" ;Free memory
;Templating
IniRead, templateExpression, Config.ini, Settings, TemplateExpression, $$
;Filters
IniRead, useSplitTerms, Config.ini, Filters, UseSplitTerms, 0
IniRead, includeRating, Config.ini, Filters, IncludeRating, 1
IniRead, minRatingToMatch, Config.ini, Filters, MinRatingToMatch, 0
IniRead, regexOptions, Config.ini, Filters, RegexOptions, m
stringSimilarity := new stringsimilarity()
;Input: https://www.autohotkey.com/docs/commands/filterInputHook.htm
filterInputHook := InputHook("", "{Enter}", "")
filterInputHook.KeyOpt("{All}", "+N")
filterInputHook.OnKeyUp := Func("FilterCommands")
filterInputHook.OnEnd := Func("ChooseCommand")
RegisterHotkeysAndShortcuts()
}
RegisterHotkeysAndShortcuts(){
global
shortcutMap := Object() ;Maps a triggered hotkey to a command
;Set up global hotkeys/shortcuts
CreateHotkeysFromSection("Config.ini", "GlobalHotkeys")
CreateShortcutsFromSection("Config.ini", "GlobalShortcuts")
;Apply active window restrictions to hotkeys/shortcuts that aren't global
IniRead, activeWindows, Config.ini, Settings, ActiveWindows
if(StrLen(activeWindows) > 0) {
windows := StrSplit(activeWindows,",")
for i, e in windows {
GroupAdd, ValidWindow, %e%
}
Hotkey, IfWinActive, ahk_group ValidWindow
}
;Set up restricted hotkeys/shortcuts
CreateHotkeysFromSection("Config.ini", "Hotkeys")
CreateShortcutsFromSection("Config.ini", "Shortcuts")
}
CreateHotkeysFromSection(config, section) {
IniRead, keys, %config%, %section%
actionHotkeys := StrSplit(keys, "`n")
;MsgBox % "Setting up: " . actionHotkeys.Count() . " hotkeys`n" . keys
for i, hotkeyLine in actionHotkeys
{
kvp := StrSplit(hotkeyLine, "=")
action := kvp[1]
hotkeys := kvp[2]
;MsgBox % "KVP: " . action . ", " . hotkeys
keys := StrSplit(hotkeys, ",")
for j, e in keys
if(StrLen(e) > 0)
Hotkey, %e%, %action%
}
}
CreateShortcutsFromSection(config, section) {
global shortcutMap
IniRead, keys, %config%, %section%
shortcuts := StrSplit(keys, "`n")
;MsgBox % "Setting up: " . shortcuts.Count() . " shortcuts`n" . keys
for i, shortcutLine in shortcuts
{
kvp := StrSplit(shortcutLine, "=")
trigger := kvp[1]
command := kvp[2]
;MsgBox % "KVP: " . trigger . ", " . command
shortcutMap[trigger] := command
Hotkey, %trigger%, HandleShortcut
}
}
;;Shortcut
HandleShortcut:
FillTemplateInput(shortcutMap[A_ThisHotkey])
;MsgBox % "Shortcut: " . A_ThisHotkey . "::" . shortcutMap[A_ThisHotkey]
Return
;;Hotkey actions
CommandFilter:
filterMode := 1
filterInputHook.Start()
Return
RegexFilter:
filterMode := 2
filterInputHook.Start()
Return
StringDistanceFilter:
filterMode := 3
filterInputHook.Start()
Return
RepeatCommand:
if(StrLen(lastCmd) > 0)
ProcessCommand(lastCmd)
Return
ClearInput:
filterInputHook.OnEnd := ""
filterInputHook.Stop()
filterInputHook.OnEnd := Func("ChooseCommand")
filterInputHook.Start()
Return
AddCommand:
ToolTip, Adding typed command upon Enter
Input, newCommand,V, {Enter}
AddCommand(newCommand)
Return
AddClipboardAsCommand:
AddCommand(Clipboard)
Return
SortCommands:
Sort, commandFile, U
FileDelete, %commandPath%
FileAppend, %commandFile%, %commandPath%
Return
MaximizeAll:
MaximizeAll()
Return
BorderlessAll:
BorderlessAll()
Return
ClickAll:
MouseGetPos, mx, my
;MsgBox % mx . ", " . my
ClickAll(mx, my)
Return
Jump:
KeyPressAll("Space", 1)
Return
ReleaseJump:
KeyPressAll("Space", 2)
Return
Reload:
Reload
Return
Exit:
ExitApp
Return
RunAsAdmin(){
full_command_line := DllCall("GetCommandLine", "str")
if not (A_IsAdmin or RegExMatch(full_command_line, " /restart(?!\S)"))
{
try
{
if A_IsCompiled
Run *RunAs "%A_ScriptFullPath%" /restart
else
Run *RunAs "%A_AhkPath%" /restart "%A_ScriptFullPath%"
}
ExitApp
}
}
KeyWaitAny(Options:="")
{
ih := InputHook(Options)
if !InStr(Options, "V")
ih.VisibleNonText := false
ih.KeyOpt("{All}", "E") ; End
ih.Start()
ErrorLevel := ih.Wait() ; Store EndReason in ErrorLevel
return ih.EndKey ; Return the key name
}
; KeyWaitCombo(Options:="")
; {
; ih := InputHook(Options)
; if !InStr(Options, "V")
; ih.VisibleNonText := false
; ih.KeyOpt("{All}", "E") ; End
; ; Exclude the modifiers
; ih.KeyOpt("{LCtrl}{RCtrl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}", "-E")
; ih.Start()
; ErrorLevel := ih.Wait() ; Store EndReason in ErrorLevel
; return ih.EndMods . ih.EndKey ; Return a string like <^<+Esc
; }