Trigger representations¶
This module owns conversion between semantic trigger text and deterministic, minimally escaped AutoHotkey source spelling, plus the reusable case-insensitive comparison key derived from semantic text.
The semantic-to-AHK and AHK-to-semantic helpers are intentionally asymmetric with respect to source spelling: multiple valid AHK spellings can normalize to one canonical source representation.
trigger ¶
Normalize AutoHotkey hotstring trigger source and matching representations.
The project keeps two distinct trigger representations:
- a semantic trigger, containing the actual characters AutoHotkey should recognize;
- an AHK trigger, containing a deterministic, minimally escaped source spelling suitable for use inside a hotstring declaration.
The conversion helpers in this module are the single source of truth for moving between those representations. The conversion is intentionally asymmetric with respect to source spelling: multiple valid AHK spellings may decode to the same semantic trigger, while semantic-to-AHK conversion always emits one canonical minimally escaped spelling.
Case-insensitive matching also lives here because it must operate on semantic trigger text rather than escaped AHK source spelling.
_SEMANTIC_TO_AHK_ESCAPE
module-attribute
¶
_SEMANTIC_TO_AHK_ESCAPE: Final[dict[str, str]] = {
"`": "``",
"\n": "`n",
"\r": "`r",
"\x08": "`b",
"\t": "`t",
"\x0b": "`v",
"\x07": "`a",
"\x0c": "`f",
}
AHK source escapes for semantic characters that always require escaping.
_AHK_ESCAPE_TO_SEMANTIC
module-attribute
¶
_AHK_ESCAPE_TO_SEMANTIC: Final[dict[str, str]] = {
"`": "`",
"n": "\n",
"r": "\r",
"b": "\x08",
"t": "\t",
"s": " ",
"v": "\x0b",
"a": "\x07",
"f": "\x0c",
":": ":",
";": ";",
}
Known AHK escape suffixes and the semantic characters they represent.
semantic_to_ahk_trigger ¶
Convert a semantic hotstring trigger to canonical AutoHotkey source text.
The semantic trigger contains the actual characters that AutoHotkey should recognize. This function converts that value into a minimally escaped, deterministic representation suitable for use as the trigger portion of an AutoHotkey hotstring declaration.
Conversion is performed in two stages.
First, characters which always require AutoHotkey escaping are converted
according to _SEMANTIC_TO_AHK_ESCAPE. All other ordinary characters are
preserved unchanged.
Second, characters whose escaping requirements depend on their surrounding AutoHotkey source are handled:
-
A semicolon is escaped only when immediately preceded by a literal space, because in that position it would otherwise begin an AutoHotkey comment. Semantic tab characters do not require special handling here because they were already converted to
`tduring the first stage. -
Colons are escaped only where necessary to prevent an unescaped
::sequence from appearing in the trigger or between the trigger and the hotstring declaration delimiter. A temporary trailing colon represents the first colon of that delimiter while the trigger is processed. Consecutive colons are then scanned from right to left, alternating between literal and escaped forms. The temporary colon is removed before returning the result.
This produces a canonical representation without unnecessarily escaping colons or semicolons.
The supported round-trip invariant is:
ahk_to_semantic_trigger(semantic_to_ahk_trigger(value)) == value
for every semantic trigger accepted by this function. The reverse source round trip is intentionally not required because AutoHotkey can accept multiple equivalent source spellings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
str
|
The semantic hotstring trigger containing the actual characters that should be recognized. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The trigger encoded for use in an AutoHotkey hotstring declaration. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
Examples:
An ordinary colon does not require escaping:
foo:bar -> foo:bar
A trailing colon must be escaped because the hotstring declaration's
closing :: immediately follows it:
foo: -> foo`:
Consecutive colons are escaped only as needed to prevent an unescaped
:: sequence:
foo::bar -> foo`::bar
A semicolon following a space must be escaped:
foo ;bar -> foo `;bar
A semicolon without a preceding space remains literal:
foo;bar -> foo;bar
Source code in hotstring\core\trigger.py
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 | |
ahk_to_semantic_trigger ¶
Convert an AutoHotkey source trigger to its semantic trigger text.
The input is the trigger portion exactly as represented in AutoHotkey source syntax. Escape sequences are decoded so the returned string contains the actual characters AutoHotkey recognizes as the hotstring trigger.
The function scans the source from left to right. Ordinary characters are
copied unchanged. When an AutoHotkey escape character (`) is
encountered, it is consumed together with the character immediately
following it.
Recognized AutoHotkey escape sequences are converted to their corresponding
semantic characters according to _AHK_ESCAPE_TO_SEMANTIC. This includes
control-character escapes such as `n and `t, as well as source
escapes such as , : ``, and ``; ``.
AutoHotkey's `s escape is also decoded to a literal space, even
though semantic_to_ahk_trigger() does not emit `s when producing
its canonical source representation.
If the escaped character does not have a special entry in
_AHK_ESCAPE_TO_SEMANTIC, the escape character itself is discarded and
the following character is preserved literally. This allows valid
unnecessary escaping in existing AutoHotkey source to normalize to the
same semantic trigger.
Because multiple valid AutoHotkey source spellings can represent the same
semantic trigger, this conversion is intentionally not the exact inverse
of semantic_to_ahk_trigger() with respect to source spelling. Instead,
the important round-trip invariant is:
ahk_to_semantic_trigger(semantic_to_ahk_trigger(value)) == value
Converting existing AutoHotkey source to semantic form and then back to source form may therefore change its spelling by canonicalizing unnecessary or optional escapes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
str
|
The trigger text as written in an AutoHotkey hotstring declaration,
excluding the surrounding option and |
required |
Returns:
| Type | Description |
|---|---|
str
|
The semantic trigger containing the actual characters recognized by |
str
|
AutoHotkey. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
Examples:
Ordinary characters require no decoding:
foo.bar -> foo.bar
An escaped colon becomes a literal semantic colon:
foo`:bar -> foo:bar
An unescaped isolated colon has the same semantic meaning:
foo:bar -> foo:bar
An escaped semicolon becomes a literal semicolon:
foo `;bar -> foo ;bar
AutoHotkey control-character escapes are converted to the actual
semantic character. For example, `t becomes a tab:
foo`tbar -> foo<TAB>bar
The AutoHotkey space escape is accepted and normalized to an ordinary semantic space:
foo`sbar -> foo bar
A doubled backtick represents one semantic backtick:
foo``bar -> foo`bar
Different valid source spellings can therefore produce the same semantic value:
foo:bar -> foo:bar
foo`:bar -> foo:bar
Source code in hotstring\core\trigger.py
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 | |
_python_case_insensitive_key ¶
Return the non-Windows fallback case-insensitive comparison key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
Semantic trigger text. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Python lowercase representation used when the Microsoft CRT is not |
str
|
available. |
Source code in hotstring\core\trigger.py
361 362 363 364 365 366 367 368 369 370 371 372 | |
_windows_case_insensitive_key ¶
Return a Microsoft CRT C-locale lowercase comparison key.
AutoHotkey's Unicode build compares case-insensitive hotstring text
through the Microsoft CRT _wcsicmp family. Lowering each semantic
trigger once with _wcslwr_l under an explicit C locale gives a
reusable key with the same lowercase basis while avoiding repeated FFI
comparisons during conflict detection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
Semantic trigger text. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Lowercased trigger key produced by the Microsoft CRT. |
Source code in hotstring\core\trigger.py
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | |
make_case_insensitive_trigger_key ¶
Create the reusable case-insensitive matching key for a semantic trigger.
On Windows the key is produced with the Microsoft CRT _wcslwr_l
function under an explicit C locale so comparisons reproduce
AutoHotkey's CRT-based case-insensitive behavior as closely as possible.
On non-Windows systems, where AutoHotkey itself does not run, Python's
str.lower() is used as a deterministic fallback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
str
|
Semantic hotstring trigger text. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Case-insensitive comparison key. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Source code in hotstring\core\trigger.py
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 | |