Hotstrings by default do not fire if the character preceding the recognized pattern is a word character. For example
::btw::by the way
will not fire if we type "abtw" because "btw" is preceded by "a".
We can override that default with option ? like this
:?:btw::by the way
as documented at https://lexikos.github.io/v2/docs/Hotstrings.htm#Options
Ok, but what if we only want to tweak the word-sensitivity by adding to and/or removing from the word character set?? (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.
For example consider the following script. (Nonsense hotstrings for simplicity. In real cases characters like _ - . can be part of e.g. variables, filenames and tags that we might want hotstrings for.)
Code: Select all
::gg::0
::ffgg::1
::ee::0
::e_ee::1
Typing "ffgg<Tab>" auto-replaces with 1
So far so good.
Typing "ee<Tab>" auto-replaces with 0
Typing "e_ee<Tab>" auto-replaces with 0 too, which is not what we wanted.
This happens because "_" is not a word character which means that the "ee" that follows it triggers hotstring ::ee::
We did type "e_ee" so hotstring ::e_ee:: was also eligible to fire. But when the same character (in this case the last "e" that we typed) makes 2+ hotstrings eligible to fire AutoHotkey only fires the one among them that is earliest in the script (closest to the script's first line). In this case ::ee::
Workaround 1
We can avoid the issue in the previous example by switching the hotstring line positions
Code: Select all
::e_ee::1
::ee::0
Typing "e_ee<Tab>" auto-replaces with 1 (both hotstrings are eligible but only ::e_ee:: fires because earliest)
But in a script with a large number of hotstrings it can be a hassle to keep track of their line number order.
Workaround 2
We can split hotstrings that contain "_" into two steps with the help of a few options and functions
Code: Select all
;hotstring options:
;X execute function or expression instead of text auto-replace
;* fire without ending char
;Z reset hotstring recognizer on fire
;b0 disable auto backspacing
global Prefix := ""
:X:hh::HS()
:X*Zb0:h_::Cache("h_")
Cache(Param) {
global Prefix := Param
}
HS() {
global Prefix
if IsSet(Prefix)
{
Send("{BackSpace " StrLen(Prefix) "}")
Send(1)
}
else
Send(0)
Prefix := ""
}
Which brings me to...
Feature request
Hotstrings already has the option EndChars to edit the set of ending characters.
I wish we similarly had the option WordChars to edit the set of word characters. The syntax could be something like this
Code: Select all
#Hotstring WordChars(AlphaNum := 1, AddCharSet := "_", RemoveCharSet := "")
::ee::0
::e_ee::1
What do you think?
Is something incorrectly described?
Is a better workaround already possible?
Do you like the feature suggestion?