Skip to content

Commit

Permalink
add "*" option (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
8LWXpg committed Feb 11, 2023
1 parent dc79950 commit 89bc1c1
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 33 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Use `Space`, `Tab` or `Enter` to trigger RegExHotstring.
- calls function with RegEx match info
- RegExReplace string
- Options:
- \* (asterisk): An ending character (e.g. Space, Tab, or Enter) is not required to trigger the hotstring.
use *0 to turn this option back off.

- ? (question mark): The hotstring will be triggered even when it is inside another word;
that is, when the character typed immediately before it is alphanumeric.
Use ?0 to turn this option back off.
Expand Down
94 changes: 63 additions & 31 deletions RegExHotstring.ahk
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
#Requires AutoHotkey v2.0

RegHook := RegExHs("VI")
RegHook.VisibleText := false
RegHook.NotifyNonText := true
RegHook.KeyOpt("{Space}{Tab}{Enter}", "+SN")
RegHook.Start()

/**
* Create a RegEx Hotstring or replace already existing one
* @param {String} Str RegEx string
* @param {Func or String} CallBack calls function with RegEx match info or replace string
* @param {String} Options
*
*
* \* (asterisk): An ending character (e.g. Space, Tab, or Enter) is not required to trigger the hotstring.
* use *0 to turn this option back off.
*
* ? (question mark): The hotstring will be triggered even when it is inside another word;
* that is, when the character typed immediately before it is alphanumeric.
* Use ?0 to turn this option back off.
*
*
* B0 (B followed by a zero): Automatic backspacing is not done to erase the abbreviation you type.
* Use a plain B to turn backspacing back on after it was previously turned off.
*
*
* C: Case sensitive: When you type an abbreviation, it must exactly match the case defined in the script.
* Use C0 to turn case sensitivity back off.
*
*
* O: Omit the ending character of auto-replace hotstrings when the replacement is produced.
* Use O0 (the letter O followed by a zero) to turn this option back off.
*/
Expand All @@ -30,16 +33,19 @@ RegExHotstring(Str, CallBack, Options := "") {

class RegExHs extends InputHook {
; stores with RegEx string as key and obj as value
hs := Map()
; no "*" option
a0 := Map()
; with "*" option
a := Map()

class obj {
__New(string, call, options) {
this.call := call
this.str := string
this.opt := Map("?", false, "B", true, "C", false, "O", false)
this.opt := Map("*", false, "?", false, "B", true, "C", false, "O", false)
loop parse (options) {
switch A_LoopField {
case "?", "B", "C", "O":
case "*", "?", "B", "C", "O":
this.opt[A_LoopField] := true
case "0":
try
Expand All @@ -58,20 +64,57 @@ class RegExHs extends InputHook {

; append new RegExHotstring
Add(Str, CallBack, Options) {
this.hs[Str] := RegExHs.obj(Str, CallBack, Options)
info := RegExHs.obj(Str, CallBack, Options)
if (info.opt["*"]) {
try
this.a0.Delete(Str)
info.opt["O"] := true
this.a[Str] := info
} else {
try
this.a.Delete(Str)
this.a0[Str] := info
}
}

; clear input when press non-text key
OnKeyDown := this.keyDown
keyDown(vk, sc) {
if (vk = 8 || vk = 160 || vk = 161)
if (vk = 8) {
Send("{Blind}{vk08 down}")
return

if (vk != 32 && vk != 9 && vk != 13) {
this.Stop()
this.Start()
}
if (vk = 160 || vk = 161)
return

this.Stop()
this.Start()
}

OnKeyUp := this.keyUp
keyUp(vk, sc) {
if (vk = 8 || vk = 32 || vk = 9 || vk = 13)
Send("{Blind}{vk" Format("{:02x}", vk) " up}")
}

OnChar := this.Char
Char(c) {
; debug use
; ToolTip(this.Input)

vk := GetKeyVK(GetKeyName(c))
if (vk = 32 || vk = 9 || vk = 13) {
this.match(this.a0, vk, 0)
} else {
this.match(this.a, vk, 1)
}
}

match(map, vk, bs) {
if (!map.Count) {
Send("{Blind}{vk" Format("{:02x}", vk) " down}")
return
}
; find the last pattern without \s
if (!RegExMatch(this.Input, "(\S+)(?![\s\S]*(\S+))", &match)) {
this.Stop()
Expand All @@ -80,41 +123,30 @@ class RegExHs extends InputHook {
return
}
input := match[1]
this.Stop()
; loop through each strings and find the first match
for , obj in this.hs {
for , obj in map {
str := obj.str
call := obj.call
opt := obj.opt
start := RegExMatch(input, str, &match)
if (start) {
if (opt["B"])
Send("{BS " match.Len[0] "}")
Send("{BS " match.Len[0] - bs "}")
if (call is String) {
this.Stop()
Send(RegExReplace(SubStr(input, start), str, call))
if (!opt["O"])
Send("{Blind}{vk" Format("{:02x}", vk) " down}")
this.Start()
} else if (call is Func) {
this.Stop()
call(match)
this.Start()
} else
throw TypeError('CallBack type error `nCallBack should be "Func" or "String"')
this.Start()
return
}
}
Send("{Blind}{vk" Format("{:02x}", vk) " down}")
this.Start()
}

OnKeyUp := this.keyUp
keyUp(vk, sc) {
if (vk = 32 || vk = 9 || vk = 13)
Send("{Blind}{vk" Format("{:02x}", vk) " up}")
}

; debug use
/* OnChar := this.Char
Char(c) {
ToolTip(this.Input)
} */
}
7 changes: 5 additions & 2 deletions demo.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@
#Include RegExHotstring.ahk
#SingleInstance Force

; the upmost function will be triggered if it has the same expression
; the upmost function will be triggered first

; replace with regex string
RegExHotstring("(\w+)a", "b$1", "C")
RegExHotstring("(\w)a(\w)", "$2a$1")
RegExHotstring("(\w)a(\w)", "$2a$1", "*")
RegExHotstring("(\d+)(\w+)", "$2$1", "O?B0")

; use anonymous function
RegExHotstring("(\w+)b", (match) => MsgBox("matched: " match[1]))

; modify callback and options
^!a:: RegExHotstring("(\w+)a", (match) => MsgBox("matched: " match[1]), "*")

; call with function name
RegExHotstring("(\w*)c", call)
RegExHotstring("r(\d+)s", rand)
Expand Down

0 comments on commit 89bc1c1

Please sign in to comment.