Hotstrings with non-word characters like _

Propose new features and changes
neogna2
Posts: 586
Joined: 15 Sep 2016, 15:44

Hotstrings with non-word characters like _

Post by neogna2 » 07 Feb 2022, 15:34

This is a mix of question/discussion/wish but I think Help is the best place for it.

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
? (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.
Ok, but what if we only want to tweak the word-sensitivity by adding to and/or removing from the word character set?
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 "gg<Tab>" auto-replaces with 0
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 "ee<Tab>" auto-replaces with 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 := ""
}
But that can also be a hassle to deal with in scripts with a lot of hotstrings.

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
Where AlphaNum toggles the set a-zA-Z0-9 on/off from the words set and AddCharSet/RemoveCharSet adds/removes characters from the words set. That makes it possible to have scripts with lots of hotstrings with/without the "e_" prefix for example, without worrying about their line ordering or resorting to workaround 2 above.

What do you think?
Is something incorrectly described?
Is a better workaround already possible?
Do you like the feature suggestion?

neogna2
Posts: 586
Joined: 15 Sep 2016, 15:44

Re: Hotstrings with non-word characters like _

Post by neogna2 » 24 May 2022, 11:28

Tagging @lexikos ICYMI, since it was posted a while back and not in wish list section.
Last edited by gregster on 25 May 2022, 01:05, edited 1 time in total.
Reason: Topic moved from 'AutoHotkey v2 Help'.

Post Reply

Return to “Wish List”