AutoCorrect2 Hotstrings
| Description | Generate typo-based AutoHotkey hotstrings and validate them against AutoCorrect2 |
| Author(s) | Or Fadida |
| Repository | https://github.com/orfadida2000/autocorrect2-hotstring-generation |
| Copyright | Copyright © 2026 Or Fadida |
Table of Contents
AutoCorrect2 Hotstring Generation¶
This project generates plausible keyboard-typo hotstrings, removes ambiguous generated mappings, checks the remaining candidates against AutoCorrect2, and can append accepted definitions to a dedicated generated AutoHotkey include file.
The project deliberately separates four concerns:
hotstring.core— generic AutoHotkey hotstring models, trigger conversion, option resolution, and conflict semantics;hotstring.typo_generation— typo generation and internal ambiguity filtering;hotstring.autocorrect2— AutoCorrect2-specific source loading, candidate rendering, integration checks, and generated-file writing;hotstring.cli— command-line parsing, external-input resolution, runtime command construction, and pipeline dispatch.
Project-level orchestration, reporting, and generic file I/O remain at the
hotstring package root. The hotstring.__main__ module provides the python -m hotstring entry point
and delegates command-line execution to hotstring.cli.application.main.
The processing stages can be used independently. Typo generation does not depend on AutoCorrect2, and AutoCorrect2 checking can operate on manually constructed candidates.
The three workflows are also available through the typo-generation,
autocorrect2-check, and full-pipeline subcommands.
See also: Command-line interface for command syntax and shared runtime configuration.
License: This project is licensed under the MIT License.
Project Background¶
Purpose¶
AutoCorrect2 Hotstrings is a supporting project for AutoCorrect2. Its purpose is to generate plausible keyboard-typo hotstrings, evaluate whether those hotstrings are safe to use, and prepare accepted corrections for integration with an existing AutoCorrect2 setup.
The project focuses on a problem that becomes increasingly important as an autocorrect library grows: a generated correction must not merely look plausible. Its trigger also needs to behave safely alongside other generated hotstrings and the hotstrings that already exist in AutoCorrect2.
At a high level, the workflow is:
Workflow Diagram
flowchart TD
A["Target words"] --> B["Generate plausible<br>keyboard typos"]
B --> C["Remove internally<br>ambiguous mappings"]
C --> D["Create AutoCorrect2<br>candidates"]
D --> E["Check against existing<br>AutoCorrect2 hotstrings"]
E --> F["Keep accepted<br>candidates"]
F --> G["Optionally write<br>hotstrings and reports"]
The project is therefore not an autocorrect runtime of its own. AutoHotkey and AutoCorrect2 remain responsible for recognizing and executing hotstrings. This project provides generation, analysis, validation, and integration tooling around that existing system.
AutoHotkey and hotstrings¶
AutoHotkey is a Windows automation and scripting language. One of its core text-automation features is the hotstring.
A hotstring watches typed input for a trigger and reacts when that trigger is recognized. A simple hotstring can replace one piece of text with another, while an execute hotstring can invoke arbitrary AutoHotkey code.
In its simplest form, an autocorrect hotstring maps a misspelled trigger to an intended word.
This makes hotstrings a natural foundation for a continuously running autocorrect system. AutoHotkey also provides options that change how triggers are recognized, including case sensitivity, whether an ending character is required, and whether matching is allowed inside words.
Those recognition rules matter to this project because two hotstrings can interfere even when their trigger strings are not identical. Conflict detection therefore needs to model the relevant AutoHotkey hotstring semantics rather than performing only simple string equality checks.
The original AutoCorrect.ahk¶
The lineage begins with AutoCorrect.ahk, initially released by Jim Biancolo on September 24, 2006.
The original script implemented autocorrection in AutoHotkey using lists of common misspellings. Its own introduction emphasized an important limitation: an autocorrect system should focus on corrections that are sufficiently unambiguous rather than attempting to silently correct every possible misspelling.
That distinction remains useful today. An incorrect automatic correction can be worse than leaving a questionable word untouched, because the replacement may look valid and no longer be caught by a conventional spellchecker.
The script was expanded over time with additional misspellings and correction rules, helping establish the AutoHotkey hotstring-based autocorrect approach from which later projects evolved.
AutoCorrect2¶
AutoCorrect2 is a modern AutoHotkey v2 project built on that lineage.
It began as a version of the earlier AutoCorrect.ahk, but has evolved into a
suite of interrelated AutoHotkey v2 scripts and tools for using, creating,
managing, analyzing, and improving autocorrect hotstrings.
That broader tooling is important: maintaining a large autocorrect collection is not just a matter of adding more typo/replacement pairs. It also involves examining trigger behavior, refining entries, managing generated content, and avoiding corrections that would interfere with valid typing or with other hotstrings.
AutoCorrect2 provides the runtime environment and surrounding tools in which the hotstrings produced by this project are intended to operate.
Where this project fits¶
The relationship can be summarized as:
Relationship Diagram
flowchart TD
A["AutoHotkey"] -->|"runtime for"| B["AutoCorrect.ahk"]
A -->|"runtime for"| C["AutoCorrect2"]
B -->|"predecessor of"| C
D["AutoCorrect2 Hotstrings<br>(this project)"] -->|"supports"| C
This project operates at the generation and analysis layer.
Given target words, it can generate typo candidates that mimic plausible keyboard mistakes. Those candidates are then filtered before integration:
- ambiguous generated mappings can be removed;
- generated hotstrings can be checked against one another;
- candidates can be checked against existing AutoCorrect2 hotstrings;
- AutoHotkey recognition rules relevant to conflicts can be taken into account;
- accepted entries can be rendered in AutoCorrect2-compatible form;
- reports can explain which candidates were accepted or rejected.
The intent is not to maximize the number of generated corrections. The intent is to produce a set of useful candidates while reducing unsafe or ambiguous automatic behavior.
Design principle¶
A generated typo is only useful if correcting it automatically is reasonably safe.
That principle influences the architecture of the project. Generation and conflict analysis are deliberately separate concerns: producing a plausible typo does not automatically mean that the corresponding hotstring should be added.
The project therefore treats generation as the beginning of the pipeline, not the final decision.
Further reading¶
Getting started¶
Install¶
The project uses uv and is configured as a non-package project. A normal sync
installs the runtime dependency plus the default dev and docs groups:
uv sync
Configure AutoCorrect2¶
The project does not contain a machine-specific AutoCorrect2 path. Commands which read AutoCorrect2 resolve the project directory in this order:
--autocorrect2-project-dir;- the
AUTOCORRECT2_PROJECT_DIRprocess environment variable; - a dotenv file selected with
--env-file; .envat the repository root.
For normal local use, copy the committed example and edit the value:
Copy-Item .env.example .env
AUTOCORRECT2_PROJECT_DIR=H:/Projects/AutoCorrect2
The local .env is ignored by Git. A relative path in a dotenv file is
resolved relative to that file. Relative command-line and process-environment
paths are resolved relative to the current working directory.
Add a one-time #Include for Core/GeneratedHotstrings.ahk in the same active
AutoCorrect2 hotstring context as the main autocorrection library. The generated
file remains project-owned and is scanned on later runs when it exists.
Run a workflow¶
The command-line interface mirrors the three public pipeline functions:
uv run python -m hotstring --help
For example, run the complete workflow with a UTF-8 file containing one source word per non-empty line:
uv run python -m hotstring full-pipeline `
--words-file .\words.txt `
--single-attempts 100 `
--multi-attempts 100 `
--multi-min-length 5 `
--report .\hotstring-generation-report.txt
Those sampling values are examples rather than application defaults. The CLI
requires them so every run states its sampling policy explicitly. Use
--write-accepted to opt into modifying
Core/GeneratedHotstrings.ahk; without it, AutoCorrect2-aware workflows only
read and report.
Add -v before the workflow name for progress messages, or -vv for debugging
details:
uv run python -m hotstring -v full-pipeline --help
Build the documentation¶
uv run mkdocs serve
The MkDocs configuration uses these committed stylesheet files under
docs/assets/stylesheets/:
catppuccin-latte.csscatppuccin-mocha.cssdracula.cssextra.css
Command-line usage¶
The hotstring.__main__ module provides the python -m hotstring entry point and delegates
command-line execution to main() which exposes the project's three
public workflows as subcommands.
| Subcommand | Workflow |
|---|---|
typo-generation |
Generate typo mappings and remove internally ambiguous mappings |
autocorrect2-check |
Check supplied candidates against existing AutoCorrect2 hotstrings |
full-pipeline |
Generate typo candidates and check the survivors against AutoCorrect2 |
Display the top-level help or the help for one subcommand with:
uv run python -m hotstring --help
uv run python -m hotstring typo-generation --help
uv run python -m hotstring autocorrect2-check --help
uv run python -m hotstring full-pipeline --help
Logging verbosity¶
-v and --verbose are repeatable top-level options:
| Invocation | Logging level |
|---|---|
| no verbosity option | Normal command summaries and concise errors |
-v |
Informational logging |
-vv |
Debug logging, including a traceback for an unexpected runtime failure |
The verbosity option belongs to the top-level parser, so it must appear before the subcommand:
uv run python -m hotstring -v typo-generation ...
uv run python -m hotstring -vv full-pipeline ...
Repeating -v more than twice continues to use debug logging.
Typo generation¶
typo-generation requires exactly one source of words:
- repeat
--word WORDto supply words directly; or - use
--words-file PATHfor a UTF-8 file containing one word per line.
Blank lines are ignored, and duplicate words are removed while preserving their first occurrence.
The command creates the project's default ordered
TypoGenerationTask
sequence from these required arguments:
| Argument | Meaning |
|---|---|
--single-attempts COUNT |
Attempts per eligible word for each forced single-error task |
--multi-attempts COUNT |
Attempts per eligible word for the mixed two-error task |
--multi-min-length LENGTH |
Minimum word length for the mixed two-error task |
Optional generation arguments are:
| Argument | Meaning |
|---|---|
--language LANGUAGE |
MULTYPO language identifier; defaults to english |
--excluding-set / --no-excluding-set |
Enable or disable MULTYPO's language excluding set; enabled by default |
--keyboard-weights HORIZONTAL VERTICAL |
Relative keyboard-neighbor weights; defaults to 9 1 |
--workers COUNT |
Process-pool size; omit it to use the execution layer's default |
--report PATH |
Write a typo-generation report |
For example:
uv run python -m hotstring typo-generation `
--words-file .\words.txt `
--single-attempts 100 `
--multi-attempts 100 `
--multi-min-length 5 `
--workers 4 `
--report .\reports\typo-generation.txt
This subcommand does not load or modify an AutoCorrect2 project.
AutoCorrect2 project directory¶
The autocorrect2-check and full-pipeline subcommands resolve the local
AutoCorrect2 project directory in this order:
--project-dir PATH;- the process environment variable
AUTOCORRECT2_PROJECT_DIR; - the dotenv file selected by
--env-file PATH; .envat the project root.
Resolution stops at the first configured source. A lower-priority dotenv file is therefore not opened or validated after a command-line or process-environment value has been selected.
A project-root .env file can contain:
AUTOCORRECT2_PROJECT_DIR=H:/Projects/AutoCorrect2
An explicit dotenv file uses the same key:
uv run python -m hotstring autocorrect2-check `
--env-file .\config\autocorrect2.env `
--candidate "teh" "the" "B0X"
A relative value read from a dotenv file is resolved relative to that file's
directory. A relative --project-dir value or process-environment value is
resolved relative to the current working directory.
See AutoCorrect2 configuration for the required source-file layout and generated-file policy.
AutoCorrect2 conflict checking¶
autocorrect2-check accepts manually supplied
AutoCorrect2CandidateHotstring
objects without running typo generation.
Supply candidates directly by repeating --candidate with three values:
--candidate TRIGGER REPLACEMENT OPTIONS
For example:
uv run python -m hotstring autocorrect2-check `
--candidate "teh" "the" "B0X" `
--candidate "adn" "and" "B0X" `
--project-dir "H:\Projects\AutoCorrect2" `
--report .\reports\autocorrect2-check.txt
Alternatively, --candidates-file PATH accepts a UTF-8 JSON file containing a
top-level array. Every object must contain exactly the string fields trigger,
replacement, and options:
[
{
"trigger": "teh",
"replacement": "the",
"options": "B0X"
},
{
"trigger": "adn",
"replacement": "and",
"options": "B0X"
}
]
Use the file with:
uv run python -m hotstring autocorrect2-check `
--candidates-file .\candidates.json
--candidate and --candidates-file are mutually exclusive.
Full pipeline¶
full-pipeline composes typo generation and AutoCorrect2 conflict checking.
It accepts the same word and generation arguments as typo-generation, then
converts the surviving mappings into generated B0X candidates before running
the AutoCorrect2 check.
For example:
uv run python -m hotstring full-pipeline `
--words-file .\words.txt `
--single-attempts 100 `
--multi-attempts 100 `
--multi-min-length 5 `
--workers 4 `
--report .\reports\full-pipeline.txt
The project directory can come from any of the four configuration sources
described above. full-pipeline does not accept --candidate or
--candidates-file, because it creates candidates from the typo-generation
result.
Reports and generated output¶
All three subcommands accept --report PATH. Parent directories are created by
the reporting layer when required.
AutoCorrect2-aware commands are read-only by default. Supply
--write-accepted to append accepted candidates to
Core/GeneratedHotstrings.ahk:
uv run python -m hotstring full-pipeline `
--words-file .\words.txt `
--single-attempts 100 `
--multi-attempts 100 `
--multi-min-length 5 `
--write-accepted
Writing manually supplied candidates remains subject to the writer's explicit generated-option contract.
Exit statuses¶
| Status | Meaning |
|---|---|
0 |
The selected workflow completed successfully |
1 |
Pipeline execution failed |
2 |
Command-line syntax or resolved runtime configuration was invalid |
130 |
Execution was interrupted from the terminal |
Project structure¶
Project Structure
autocorrect2-hotstring-generation/
├── docs/
│ ├── index.md
│ ├── api/
│ │ ├── index.md
│ │ ├── cli/
│ │ │ ├── index.md
│ │ │ ├── application.md
│ │ │ ├── commands.md
│ │ │ ├── parser.md
│ │ │ └── runtime.md
│ │ ├── core/
│ │ │ ├── index.md
│ │ │ ├── conflicts.md
│ │ │ ├── constants.md
│ │ │ ├── models.md
│ │ │ ├── options.md
│ │ │ └── trigger.md
│ │ ├── autocorrect2/
│ │ │ ├── index.md
│ │ │ ├── source_loading/
│ │ │ │ ├── index.md
│ │ │ │ ├── cache.md
│ │ │ │ ├── loader.md
│ │ │ │ └── parser.md
│ │ │ ├── constants.md
│ │ │ ├── integration.md
│ │ │ ├── models.md
│ │ │ └── writer.md
│ │ ├── typo-generation/
│ │ │ ├── index.md
│ │ │ ├── aggregation.md
│ │ │ ├── execution.md
│ │ │ ├── generation.md
│ │ │ └── models.md
│ │ ├── constants.md
│ │ ├── file-io.md
│ │ ├── pipeline.md
│ │ └── report.md
│ ├── assets/
│ │ ├── icons/
│ │ │ ├── ACicon.ico
│ │ │ └── autocorrect2-spellcheck.svg
│ │ ├── scripts/
│ │ │ └── header-title-link.js
│ │ └── stylesheets/
│ │ ├── dracula.css
│ │ └── extra.css
│ ├── concepts/
│ │ ├── index.md
│ │ ├── autocorrect2.md
│ │ ├── conflict-detection.md
│ │ ├── hotstrings.md
│ │ └── typo-generation.md
│ ├── configuration/
│ │ ├── index.md
│ │ ├── autocorrect2.md
│ │ └── typo-generation.md
│ ├── workflows/
│ │ ├── index.md
│ │ ├── autocorrect2-check.md
│ │ ├── full-pipeline.md
│ │ ├── reporting.md
│ │ └── typo-generation.md
│ ├── command-line.md
│ ├── getting-started.md
│ ├── license.md
│ ├── project-background.md
│ └── project-structure.md
├── hotstring/
│ ├── __init__.py
│ ├── __main__.py
│ ├── cli/
│ │ ├── __init__.py
│ │ ├── application.py
│ │ ├── commands.py
│ │ ├── parser.py
│ │ └── runtime.py
│ ├── core/
│ │ ├── __init__.py
│ │ ├── conflicts.py
│ │ ├── constants.py
│ │ ├── models.py
│ │ ├── options.py
│ │ └── trigger.py
│ ├── autocorrect2/
│ │ ├── __init__.py
│ │ ├── source_loading/
│ │ │ ├── __init__.py
│ │ │ ├── cache.py
│ │ │ ├── loader.py
│ │ │ └── parser.py
│ │ ├── constants.py
│ │ ├── integration.py
│ │ ├── models.py
│ │ └── writer.py
│ ├── typo_generation/
│ │ ├── __init__.py
│ │ ├── aggregation.py
│ │ ├── execution.py
│ │ ├── generation.py
│ │ └── models.py
│ ├── constants.py
│ ├── file_io.py
│ ├── pipeline.py
│ └── report.py
├── .env.example
├── .gitignore
├── LICENSE
├── mkdocs.yml
├── pyproject.toml
├── README.md
└── uv.lock
Generic AutoHotkey hotstring behavior lives under hotstring/core/.
AutoCorrect2-specific knowledge is isolated under hotstring/autocorrect2/,
with source loading further separated into its own subpackage. Typo generation
remains independent under hotstring/typo_generation/.
The hotstring.cli subpackage forms the command-line application layer:
parser.pydefines command-line syntax;runtime.pyresolves external input and constructs runtime command objects;commands.pydispatches those objects to the public pipelines;application.pyowns logging, process-level errors, and exit statuses;__init__.pyre-exportsmain.
The hotstring.__main__ module provides the python -m hotstring entry point
and delegates command-line execution to hotstring.cli.application.main. Other top-level
hotstring modules remain responsible for project-level orchestration and
infrastructure rather than the generic hotstring domain model.
Concepts
Concepts¶
The project separates generic AutoHotkey semantics, typo sampling, AutoCorrect2 integration, and orchestration.
The main conceptual boundaries are:
- declared vs resolved hotstring options;
- generic hotstrings vs semantic correction candidates;
- generic candidates vs AutoCorrect2-specific candidates;
- typo generation vs AutoCorrect2 conflict checking;
- report construction vs filesystem output.
These boundaries allow either processing stage to run independently and keep context-dependent AutoHotkey defaults out of the parser itself.
Hotstrings and options¶
Trigger representations¶
The generic hotstring model keeps trigger meaning separate from AutoHotkey source spelling.
Each initialized Hotstring stores two
trigger representations:
semantic_trigger— the actual characters AutoHotkey should recognize;ahk_trigger— the deterministic, minimally escaped spelling used when rendering AHK source.
The constructor argument trigger is an InitVar, so it is not retained as a
third ambiguous representation after initialization.
By default, Hotstring and candidate classes interpret constructor trigger
as semantic text. ExistingHotstring
receives trigger text extracted from an AHK source file, so it shadows the class
policy TRIGGER_INPUT_IS_AHK_SOURCE = True. The base
Hotstring.__post_init__()
still owns the same resolution algorithm for every subclass:
flowchart LR
A["Constructor trigger"] -->|"apply class policy"| B["semantic_trigger"]
B -->|"encode canonically"| C["ahk_trigger"]
When
CHECK_TRIGGER_ROUND_TRIP is
enabled, initialization also verifies the conversion invariant:
ahk_to_semantic_trigger(ahk_trigger) == semantic_trigger
This is an internal consistency check. A failure indicates a bug in the conversion contract rather than invalid user input.
Trigger conversion and canonicalization¶
semantic_to_ahk_trigger()
produces one deterministic, minimally escaped AHK representation.
ahk_to_semantic_trigger()
performs the reverse semantic conversion: it interprets an AHK source spelling
and returns the trigger characters that spelling represents. It may therefore
accept multiple valid source spellings that have the same semantic result.
During canonical encoding, characters which always require source escaping, such as a literal backtick or supported control characters, are escaped unconditionally. Colons and semicolons are escaped only when their source context requires it:
:is escaped only as needed to prevent an unescaped::sequence inside the trigger or against the declaration delimiter;;is escaped only when a literal source space immediately precedes it and it would otherwise begin a comment.
Consequently, multiple valid source spellings can decode to the same semantic trigger. For example:
foo:bar
foo`:bar
both decode to:
foo:bar
and re-encode canonically as the minimally escaped form:
foo:bar
The helpers are therefore intentionally asymmetric with respect to source spelling. The supported semantic round trip is:
ahk_to_semantic_trigger(semantic_to_ahk_trigger(value)) == value
for every semantic trigger accepted by the encoder. Re-encoding arbitrary AHK source is allowed to canonicalize optional or unnecessary escapes.
Case-insensitive matching key¶
Conflict detection operates on semantic trigger text, never on escaped AHK
source spelling. Each hotstring therefore caches a derived
case_insensitive_semantic_trigger_key.
On Windows the key is produced with the Microsoft CRT under an explicit C
locale to follow AutoHotkey's case-insensitive comparison basis as closely as
possible. On non-Windows systems, str.lower() is used as a deterministic
fallback. The key is runtime-derived state and is not persisted in the source
cache.
Hotstring rendering¶
Hotstring.render(content=None)
renders the canonical option declaration and ahk_trigger, never the
constructor input.
content means everything emitted after the declaration's second ::. It is
therefore intentionally broader than an inline replacement RHS: depending on
AutoHotkey syntax and options, it may be replacement text, executable content,
or multiline block content.
The generic
Hotstring.to_ahk_string_literal()
helper separately handles AHK double-quoted string syntax. It escapes literal
backticks and quotes plus all supported AHK control escapes (r, n, b,
t, v, a, and f). Trigger encoding and quoted-string encoding remain
separate because their syntax rules are different.
Declared option state¶
HotstringOptions represents what is
explicitly declared on one hotstring. Every omitted option uses the shared
sentinel:
InheritedState.INHERIT
This is distinct from the actual semantic value of the option. For example,
CaseMode contains only real case modes,
while inheritance is represented by
InheritedState rather than by a
synthetic CaseMode.INHERIT member.
Two-state settings use the SettingState
members SettingState.ENABLED and SettingState.DISABLED. The * option is
exposed semantically as ending_character_optional, so its mapping is direct:
| Declaration | Semantic state |
|---|---|
* |
SettingState.ENABLED |
*0 |
SettingState.DISABLED |
| omitted | InheritedState.INHERIT |
declaration()
serializes the parsed semantic state back to one canonical option string.
Repeated or contradictory source options therefore collapse to the last
effective value rather than being reproduced verbatim.
Resolved option state¶
ResolvedHotstringOptions is
a separate dataclass rather than a subclass of
HotstringOptions. Its fields
contain only concrete values; none are typed with
InheritedState.
ResolvedHotstringOptions.from_options()
constructs a resolved object from:
- one parsed
HotstringOptionsdeclaration; and - the fully resolved defaults applicable at that declaration position.
Explicit values override those defaults. InheritedState.INHERIT leaves the
corresponding default unchanged. This makes resolution context-sensitive
without making HotstringOptions itself aware of file position,
#Hotstring, or other sources of defaults.
Send mode¶
The declared SendMode enum represents the
three actual hotstring send-mode choices:
INPUT
PLAY
EVENT
The declaration mapping is:
| Hotstring option | Declared value |
|---|---|
SI |
SendMode.INPUT |
SP |
SendMode.PLAY |
SE |
SendMode.EVENT |
| omitted | InheritedState.INHERIT |
Input mode has two distinct effective fallback behaviors, so the resolved model
uses a separate four-state
ResolvedSendMode enum:
class ResolvedSendMode(Enum):
INPUT_WITH_PLAY_FALLBACK = auto()
INPUT_WITH_EVENT_FALLBACK = auto()
PLAY = auto()
EVENT = auto()
ResolvedHotstringOptions.send_mode is therefore typed as
ResolvedSendMode.
The important mappings are:
| Effective source | Resolved value |
|---|---|
explicit SI |
ResolvedSendMode.INPUT_WITH_PLAY_FALLBACK |
| AutoHotkey built-in default | ResolvedSendMode.INPUT_WITH_EVENT_FALLBACK |
SP |
ResolvedSendMode.PLAY |
SE |
ResolvedSendMode.EVENT |
InheritedState.INHERIT does not inherently mean
INPUT_WITH_EVENT_FALLBACK. It means to use the currently applicable hotstring
default. If inheritance eventually reaches AutoHotkey's untouched built-in
default, the resulting resolved value is
ResolvedSendMode.INPUT_WITH_EVENT_FALLBACK. If an applicable default has
already selected SI, SP, or SE, the inherited value resolves according
to that default instead.
Candidate hierarchy¶
The generic model hierarchy is:
Candidate hotstring class hierarchy
classDiagram
direction TB
Hotstring <|-- CandidateHotstring
CandidateHotstring <|-- AutoCorrect2CandidateHotstring
class CandidateHotstring {
<<abstract>>
}
CandidateHotstring stores the
semantic replacement and requires a concrete subclass to derive the
AutoHotkey content corresponding to that replacement. The public
Hotstring.render() contract remains
inherited unchanged, so the hierarchy does not narrow the method signature.
AutoCorrect2CandidateHotstring
supplies the AutoCorrect2-specific mapping: the replacement is converted to a
complete escaped AutoHotkey string literal and wrapped in f(...).
Typo generation¶
Each source item is treated as exactly one word. For every configured typo
distribution and every source word, MULTYPO is sampled
generation_attempts_per_word times.
MULTYPO itself receives typo_rate=1.0 for each attempt because every sampling
attempt is intended to corrupt the supplied word. The project therefore does
not expose the old custom typo_rate argument that previously scaled the
number of iterations.
The low-level generator uses insert_typos() directly rather than the
sentence-oriented insert_typos_in_text() wrapper. Sentence tokenization and
NLTK resources are therefore unnecessary for this workflow.
Raw samples are aggregated by noisy form. A noisy form that maps to exactly one target word becomes a candidate; one that maps to multiple target words is recorded as an internal clash and removed before AutoCorrect2 processing.
Conflict detection¶
Conflict checking operates on semantic trigger text and effective hotstring matching semantics, not on AHK source spelling or on whether a particular option token happened to be present in the source.
Before matching, a parsed
HotstringOptions declaration is
converted to a
ResolvedHotstringOptions
using the defaults that apply at that declaration position. Conflict detection
then reads only the resolved recognition fields it needs.
Matching directions¶
Conflict checking examines both directions:
- whether an existing hotstring can activate while a candidate is typed;
- whether the candidate can activate while an existing trigger is typed.
Every occurrence is considered, including overlapping occurrences. The
implementation uses repeated str.find() searches advancing by one character,
so a trigger such as ana is found at both valid positions in banana.
Recognition options¶
The checker supports all combinations of the recognition-related hotstring options currently modeled by the project:
*/*0— whether an ending character is optional;?/?0— whether an alphanumeric predecessor is permitted;C,C0, andC1— effective case matching.
Options unrelated to trigger recognition, such as backspacing, execution, priority, send mode, replacement mode, key delay, or recognizer reset, do not affect conflict recognition.
Boundaries¶
A matching occurrence has a valid left boundary when one of these is true:
- the occurrence starts at the beginning of the containing trigger;
- the preceding character is non-alphanumeric;
- the tested hotstring permits an alphanumeric predecessor through
?.
The right boundary is valid when one of these is true:
- the tested hotstring does not require an ending character (
*is enabled); - the occurrence reaches the end of the containing trigger, because a later typed ending character can still activate it;
- the following character is in the effective ending-character set.
An ending character may itself appear anywhere inside a hotstring trigger. That is valid AutoHotkey input; the character matters to conflict logic only when it serves as the character immediately following a shorter matched occurrence.
Case matching¶
If both compared hotstrings are case-sensitive, occurrence and same-trigger
checks use their exact semantic_trigger strings.
If either hotstring is case-insensitive, a shared typed casing can exist when
their AutoHotkey-compatible case-insensitive semantic keys match. The cached
case_insensitive_semantic_trigger_key is derived once from each semantic
trigger and reused throughout matching.
On Windows the key uses the Microsoft CRT C-locale lowercase basis. The
non-Windows fallback uses str.lower() and includes a defensive slice-based
path if lowercasing changes string length.
AutoCorrect2 integration¶
The AutoCorrect2 layer owns only behavior that is specific to the external AutoCorrect2 project.
Source loading¶
Existing declarations are loaded through the nested
hotstring.autocorrect2.source_loading package:
parserextracts static hotstring declarations from decoded source text;cachepersists source fingerprints and minimal extracted state;loadercoordinates the configured required and optional source files.
The parser is escape-aware. It scans trigger source character by character so
escaped colons and backticks cannot be mistaken for the trigger's closing ::
delimiter.
Parsed trigger text is supplied to
ExistingHotstring in AHK source
form. The generic model then derives semantic_trigger, canonical
ahk_trigger, parsed options, and the case-insensitive semantic comparison key.
The persistent source cache stores canonical AHK trigger text and canonical option declarations, not semantic or comparison-key state. SHA-256 of the exact source bytes is authoritative for content identity; size and modification time are metadata only. Cached semantic state is rebuilt by the current model every time an entry is restored.
Candidate rendering and output¶
Approved generated candidates are represented by
AutoCorrect2CandidateHotstring.
Its concrete replacement-to-content mapping wraps a safely escaped AutoHotkey
string literal in AutoCorrect2's f(...) helper.
Generated candidates are not inserted into upstream-maintained
AutoCorrectHotstrings.ahk. They are appended to
Core/GeneratedHotstrings.ahk, which AutoCorrect2 includes once through a
manually added #Include directive.
The writer enforces the generated-file B0X
contract. Generic conflict detection is deliberately independent of that output
policy and supports other recognition-option combinations.
Keeping generated content separate allows later conflict checks to inspect previously generated entries without modifying upstream-maintained files.
Workflows
Workflows¶
Three public workflows are available through both Python APIs and matching CLI subcommands:
- standalone typo generation through
run_typo_generation()andtypo-generationrespectively; - standalone AutoCorrect2 conflict checking through
run_autocorrect2_check()andautocorrect2-checkrespectively; - the composed workflow through
run_full_pipeline()andfull-pipelinerespectively.
The full workflow reuses the first two rather than duplicating their logic.
Typo generation remains independent of AutoCorrect2; the adaptation from a
noisy-word mapping to
AutoCorrect2CandidateHotstring
belongs to the composed pipeline.
See also: Command-line interface for command syntax and shared runtime configuration.
Full pipeline¶
run_full_pipeline() composes
run_typo_generation() with
run_autocorrect2_check() and
returns a FullPipelineResult:
Full Pipeline Workflow
flowchart TD
A["Source words and<br>generation settings"] --> B["Generate typo<br>mappings"]
B --> C["TypoGenerationResult"]
C -->|"candidate mappings"| D["Create B0X<br>AutoCorrect2 candidates"]
D --> E["Check against<br>AutoCorrect2"]
E --> F["AutoCorrect2CheckResult"]
C --> G["FullPipelineResult"]
F --> G
The adaptation step converts each surviving noisy-to-target mapping into an
AutoCorrect2CandidateHotstring
using the fixed generated option set B0X. Typo generation itself has no
dependency on
HotstringOptions or AutoCorrect2.
The full pipeline disables stage-specific report writing while composing the two stages and creates one combined report at the end when requested.
Command-line usage¶
Run the composed workflow with full-pipeline:
uv run python -m hotstring full-pipeline `
--words-file .\words.txt `
--single-attempts 100 `
--multi-attempts 100 `
--multi-min-length 5 `
--workers 4 `
--report .\reports\full-pipeline.txt
The AutoCorrect2 project directory is resolved from --project-dir, the
process environment, an explicit dotenv file, or the project-root .env.
The command remains read-only unless --write-accepted is supplied. It does
not accept manually supplied candidates because it creates B0X candidates
from the typo-generation result.
See also: Command-line interface for all shared options.
Typo generation¶
This standalone workflow generates and filters typo mappings without loading AutoCorrect2 data.
run_typo_generation() accepts source
words, an ordered sequence of
TypoGenerationTask
objects, a
TypoGenerationConfig,
and an optional n_workers value.
Typo Generation Workflow
flowchart TD
A["Source words"] --> D["Execute typo-generation<br>tasks"]
B["Generation tasks"] --> D
C["Configuration<br>and worker count"] --> D
D --> E["Raw MULTYPO samples"]
E --> F["Aggregate and classify<br>generated mappings"]
F --> G["TypoGenerationResult"]
TypoGenerationResult.candidates maps each unambiguous noisy form to exactly
one target word. clashes contains noisy forms that mapped to multiple target
words and are therefore removed before any AutoCorrect2 processing.
This workflow has no dependency on AutoCorrect2 hotstring models or option policies.
Command-line usage¶
Run standalone typo generation with typo-generation:
uv run python -m hotstring typo-generation `
--words-file .\words.txt `
--single-attempts 100 `
--multi-attempts 100 `
--multi-min-length 5 `
--workers 4 `
--report .\reports\typo-generation.txt
The command accepts either repeated --word arguments or one --words-file,
but not both. It does not load or modify AutoCorrect2.
See also: Command-line interface for all generation options.
AutoCorrect2 conflict checking¶
Use this workflow when candidate hotstrings already exist and need to be checked against the active hotstrings in a configured AutoCorrect2 project.
run_autocorrect2_check() accepts
a sequence of
AutoCorrect2CandidateHotstring
objects:
Conflict Checking Workflow
flowchart TD
A["Supplied candidates"] --> D["Resolve options and<br>assess conflicts"]
B["Configured AutoCorrect2<br>source files"] --> C["Load existing<br>hotstrings"]
C --> D
D --> E["AutoCorrect2CheckResult"]
Typo generation is not involved. The returned
AutoCorrect2CheckResult
partitions the supplied candidates into accepted and rejected groups.
Each supplied candidate retains its semantic replacement and derives the AutoCorrect2-compatible AutoHotkey content used when it is rendered.
The pipeline can optionally append accepted candidates to the generated include
file. The AutoCorrect2 writer owns the generated-file location and output
policy, while generic filesystem operations remain in
hotstring.file_io.
Command-line usage¶
Supply candidates directly by repeating --candidate:
uv run python -m hotstring autocorrect2-check `
--candidate "teh" "the" "B0X" `
--candidate "adn" "and" "B0X" `
--project-dir "H:\Projects\AutoCorrect2" `
--report .\reports\autocorrect2-check.txt
Each occurrence receives the semantic trigger, semantic replacement, and hotstring option string.
Alternatively, use --candidates-file with a UTF-8 JSON array:
[
{
"trigger": "teh",
"replacement": "the",
"options": "B0X"
},
{
"trigger": "adn",
"replacement": "and",
"options": "B0X"
}
]
uv run python -m hotstring autocorrect2-check `
--candidates-file .\candidates.json
--candidate and --candidates-file are mutually exclusive. The command is
read-only unless --write-accepted is supplied.
See also: Command-line interface for project-directory resolution and all command options.
Reporting¶
Report builders return list[str] and never write files themselves:
The full report reuses the two stage-specific report bodies. Run-level framing
belongs to build_report_document(),
which can add metadata that should appear only once around the combined body.
Only the pipeline layer decides when a report is written and delegates the
filesystem operation to hotstring.file_io.
Configuration
Configuration¶
Configuration is divided between AutoCorrect2 integration and typo-generation behavior. These concerns are independent: standalone typo generation does not require an AutoCorrect2 project directory.
AutoCorrect2 integration¶
AutoCorrect2 configuration explains how the local
AutoCorrect2 project directory is resolved, including command-line,
environment-variable, and dotenv sources. It also describes generated output
and the explicit --write-accepted requirement.
Typo generation¶
Typo-generation configuration describes the generation
settings represented by
TypoGenerationConfig,
the ordered
TypoGenerationTask
sequence, and execution settings such as the worker count.
See also: Command-line interface for command syntax and all command options.
Typo-generation configuration¶
TypoGenerationConfig
contains settings shared by every task in one generation run:
language;use_excluding_set;horizontal_vs_vertical.
Individual sampling policies are represented by
TypoGenerationTask.
Each task defines:
- its typo-operation distribution;
- its typo rate;
- its generation attempts per eligible word;
- its minimum eligible word length.
Default CLI task set¶
The CLI uses
create_default_typo_generation_tasks()
to construct the ordered default task sequence:
- one forced single-error task for each supported operation distribution;
- one mixed two-error task.
The required CLI arguments are:
| Argument | Runtime setting |
|---|---|
--single-attempts COUNT |
Attempts per word for each forced single-error task |
--multi-attempts COUNT |
Attempts per word for the mixed two-error task |
--multi-min-length LENGTH |
Minimum word length for the mixed two-error task |
Shared generator settings use:
| Argument | Runtime setting |
|---|---|
--language LANGUAGE |
TypoGenerationConfig.language |
--excluding-set / --no-excluding-set |
TypoGenerationConfig.use_excluding_set |
--keyboard-weights HORIZONTAL VERTICAL |
TypoGenerationConfig.horizontal_vs_vertical |
Execution setting¶
--workers COUNT becomes the pipeline's n_workers argument. Worker count is
not part of TypoGenerationConfig because it changes how the requested work is
executed, not the requested generation semantics.
AutoCorrect2 configuration¶
Project directory¶
The project does not contain a hard-coded local AutoCorrect2 path. The CLI resolves the directory in this order:
--project-dir PATH;- the process environment variable
AUTOCORRECT2_PROJECT_DIR; - the dotenv file selected by
--env-file PATH; .envat the project root.
Resolution stops at the first configured source. Relative values from a dotenv file are resolved relative to that file's directory. Relative command-line and process-environment values are resolved relative to the current working directory.
A dotenv file uses:
AUTOCORRECT2_PROJECT_DIR=H:/Projects/AutoCorrect2
Required sources¶
The selected AutoCorrect2 project directory must contain:
Core/AutoCorrectHotstrings.ahkCore/PersonalHotstrings.ahkIncludes/DateTool.ahk
Core/GeneratedHotstrings.ahk is optional on the first run and is scanned once
it exists.
Generated output¶
AutoCorrect2-aware commands are read-only by default. --write-accepted
enables appending accepted candidates to Core/GeneratedHotstrings.ahk.
Candidates supplied manually to autocorrect2-check must satisfy the writer's
explicit generated-option contract before they can be written. The full
pipeline creates generated candidates with the required B0X options.
Matching defaults¶
HotstringOptions does not bake
AutoHotkey defaults into omitted fields. Omitted values remain the INHERIT
member of InheritedState until a
ResolvedHotstringOptions is
created with the defaults that apply at that source position.
Resolution combines the parsed declaration with the fully resolved defaults applicable at that source position:
Resolution Diagram
flowchart TD
A["HotstringOptions<br>declaration"] --> C["Resolve inherited<br>fields"]
B["Applicable<br>resolved defaults"] --> C
C --> D["ResolvedHotstringOptions<br>effective state"]
Until positional directive analysis is implemented, the AutoCorrect2 pipeline can resolve declarations against the configured built-in/default option object.
The conflict checker currently assumes the configured ending-character set and uses only the resolved recognition-related fields required for matching.
API Reference
API reference¶
The API reference mirrors the Python package hierarchy and is rendered directly from source docstrings with mkdocstrings.
hotstring.corecontains generic AutoHotkey hotstring behavior.hotstring.autocorrect2contains AutoCorrect2-specific integration, including the nestedsource_loadingsubpackage.hotstring.typo_generationcontains typo-generation functionality.hotstring.clicontains command-line parsing, runtime configuration, and pipeline dispatch.- Top-level
hotstringmodules such aspipeline,report, andfile_ioare documented directly under this API section.
The conceptual and workflow documentation should be used for architectural context; these pages focus on concrete Python symbols and signatures.
Core
Core API¶
hotstring.core contains the generic AutoHotkey hotstring domain model and
recognition logic. It does not depend on AutoCorrect2 integration or typo
generation.
The subpackage contains:
- semantic/AHK trigger conversion and case-insensitive keys;
- hotstring and candidate domain models;
- option parsing and effective option resolution;
- conflict detection;
- generic AutoHotkey defaults and constants.
Core models¶
This module contains the generic Hotstring model, the abstract
CandidateHotstring specialization, and ExistingHotstring for declarations
loaded from AHK source.
Hotstring uses a class-level trigger-input policy rather than subclass
resolver methods. ExistingHotstring shadows that policy so the shared base
initialization logic knows its constructor trigger is AHK source text.
models ¶
Define generic AutoHotkey hotstring domain models.
CHECK_TRIGGER_ROUND_TRIP
module-attribute
¶
Whether hotstring initialization verifies the trigger conversion invariant.
Hotstring
dataclass
¶
Represent the generic declaration portion of an AutoHotkey v2 hotstring.
trigger and options_input are constructor-only values. By default,
trigger is interpreted as semantic trigger text. Subclasses whose
constructor receives AHK source-form trigger text can override the
TRIGGER_INPUT_IS_AHK_SOURCE class policy without replacing the shared
trigger-resolution algorithm.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
InitVar[str]
|
Constructor trigger input. For |
required |
options_input
|
InitVar[str | HotstringOptions]
|
Parsed hotstring options or a raw option declaration string. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
TRIGGER_INPUT_IS_AHK_SOURCE |
bool
|
Whether the constructor's If Subclasses may override this class attribute to define the expected representation of their constructor trigger input. |
semantic_trigger |
str
|
Semantic trigger text containing the actual characters AutoHotkey should recognize. |
ahk_trigger |
str
|
Canonical, minimally escaped trigger source spelling used inside an AHK hotstring declaration. |
options |
HotstringOptions
|
Parsed per-hotstring options. This is always a
|
case_insensitive_semantic_trigger_key |
str
|
Cached comparison key derived from |
Source code in hotstring\core\models.py
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 | |
__post_init__ ¶
__post_init__(
trigger: str, options_input: str | HotstringOptions
) -> None
Resolve constructor inputs and establish immutable hotstring state.
Trigger initialization follows one shared algorithm for the full hierarchy:
- interpret the constructor trigger according to
TRIGGER_INPUT_IS_AHK_SOURCE; - derive the semantic trigger;
- derive the canonical AHK trigger from the semantic trigger;
- optionally verify that decoding the canonical AHK trigger reproduces the same semantic trigger.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
str
|
Constructor trigger input supplied through the |
required |
options_input
|
str | HotstringOptions
|
Raw or already parsed option input supplied through the
|
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the trigger or options input has an invalid type. |
ValueError
|
If the resolved semantic trigger is empty or cannot be represented safely in canonical AHK source form, or if the option string is invalid. |
AssertionError
|
If |
Source code in hotstring\core\models.py
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 | |
to_ahk_string_literal
staticmethod
¶
Convert text to an AutoHotkey v2 double-quoted string literal.
This helper is intentionally separate from hotstring-trigger source encoding. A quoted AHK expression string and a hotstring trigger declaration have different escaping rules.
Literal backticks, double quotes, and every supported AutoHotkey control escape are encoded. Unsupported ASCII control characters are rejected rather than emitted invisibly into generated source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
Text to encode as an AutoHotkey string literal. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Complete double-quoted AHK string literal. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
Source code in hotstring\core\models.py
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 | |
render ¶
Render the hotstring declaration with optional trailing content.
Rendering always uses the canonical ahk_trigger representation,
never the constructor input or semantic trigger. This guarantees that
triggers containing context-sensitive colons or semicolons, literal
backticks, or supported control characters are emitted safely and
consistently.
content means everything emitted after the declaration's second
::. It can therefore represent replacement text, executable inline
content, or a multiline hotstring function body. If content is
omitted, subclasses may provide their own default through
_default_content().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content
|
str | None
|
Optional content to emit after the second |
None
|
Returns:
| Type | Description |
|---|---|
str
|
Complete hotstring source text. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the supplied or subclass-provided content is neither a
string nor |
Source code in hotstring\core\models.py
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 | |
_default_content ¶
_default_content() -> str | None
Return subclass-provided content used by render() when omitted.
Returns:
| Type | Description |
|---|---|
str | None
|
Default content, or |
Source code in hotstring\core\models.py
259 260 261 262 263 264 265 | |
CandidateHotstring
dataclass
¶
Represent an abstract proposed hotstring correction.
Candidate constructor trigger input is semantic text, so this class keeps
the inherited TRIGGER_INPUT_IS_AHK_SOURCE = False policy. Concrete
subclasses define how the semantic replacement is converted into
AutoHotkey content. The computed content is cached once during
initialization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
InitVar[str]
|
Semantic trigger text proposed for the candidate. |
required |
options_input
|
InitVar[str | HotstringOptions]
|
Raw or already parsed hotstring options. |
required |
replacement
|
str
|
Intended semantic replacement text. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
replacement |
str
|
Intended semantic replacement text. |
content |
str
|
Derived AutoHotkey content computed by the concrete subclass. |
Source code in hotstring\core\models.py
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 | |
__post_init__ ¶
__post_init__(
trigger: str, options_input: str | HotstringOptions
) -> None
Validate the candidate and derive its AutoHotkey content.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
str
|
Semantic trigger constructor input. |
required |
options_input
|
str | HotstringOptions
|
Raw or parsed option constructor input. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If base hotstring initialization rejects an input. |
AssertionError
|
If an enabled base trigger invariant check fails. |
Source code in hotstring\core\models.py
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 | |
compute_content
abstractmethod
¶
Convert semantic replacement text into concrete AHK content.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
replacement
|
str
|
Stored candidate replacement. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Content suitable for the concrete candidate type. |
Source code in hotstring\core\models.py
332 333 334 335 336 337 338 339 340 341 342 343 | |
_default_content ¶
_default_content() -> str
Return the candidate's precomputed content for default rendering.
Returns:
| Type | Description |
|---|---|
str
|
Precomputed candidate content. |
Source code in hotstring\core\models.py
345 346 347 348 349 350 351 | |
ExistingHotstring
dataclass
¶
Bases: Hotstring
Represent an existing hotstring discovered in an AHK source file.
Unlike the generic and candidate models, trigger passed to this class is
interpreted as AHK source-form trigger text. The class expresses that
difference only by shadowing TRIGGER_INPUT_IS_AHK_SOURCE; the base
__post_init__() still owns the complete resolution algorithm. Existing
source is decoded to semantic form and re-encoded to the project's
canonical minimally escaped AHK form, so equivalent source spellings
produce identical stored trigger state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
InitVar[str]
|
Trigger source spelling extracted from the AHK declaration. |
required |
options_input
|
InitVar[str | HotstringOptions]
|
Raw or parsed hotstring options. |
required |
source
|
Path
|
Source path from which the declaration was extracted. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
source |
Path
|
Source path from which the declaration was extracted. |
Source code in hotstring\core\models.py
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | |
__post_init__ ¶
__post_init__(
trigger: str, options_input: str | HotstringOptions
) -> None
Resolve the AHK trigger input and validate the source field.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
str
|
AHK source-form trigger constructor input. |
required |
options_input
|
str | HotstringOptions
|
Raw or parsed option constructor input. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If the trigger or option input is invalid. |
AssertionError
|
If an enabled base trigger invariant check fails. |
Source code in hotstring\core\models.py
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | |
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 | |
Hotstring options¶
This module contains the declared option model, inheritance sentinel, semantic enums, and fully resolved option model.
The declared send mode uses SendMode (INPUT, PLAY, and EVENT). Fully
resolved options use the separate ResolvedSendMode enum so Input's Play and
Event fallback behaviors remain explicit without complicating the field type.
options ¶
Parse, normalize, and resolve AutoHotkey v2 hotstring option strings.
HotstringOptions is the single source
of truth for interpreting per-hotstring option strings in this project.
Omitted inheritable options are represented by the enum member INHERIT of
InheritedState.
ResolvedHotstringOptions
represents the corresponding fully resolved semantic state.
InheritedState ¶
Bases: Enum
Represent an option value inherited from the applicable defaults.
Attributes:
| Name | Type | Description |
|---|---|---|
INHERIT |
The option is not explicitly set and should inherit from the applicable default. |
Source code in hotstring\core\options.py
27 28 29 30 31 32 33 34 35 36 | |
SettingState ¶
Bases: Enum
Represent the explicit state of a two-state option.
Attributes:
| Name | Type | Description |
|---|---|---|
ENABLED |
The option behavior is explicitly enabled. |
|
DISABLED |
The option behavior is explicitly disabled. |
Source code in hotstring\core\options.py
39 40 41 42 43 44 45 46 47 48 49 50 | |
CaseMode ¶
Bases: Enum
Represent AutoHotkey hotstring case-matching behavior.
Attributes:
| Name | Type | Description |
|---|---|---|
SENSITIVE |
Match the trigger case-sensitively. |
|
INSENSITIVE_CONFORMING |
Match case-insensitively and allow replacement case conformation. |
|
INSENSITIVE_FIXED |
Match case-insensitively without replacement case conformation. |
Source code in hotstring\core\options.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
ReplacementMode ¶
Bases: Enum
Represent AutoHotkey replacement-text interpretation behavior.
Attributes:
| Name | Type | Description |
|---|---|---|
NORMAL |
Use normal replacement processing. |
|
RAW |
Use raw replacement processing. |
|
TEXT |
Use text-mode replacement processing. |
Source code in hotstring\core\options.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
SendMode ¶
Bases: Enum
Represent the explicitly selected hotstring send mode.
Attributes:
| Name | Type | Description |
|---|---|---|
INPUT |
Explicitly select SendInput. |
|
PLAY |
Explicitly select SendPlay. |
|
EVENT |
Explicitly select SendEvent. |
Source code in hotstring\core\options.py
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | |
ResolvedSendMode ¶
Bases: Enum
Represent the fully resolved hotstring send behavior.
Attributes:
| Name | Type | Description |
|---|---|---|
INPUT_WITH_PLAY_FALLBACK |
Explicit |
|
INPUT_WITH_EVENT_FALLBACK |
Built-in default: use SendInput with SendEvent fallback. |
|
PLAY |
Use SendPlay. |
|
EVENT |
Use SendEvent. |
Source code in hotstring\core\options.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
HotstringOptions
dataclass
¶
Represent a validated per-hotstring AutoHotkey option declaration.
The original option string is retained in options. Every omitted option
is represented by the singleton InheritedState.INHERIT, preserving the
distinction between an inherited value and an explicitly selected value.
Attributes:
| Name | Type | Description |
|---|---|---|
options |
str
|
Original validated option string with surrounding horizontal whitespace removed. |
ending_character_optional |
SettingState | InheritedState
|
Whether the hotstring may activate without an ending character,
or |
trigger_inside_word |
SettingState | InheritedState
|
Explicit inside-word matching state, or |
automatic_backspacing |
SettingState | InheritedState
|
Explicit automatic-backspacing state, or |
case_mode |
CaseMode | InheritedState
|
Explicit case-matching mode, or |
key_delay |
int | InheritedState
|
Explicit key delay, or |
omit_ending_character |
SettingState | InheritedState
|
Explicit ending-character omission state, or |
priority |
int | InheritedState
|
Explicit priority, or |
replacement_mode |
ReplacementMode | InheritedState
|
Explicit replacement-processing mode, or |
suspend_exempt |
SettingState | InheritedState
|
Explicit suspension-exemption state, or |
send_mode |
SendMode | InheritedState
|
Explicit send mode, or |
execute |
SettingState | InheritedState
|
Explicit execute state, or |
reset_recognizer |
SettingState | InheritedState
|
Explicit recognizer-reset state, or |
Source code in hotstring\core\options.py
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 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | |
__post_init__ ¶
__post_init__() -> None
Validate and parse the supplied option string.
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If the string contains an unsupported option or an invalid numeric value. |
Source code in hotstring\core\options.py
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 370 | |
declaration ¶
declaration() -> str
Return a canonical option string for the parsed semantic state.
Returns:
| Type | Description |
|---|---|
str
|
Canonical option text in dataclass field order. Inherited options |
str
|
are omitted. |
Source code in hotstring\core\options.py
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | |
ResolvedHotstringOptions
dataclass
¶
Represent a fully resolved AutoHotkey hotstring option state.
Unlike HotstringOptions, every
field contains a concrete semantic value. InheritedState is therefore
absent from every field annotation.
Attributes:
| Name | Type | Description |
|---|---|---|
ending_character_optional |
SettingState
|
Whether the hotstring may activate without an ending character. |
trigger_inside_word |
SettingState
|
Whether the trigger may begin after an alphanumeric character. |
automatic_backspacing |
SettingState
|
Whether AutoHotkey automatically erases the typed trigger. |
case_mode |
CaseMode
|
Effective case-matching mode. |
key_delay |
int
|
Effective hotstring key delay. |
omit_ending_character |
SettingState
|
Whether an ending character is omitted from replacement output. |
priority |
int
|
Effective hotstring thread priority. |
replacement_mode |
ReplacementMode
|
Effective replacement-text processing mode. |
suspend_exempt |
SettingState
|
Whether the hotstring is exempt from suspension. |
send_mode |
ResolvedSendMode
|
Effective replacement send mode. |
execute |
SettingState
|
Whether inline content is executed rather than used as literal replacement text. |
reset_recognizer |
SettingState
|
Whether the recognizer resets after activation. |
Source code in hotstring\core\options.py
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 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 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 | |
__post_init__ ¶
__post_init__() -> None
Validate the resolved option state.
Raises:
| Type | Description |
|---|---|
TypeError
|
If any field has an invalid type. |
ValueError
|
If any numeric field is outside its accepted range. |
Source code in hotstring\core\options.py
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | |
from_options
classmethod
¶
from_options(
options: HotstringOptions,
*,
defaults: ResolvedHotstringOptions,
) -> Self
Resolve one parsed declaration against concrete applicable defaults.
Each explicitly set value in options overrides the corresponding
value in defaults; each InheritedState.INHERIT value leaves the
applicable default unchanged.
Explicit SI is resolved to SendInput with SendPlay fallback, while
an inherited built-in default can remain SendInput with SendEvent
fallback. This preserves AutoHotkey's distinction between those cases.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
options
|
HotstringOptions
|
Parsed per-hotstring declaration to resolve. |
required |
defaults
|
ResolvedHotstringOptions
|
Fully resolved defaults applicable to the declaration. |
required |
Returns:
| Type | Description |
|---|---|
Self
|
New fully resolved option state. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If either argument has an invalid type. |
RuntimeError
|
If the parsed and resolved option models stop exposing the same option field names. |
Source code in hotstring\core\options.py
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 | |
Conflict detection¶
conflicts ¶
Detect trigger-recognition conflicts between candidate and existing hotstrings.
Conflict detection models the three trigger-recognition dimensions relevant to whether two hotstrings can activate on overlapping typed text:
- case sensitivity (
C/C0/C1); - whether an alphanumeric predecessor is permitted (
?/?0); - whether an ending character is required (
*/*0).
Other hotstring options affect replacement or execution behavior rather than trigger recognition and therefore do not restrict conflict checking.
ConflictKind ¶
Bases: Enum
Classify why two hotstrings conflict.
Attributes:
| Name | Type | Description |
|---|---|---|
SAME_TRIGGER |
Candidate and existing definitions can recognize the same complete trigger text. |
|
EXISTING_FIRES_DURING_CANDIDATE |
The existing definition can become eligible while a valid typed form of the candidate trigger is being entered. |
|
CANDIDATE_FIRES_DURING_EXISTING |
The candidate can become eligible while a valid typed form of the existing trigger is being entered. |
Source code in hotstring\core\conflicts.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
HotstringConflict
dataclass
¶
Describe one conflict between a candidate and an existing definition.
Attributes:
| Name | Type | Description |
|---|---|---|
candidate |
CandidateHotstring
|
Candidate involved in the conflict. |
existing |
ExistingHotstring
|
Existing definition involved in the conflict. |
kind |
ConflictKind
|
Conflict classification. |
reason |
str
|
Human-readable explanation of the matching overlap. |
Source code in hotstring\core\conflicts.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
CandidateAssessment
dataclass
¶
Represent all conflicts discovered for one candidate.
Attributes:
| Name | Type | Description |
|---|---|---|
candidate |
CandidateHotstring
|
Candidate that was checked. |
conflicts |
tuple[HotstringConflict, ...]
|
All conflicting existing hotstrings. |
Source code in hotstring\core\conflicts.py
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | |
_TriggerOverlap
dataclass
¶
Describe a trigger occurrence satisfying both recognition boundaries.
Attributes:
| Name | Type | Description |
|---|---|---|
start |
int
|
Inclusive start index inside the containing semantic trigger. |
end |
int
|
Exclusive end index inside the containing semantic trigger. |
left_reason |
str
|
Explanation of the valid left boundary. |
right_reason |
str
|
Explanation of the valid right boundary. |
Source code in hotstring\core\conflicts.py
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 | |
find_conflict ¶
find_conflict(
candidate: CandidateHotstring,
existing: ExistingHotstring,
*,
ending_chars: frozenset[str] = DEFAULT_ENDING_CHARS,
option_defaults: ResolvedHotstringOptions = DEFAULT_HOTSTRING_OPTIONS,
) -> HotstringConflict | None
Check one candidate against one existing hotstring.
All combinations of case sensitivity, inside-word recognition, and ending-character requirements are supported for both definitions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidate
|
CandidateHotstring
|
Candidate to check. |
required |
existing
|
ExistingHotstring
|
Existing definition to compare against. |
required |
ending_chars
|
frozenset[str]
|
Effective AutoHotkey ending-character set. |
DEFAULT_ENDING_CHARS
|
option_defaults
|
ResolvedHotstringOptions
|
Fully resolved defaults applicable to inherited hotstring options. |
DEFAULT_HOTSTRING_OPTIONS
|
Returns:
| Type | Description |
|---|---|
HotstringConflict | None
|
Detected conflict, or |
Source code in hotstring\core\conflicts.py
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 | |
assess_candidate ¶
assess_candidate(
candidate: CandidateHotstring,
existing_hotstrings: Sequence[ExistingHotstring],
*,
ending_chars: frozenset[str] = DEFAULT_ENDING_CHARS,
option_defaults: ResolvedHotstringOptions = DEFAULT_HOTSTRING_OPTIONS,
) -> CandidateAssessment
Check one candidate against all existing definitions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidate
|
CandidateHotstring
|
Candidate to evaluate. |
required |
existing_hotstrings
|
Sequence[ExistingHotstring]
|
Existing definitions to compare against. |
required |
ending_chars
|
frozenset[str]
|
Effective AutoHotkey ending-character set. |
DEFAULT_ENDING_CHARS
|
option_defaults
|
ResolvedHotstringOptions
|
Fully resolved defaults applicable to inherited hotstring options. |
DEFAULT_HOTSTRING_OPTIONS
|
Returns:
| Type | Description |
|---|---|
CandidateAssessment
|
Complete candidate assessment. |
Source code in hotstring\core\conflicts.py
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 | |
assess_candidates ¶
assess_candidates(
candidates: Sequence[CandidateHotstring],
existing_hotstrings: Sequence[ExistingHotstring],
*,
ending_chars: frozenset[str] = DEFAULT_ENDING_CHARS,
option_defaults: ResolvedHotstringOptions = DEFAULT_HOTSTRING_OPTIONS,
) -> tuple[CandidateAssessment, ...]
Check multiple candidates against all existing definitions.
Candidate-to-candidate checking is intentionally not performed here; typo-generation aggregation handles internal candidate ambiguity before the full pipeline reaches this stage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidates
|
Sequence[CandidateHotstring]
|
Candidates to evaluate. |
required |
existing_hotstrings
|
Sequence[ExistingHotstring]
|
Existing definitions to compare against. |
required |
ending_chars
|
frozenset[str]
|
Effective ending-character set. |
DEFAULT_ENDING_CHARS
|
option_defaults
|
ResolvedHotstringOptions
|
Fully resolved defaults applicable to inherited hotstring options. |
DEFAULT_HOTSTRING_OPTIONS
|
Returns:
| Type | Description |
|---|---|
tuple[CandidateAssessment, ...]
|
Candidate assessments in input order. |
Source code in hotstring\core\conflicts.py
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 | |
_find_candidate_conflict ¶
_find_candidate_conflict(
candidate: CandidateHotstring,
candidate_options: ResolvedHotstringOptions,
existing: ExistingHotstring,
existing_options: ResolvedHotstringOptions,
*,
ending_chars: frozenset[str],
) -> HotstringConflict | None
Check one existing definition against one candidate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidate
|
CandidateHotstring
|
Candidate definition. |
required |
candidate_options
|
ResolvedHotstringOptions
|
Fully resolved candidate options. |
required |
existing
|
ExistingHotstring
|
Existing definition. |
required |
existing_options
|
ResolvedHotstringOptions
|
Fully resolved existing options. |
required |
ending_chars
|
frozenset[str]
|
Effective ending-character set. |
required |
Returns:
| Type | Description |
|---|---|
HotstringConflict | None
|
Detected conflict, or |
Source code in hotstring\core\conflicts.py
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 | |
_same_trigger_can_match ¶
_same_trigger_can_match(
candidate: Hotstring,
*,
candidate_case_sensitive: bool,
existing: Hotstring,
existing_case_sensitive: bool,
) -> bool
Return whether two complete trigger definitions share a typed form.
If both hotstrings are case-sensitive, their semantic triggers must match exactly. If either definition is case-insensitive, a shared casing exists whenever their AutoHotkey-compatible case-insensitive keys are equal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidate
|
Hotstring
|
First hotstring. |
required |
candidate_case_sensitive
|
bool
|
Whether the first hotstring requires exact case. |
required |
existing
|
Hotstring
|
Second hotstring. |
required |
existing_case_sensitive
|
bool
|
Whether the second hotstring requires exact case. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether the two complete trigger definitions can recognize the same |
bool
|
typed text. |
Source code in hotstring\core\conflicts.py
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
_iter_trigger_overlaps ¶
_iter_trigger_overlaps(
*,
trigger: Hotstring,
container: Hotstring,
allow_alphanumeric_predecessor: bool,
require_ending_character: bool,
trigger_case_sensitive: bool,
container_case_sensitive: bool,
ending_chars: frozenset[str],
) -> Iterator[_TriggerOverlap]
Yield occurrences satisfying trigger recognition and both boundaries.
trigger is the hotstring whose ability to activate is being tested.
container is the other hotstring whose trigger is being typed.
Case handling must consider both definitions. If both are case-sensitive, only the exact source-defined casing of the container is a valid typed form. If either is case-insensitive, a shared casing can exist for an occurrence whenever the corresponding case-insensitive keys match.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
Hotstring
|
Hotstring whose activation is being tested. |
required |
container
|
Hotstring
|
Other hotstring whose semantic trigger is being typed around it. |
required |
allow_alphanumeric_predecessor
|
bool
|
Whether the tested hotstring permits an alphanumeric predecessor. |
required |
require_ending_character
|
bool
|
Whether the tested hotstring requires an ending character. |
required |
trigger_case_sensitive
|
bool
|
Whether the tested hotstring requires exact trigger casing. |
required |
container_case_sensitive
|
bool
|
Whether the containing hotstring requires exact trigger casing. |
required |
ending_chars
|
frozenset[str]
|
Effective ending-character set. |
required |
Yields:
| Type | Description |
|---|---|
_TriggerOverlap
|
Every boundary-valid occurrence. |
Source code in hotstring\core\conflicts.py
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 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 449 450 451 452 453 454 455 456 457 458 459 460 461 | |
_iter_hotstring_occurrence_starts ¶
_iter_hotstring_occurrence_starts(
*,
trigger: Hotstring,
container: Hotstring,
require_exact_case: bool,
) -> Iterator[int]
Yield semantic occurrence starts under the required case semantics.
The normal Windows path searches the already cached semantic or
case-insensitive trigger strings directly. A defensive fallback preserves
original semantic indices if a non-Windows str.lower() transformation
changes Unicode string length.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
Hotstring
|
Hotstring whose semantic trigger is being located. |
required |
container
|
Hotstring
|
Hotstring whose semantic trigger is being searched. |
required |
require_exact_case
|
bool
|
Whether both definitions require exact casing. |
required |
Yields:
| Type | Description |
|---|---|
int
|
Start index of each occurrence in |
Source code in hotstring\core\conflicts.py
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | |
_iter_occurrence_starts ¶
Yield every exact string occurrence start, including overlaps.
Repeated str.find() is used instead of a regex lookahead. Advancing the
next search by one character, rather than by the matched trigger length,
preserves overlapping occurrences such as both ana matches in
banana.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trigger
|
str
|
Exact string to locate. |
required |
container
|
str
|
String in which to locate it. |
required |
Yields:
| Type | Description |
|---|---|
int
|
Start index of each occurrence. |
Source code in hotstring\core\conflicts.py
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 | |
_left_boundary_reason ¶
_left_boundary_reason(
*,
container: str,
start: int,
allow_alphanumeric_predecessor: bool,
) -> str | None
Evaluate the left boundary of one occurrence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
container
|
str
|
Semantic trigger containing the occurrence. |
required |
start
|
int
|
Occurrence start index. |
required |
allow_alphanumeric_predecessor
|
bool
|
Whether an alphanumeric predecessor is allowed. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
Explanation of a valid boundary, or |
Source code in hotstring\core\conflicts.py
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 | |
_right_boundary_reason ¶
_right_boundary_reason(
*,
container: str,
end: int,
require_ending_character: bool,
ending_chars: frozenset[str],
) -> str | None
Evaluate the right boundary of one occurrence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
container
|
str
|
Semantic trigger containing the occurrence. |
required |
end
|
int
|
Exclusive occurrence end index. |
required |
require_ending_character
|
bool
|
Whether activation requires an ending character. |
required |
ending_chars
|
frozenset[str]
|
Effective ending-character set. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
Explanation of a valid boundary, or |
Source code in hotstring\core\conflicts.py
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | |
Core constants¶
constants ¶
Define generic project constants for AutoHotkey hotstring semantics.
DEFAULT_ENDING_CHARS
module-attribute
¶
AutoHotkey v2's built-in hotstring ending-character set.
DEFAULT_HOTSTRING_OPTIONS
module-attribute
¶
DEFAULT_HOTSTRING_OPTIONS: Final[
ResolvedHotstringOptions
] = ResolvedHotstringOptions(
ending_character_optional=SettingState.DISABLED,
trigger_inside_word=SettingState.DISABLED,
automatic_backspacing=SettingState.ENABLED,
case_mode=CaseMode.INSENSITIVE_CONFORMING,
key_delay=0,
omit_ending_character=SettingState.DISABLED,
priority=0,
replacement_mode=ReplacementMode.NORMAL,
suspend_exempt=SettingState.DISABLED,
send_mode=ResolvedSendMode.INPUT_WITH_EVENT_FALLBACK,
execute=SettingState.DISABLED,
reset_recognizer=SettingState.DISABLED,
)
AutoHotkey's built-in fully resolved hotstring option defaults.
Pipelines¶
pipeline ¶
Expose the three independent project execution pipelines.
The full workflow is deliberately implemented as composition of the typo- generation-only and AutoCorrect2-only workflows. Neither subsystem depends on the other, which keeps generation policy separate from AutoHotkey source inspection and conflict detection.
GENERATED_CANDIDATE_OPTIONS
module-attribute
¶
GENERATED_CANDIDATE_OPTIONS: Final[HotstringOptions] = (
HotstringOptions("B0X")
)
Options assigned when the full pipeline converts typo mappings to hotstrings.
FullPipelineResult
dataclass
¶
Represent the two results produced by the composed full pipeline.
Attributes:
| Name | Type | Description |
|---|---|---|
typo_generation |
TypoGenerationResult
|
Result of typo generation and internal ambiguity filtering. |
autocorrect2 |
AutoCorrect2CheckResult
|
Result of checking the surviving candidates against AutoCorrect2. |
Source code in hotstring\pipeline.py
37 38 39 40 41 42 43 44 45 46 47 48 49 | |
run_typo_generation ¶
run_typo_generation(
word_list: Sequence[str],
tasks: Sequence[TypoGenerationTask],
config: TypoGenerationConfig,
*,
n_workers: int | None = None,
report_path: Path | None = None,
logger: Logger | None = None,
) -> TypoGenerationResult
Run typo generation and internal ambiguity filtering only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
word_list
|
Sequence[str]
|
Source words to corrupt. |
required |
tasks
|
Sequence[TypoGenerationTask]
|
Ordered typo-generation tasks to execute. |
required |
config
|
TypoGenerationConfig
|
Shared MULTYPO generator configuration. |
required |
n_workers
|
int | None
|
Optional process-pool size. |
None
|
report_path
|
Path | None
|
Optional destination for a typo-generation-only report. |
None
|
logger
|
Logger | None
|
Optional orchestration logger forwarded to the execution layer. |
None
|
Returns:
| Type | Description |
|---|---|
TypoGenerationResult
|
Aggregated typo-generation result containing valid mappings and |
TypoGenerationResult
|
internally ambiguous noisy forms. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If task/execution inputs have invalid types. |
ValueError
|
If no generation tasks are supplied or a generation setting is invalid. |
RuntimeError
|
If a parallel generation task fails. |
OSError
|
If a requested report cannot be written. |
Source code in hotstring\pipeline.py
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 | |
run_autocorrect2_check ¶
run_autocorrect2_check(
candidates: Sequence[AutoCorrect2CandidateHotstring],
*,
project_dir: Path,
report_path: Path | None = None,
write_accepted: bool = False,
) -> AutoCorrect2CheckResult
Check manually supplied candidates against active AutoCorrect2 hotstrings.
Trigger conflict detection supports every combination of the recognition
options currently modeled by the project: ending-character-free matching
(*), inside-word matching (?), and case-sensitive matching (C). No
candidate is rejected merely for using one of those semantics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidates
|
Sequence[AutoCorrect2CandidateHotstring]
|
AutoCorrect2 candidates supplied directly by the caller. |
required |
project_dir
|
Path
|
AutoCorrect2 project directory containing the configured source files. |
required |
report_path
|
Path | None
|
Optional destination for an AutoCorrect2-only report. |
None
|
write_accepted
|
bool
|
Append accepted candidates to the generated include file when
|
False
|
Returns:
| Type | Description |
|---|---|
AutoCorrect2CheckResult
|
Conflict-check result partitioning candidates into accepted and |
AutoCorrect2CheckResult
|
rejected groups. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If a required AutoCorrect2 source file is missing. |
UnicodeDecodeError
|
If a source requiring parsing is not valid UTF-8 text. |
ValueError
|
If source data is invalid or writing is requested for a candidate
that violates the writer's explicit |
OSError
|
If authoritative sources, reports, or generated files cannot be read or written. |
Source code in hotstring\pipeline.py
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 | |
run_full_pipeline ¶
run_full_pipeline(
word_list: Sequence[str],
tasks: Sequence[TypoGenerationTask],
config: TypoGenerationConfig,
*,
project_dir: Path,
n_workers: int | None = None,
report_path: Path | None = None,
write_accepted: bool = False,
logger: Logger | None = None,
) -> FullPipelineResult
Run typo generation followed by AutoCorrect2 conflict checking.
The function composes the two independent stage pipelines without asking
either stage to emit its own report. Surviving typo mappings are converted
to AutoCorrect2CandidateHotstring objects with
the project's fixed generated B0X option set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
word_list
|
Sequence[str]
|
Source words to corrupt. |
required |
tasks
|
Sequence[TypoGenerationTask]
|
Ordered typo-generation tasks to execute. |
required |
config
|
TypoGenerationConfig
|
Shared MULTYPO generator configuration. |
required |
project_dir
|
Path
|
AutoCorrect2 project directory. |
required |
n_workers
|
int | None
|
Optional process-pool size. |
None
|
report_path
|
Path | None
|
Optional destination for the combined report. |
None
|
write_accepted
|
bool
|
Append final accepted candidates to the generated include file. |
False
|
logger
|
Logger | None
|
Optional typo-generation orchestration logger. |
None
|
Returns:
| Type | Description |
|---|---|
FullPipelineResult
|
Combined result containing both stage results. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If generation or source-loading inputs have invalid types. |
ValueError
|
If generation/source data is invalid or a writable candidate violates the generated-file contract. |
FileNotFoundError
|
If a required AutoCorrect2 source file is missing. |
UnicodeDecodeError
|
If an authoritative source requiring parsing is not valid UTF-8. |
RuntimeError
|
If a parallel generation task fails. |
OSError
|
If source, report, or generated files cannot be read or written. |
Source code in hotstring\pipeline.py
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 | |
_write_report ¶
Build and write one complete report document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Destination report file. |
required |
title
|
str
|
Top-level report title. |
required |
body_lines
|
Sequence[str]
|
Pipeline-specific report body lines. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the report title is empty. |
OSError
|
If the report cannot be written. |
Source code in hotstring\pipeline.py
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | |
CLI
Command-line interface API¶
hotstring.cli contains the application layer for the project's command-line
interface. It converts command-line input into validated runtime objects and
dispatches those objects to the public pipeline APIs.
The subpackage does not implement typo generation, conflict detection, source loading, or generated-file writing. Those responsibilities remain in their respective domain and pipeline modules.
The subpackage contains:
- Application, which defines the CLI entry point, logging setup, process-level error handling, and exit statuses;
- Parser, which defines the top-level parser, the three subcommands, and their arguments;
- Runtime configuration, which loads external inputs, resolves the AutoCorrect2 project directory, constructs typo-generation tasks, and creates immutable command objects;
- Command execution, which dispatches validated command objects to the corresponding pipeline functions and prints terminal summaries.
The package root re-exports
main(), allowing the repository-level
main.py entry point to import it with:
from hotstring.cli import main
Application¶
application ¶
Define the command-line application's process boundary.
This module coordinates argument parsing, runtime configuration, logging, and
command execution. Domain work remains in hotstring.pipeline, while
parser and input-resolution details live in sibling CLI modules.
main ¶
Run the command-line interface.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
argv
|
Sequence[str] | None
|
Optional argument sequence excluding the executable name. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Process exit status: zero for success, one for a runtime failure, or |
int
|
130 when execution is interrupted. Invalid command-line input is |
int
|
reported by |
Source code in hotstring\cli\application.py
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 | |
_configure_logging ¶
_configure_logging(verbosity: int) -> None
Configure application logging for the requested verbosity.
Logging is left untouched at the default verbosity so library consumers and multiprocessing workers do not inherit an unnecessary root handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
verbosity
|
int
|
Number of |
required |
Source code in hotstring\cli\application.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | |
Parser¶
parser ¶
Construct the command-line parser and its three subcommands.
Parser construction is intentionally separate from runtime resolution. This
module describes syntax and performs scalar validation; create_command_config() resolves files, environment
configuration, and domain objects after parsing succeeds.
create_argument_parser ¶
create_argument_parser() -> ArgumentParser
Create the complete top-level argument parser.
The parser exposes three independent workflows: typo generation, AutoCorrect2 conflict checking, and their composed full pipeline. Shared options are added by private helpers so their spelling and validation stay consistent across subcommands.
Returns:
| Type | Description |
|---|---|
ArgumentParser
|
Configured parser ready to parse a command-line argument sequence. |
Source code in hotstring\cli\parser.py
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 | |
_add_word_source_arguments ¶
_add_word_source_arguments(parser: ArgumentParser) -> None
Add the mutually exclusive source-word inputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parser
|
ArgumentParser
|
Subparser receiving the arguments. |
required |
Source code in hotstring\cli\parser.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
_add_candidate_source_arguments ¶
_add_candidate_source_arguments(
parser: ArgumentParser,
) -> None
Add the mutually exclusive candidate inputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parser
|
ArgumentParser
|
Subparser receiving the arguments. |
required |
Source code in hotstring\cli\parser.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
_add_generation_arguments ¶
_add_generation_arguments(parser: ArgumentParser) -> None
Add settings shared by typo-generating commands.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parser
|
ArgumentParser
|
Subparser receiving the arguments. |
required |
Source code in hotstring\cli\parser.py
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 | |
_add_autocorrect2_arguments ¶
_add_autocorrect2_arguments(parser: ArgumentParser) -> None
Add settings shared by AutoCorrect2-aware commands.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parser
|
ArgumentParser
|
Subparser receiving the arguments. |
required |
Source code in hotstring\cli\parser.py
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 | |
_add_report_argument ¶
_add_report_argument(parser: ArgumentParser) -> None
Add the optional report destination.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parser
|
ArgumentParser
|
Subparser receiving the argument. |
required |
Source code in hotstring\cli\parser.py
227 228 229 230 231 232 233 234 235 236 237 238 239 | |
_positive_integer ¶
Parse a strictly positive integer for argparse.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
Raw argument text. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Parsed positive integer. |
Raises:
| Type | Description |
|---|---|
ArgumentTypeError
|
If the value is not an integer greater than zero. |
Source code in hotstring\cli\parser.py
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | |
_minimum_two_integer ¶
Parse an integer greater than or equal to two.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
Raw argument text. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Parsed integer. |
Raises:
| Type | Description |
|---|---|
ArgumentTypeError
|
If the value is not an integer of at least two. |
Source code in hotstring\cli\parser.py
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | |
_positive_number ¶
Parse a strictly positive floating-point value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
Raw argument text. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Parsed positive number. |
Raises:
| Type | Description |
|---|---|
ArgumentTypeError
|
If the value is not finite and greater than zero. |
Source code in hotstring\cli\parser.py
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | |
_nonempty_text ¶
Reject an empty or whitespace-only text argument.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
Raw argument text. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Trimmed text. |
Raises:
| Type | Description |
|---|---|
ArgumentTypeError
|
If the value contains no non-whitespace characters. |
Source code in hotstring\cli\parser.py
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | |
Runtime configuration¶
runtime ¶
Resolve parsed CLI input into immutable runtime command objects.
This module owns the application-specific boundary between argparse values
and the project's domain APIs. It loads word and candidate files, constructs
TypoGenerationTask
objects, resolves the AutoCorrect2 project directory, and validates paths
before a pipeline starts.
AUTOCORRECT2_PROJECT_DIR_ENV
module-attribute
¶
Environment variable containing the local AutoCorrect2 project path.
DEFAULT_ENV_FILE
module-attribute
¶
DEFAULT_ENV_FILE: Final[Path] = PROJECT_ROOT / '.env'
Project-local dotenv file consulted as the final configuration source.
CommandConfig ¶
CommandConfig = (
TypoGenerationCommand
| AutoCorrect2CheckCommand
| FullPipelineCommand
)
Union of all command objects accepted by the execution layer.
CliConfigurationError ¶
Bases: ValueError
Indicate invalid runtime configuration supplied through the CLI.
Source code in hotstring\cli\runtime.py
40 41 | |
GenerationRuntimeConfig
dataclass
¶
Store resolved inputs shared by typo-generating workflows.
Attributes:
| Name | Type | Description |
|---|---|---|
words |
tuple[str, ...]
|
Ordered, de-duplicated source words. |
tasks |
tuple[TypoGenerationTask, ...]
|
Ordered typo-generation tasks derived from CLI settings. |
config |
TypoGenerationConfig
|
Shared MULTYPO generator configuration. |
n_workers |
int | None
|
Optional process-pool size. |
Source code in hotstring\cli\runtime.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
AutoCorrect2RuntimeConfig
dataclass
¶
Store resolved inputs shared by AutoCorrect2-aware workflows.
Attributes:
| Name | Type | Description |
|---|---|---|
project_dir |
Path
|
Validated AutoCorrect2 project directory. |
write_accepted |
bool
|
Whether accepted candidates may be appended to the generated include file. |
Source code in hotstring\cli\runtime.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
TypoGenerationCommand
dataclass
¶
Represent one standalone typo-generation invocation.
Attributes:
| Name | Type | Description |
|---|---|---|
generation |
GenerationRuntimeConfig
|
Resolved typo-generation inputs. |
report_path |
Path | None
|
Optional report destination. |
Source code in hotstring\cli\runtime.py
81 82 83 84 85 86 87 88 89 90 91 92 93 | |
AutoCorrect2CheckCommand
dataclass
¶
Represent one standalone AutoCorrect2 conflict-check invocation.
Attributes:
| Name | Type | Description |
|---|---|---|
candidates |
tuple[AutoCorrect2CandidateHotstring, ...]
|
Candidate hotstrings supplied directly by the user. |
autocorrect2 |
AutoCorrect2RuntimeConfig
|
Resolved AutoCorrect2 integration settings. |
report_path |
Path | None
|
Optional report destination. |
Source code in hotstring\cli\runtime.py
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | |
FullPipelineCommand
dataclass
¶
Represent one composed generation-and-check invocation.
Attributes:
| Name | Type | Description |
|---|---|---|
generation |
GenerationRuntimeConfig
|
Resolved typo-generation inputs. |
autocorrect2 |
AutoCorrect2RuntimeConfig
|
Resolved AutoCorrect2 integration settings. |
report_path |
Path | None
|
Optional combined report destination. |
Source code in hotstring\cli\runtime.py
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | |
create_command_config ¶
create_command_config(
namespace: Namespace,
) -> CommandConfig
Convert parsed arguments into one validated command object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
namespace
|
Namespace
|
Namespace returned by
|
required |
Returns:
| Type | Description |
|---|---|
CommandConfig
|
Immutable configuration for the selected workflow. |
Raises:
| Type | Description |
|---|---|
CliConfigurationError
|
If a file, path, environment value, candidate, or domain setting is invalid. |
Source code in hotstring\cli\runtime.py
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 | |
_create_generation_config ¶
_create_generation_config(
namespace: Namespace,
) -> GenerationRuntimeConfig
Build the shared typo-generation runtime configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
namespace
|
Namespace
|
Parsed command arguments. |
required |
Returns:
| Type | Description |
|---|---|
GenerationRuntimeConfig
|
Resolved generation configuration. |
Source code in hotstring\cli\runtime.py
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 | |
_create_autocorrect2_config ¶
_create_autocorrect2_config(
namespace: Namespace,
) -> AutoCorrect2RuntimeConfig
Build the shared AutoCorrect2 runtime configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
namespace
|
Namespace
|
Parsed command arguments. |
required |
Returns:
| Type | Description |
|---|---|
AutoCorrect2RuntimeConfig
|
Resolved AutoCorrect2 configuration. |
Source code in hotstring\cli\runtime.py
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | |
_load_words ¶
Load, normalize, and de-duplicate source words.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
namespace
|
Namespace
|
Parsed command arguments. |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, ...]
|
Ordered source-word tuple. |
Raises:
| Type | Description |
|---|---|
CliConfigurationError
|
If the word source is unreadable or contains no usable words. |
Source code in hotstring\cli\runtime.py
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 | |
_load_candidates ¶
_load_candidates(
namespace: Namespace,
) -> tuple[AutoCorrect2CandidateHotstring, ...]
Load and validate directly supplied candidate hotstrings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
namespace
|
Namespace
|
Parsed command arguments. |
required |
Returns:
| Type | Description |
|---|---|
tuple[AutoCorrect2CandidateHotstring, ...]
|
Candidate tuple in source order. |
Raises:
| Type | Description |
|---|---|
CliConfigurationError
|
If candidate data is missing, malformed, or invalid. |
Source code in hotstring\cli\runtime.py
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 | |
_candidate_fields ¶
Extract the three candidate fields from CLI or JSON input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
object
|
Three-value CLI sequence or JSON object. |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, str, str]
|
Semantic trigger, semantic replacement, and option declaration. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the record shape or a field type is invalid. |
ValueError
|
If a JSON object has missing or unexpected fields. |
Source code in hotstring\cli\runtime.py
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 | |
_resolve_autocorrect2_project_dir ¶
_resolve_autocorrect2_project_dir(
*,
direct_path: Path | None,
explicit_env_file: Path | None,
) -> Path
Resolve the AutoCorrect2 project path by documented precedence.
Resolution stops at the first configured source:
--project-dir;- the process environment;
- an explicitly selected
--env-file; - the project-root
.envfile.
Lower-priority sources are not opened or validated after a higher-priority value is found.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
direct_path
|
Path | None
|
Optional path supplied directly on the command line. |
required |
explicit_env_file
|
Path | None
|
Optional dotenv file selected on the command line. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
Validated absolute AutoCorrect2 project path. |
Raises:
| Type | Description |
|---|---|
CliConfigurationError
|
If no source supplies a usable path or the selected project is invalid. |
Source code in hotstring\cli\runtime.py
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | |
_project_dir_from_dotenv ¶
Read and validate the AutoCorrect2 path from one dotenv file.
Relative values are interpreted from the dotenv file's directory, making project-local configuration independent of the caller's working directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
env_file
|
Path
|
Existing dotenv file to read. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
Validated absolute AutoCorrect2 project path. |
Raises:
| Type | Description |
|---|---|
CliConfigurationError
|
If the variable is absent, empty, or resolves to an invalid project directory. |
Source code in hotstring\cli\runtime.py
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | |
_validate_autocorrect2_project_dir ¶
Validate the selected AutoCorrect2 project directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Absolute candidate directory. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The validated path. |
Raises:
| Type | Description |
|---|---|
CliConfigurationError
|
If the directory or a required hotstring source is missing. |
Source code in hotstring\cli\runtime.py
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 | |
_require_input_file ¶
Resolve a CLI path and require an existing regular file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path supplied on the command line. |
required |
label
|
str
|
Human-readable input name used in an error message. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
Absolute file path. |
Raises:
| Type | Description |
|---|---|
CliConfigurationError
|
If the path is not an existing regular file. |
Source code in hotstring\cli\runtime.py
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 | |
_optional_cli_path ¶
Resolve an optional CLI path against the current directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path | None
|
Optional path supplied on the command line. |
required |
Returns:
| Type | Description |
|---|---|
Path | None
|
Absolute path, or |
Source code in hotstring\cli\runtime.py
501 502 503 504 505 506 507 508 509 510 511 | |
_absolute_path ¶
Return an expanded absolute path without requiring it to exist.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Path to normalize. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
Expanded absolute path. |
Source code in hotstring\cli\runtime.py
514 515 516 517 518 519 520 521 522 523 524 | |
_unique_nonempty_text ¶
Normalize text values and remove duplicates while preserving order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
Iterable[str]
|
Text values to normalize. |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, ...]
|
Ordered tuple of unique, non-empty stripped values. |
Source code in hotstring\cli\runtime.py
527 528 529 530 531 532 533 534 535 536 537 | |
Command execution¶
commands ¶
Dispatch validated CLI commands to the public pipeline APIs.
The runtime layer resolves all user input before this module is called. Each
handler therefore performs only workflow dispatch and concise terminal
reporting; report generation and optional writes remain owned by
hotstring.pipeline.
execute_command ¶
execute_command(
command: CommandConfig,
*,
logger: Logger | None = None,
output: TextIO | None = None,
) -> int
Execute one validated command and print its summary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
command
|
CommandConfig
|
Runtime command created by
|
required |
logger
|
Logger | None
|
Optional orchestration logger forwarded to typo-generation pipelines. |
None
|
output
|
TextIO | None
|
Optional output stream. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Zero after successful pipeline execution. |
Source code in hotstring\cli\commands.py
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 | |
_print_typo_summary ¶
_print_typo_summary(
result: TypoGenerationResult, *, output: TextIO
) -> None
Print the stable summary fields of a typo-generation result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
TypoGenerationResult
|
Typo-generation result returned by the pipeline. |
required |
output
|
TextIO
|
Destination stream. |
required |
Source code in hotstring\cli\commands.py
108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
_print_autocorrect2_summary ¶
_print_autocorrect2_summary(
result: AutoCorrect2CheckResult, *, output: TextIO
) -> None
Print the stable summary fields of an AutoCorrect2 check result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
AutoCorrect2CheckResult
|
AutoCorrect2 result returned by the pipeline. |
required |
output
|
TextIO
|
Destination stream. |
required |
Source code in hotstring\cli\commands.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | |
_print_write_destination ¶
Print the generated-file destination when writing was enabled.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
write_accepted
|
bool
|
Whether the selected command enabled writing. |
required |
project_dir
|
Path
|
AutoCorrect2 project directory. |
required |
output
|
TextIO
|
Destination stream. |
required |
Source code in hotstring\cli\commands.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | |
_print_report_path ¶
Print the report destination when one was requested.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
report_path
|
Path | None
|
Optional report destination. |
required |
output
|
TextIO
|
Destination stream. |
required |
Source code in hotstring\cli\commands.py
166 167 168 169 170 171 172 173 174 175 176 | |
Reports¶
report ¶
Build composable line-oriented reports for all supported pipelines.
Section builders deliberately omit run-level metadata such as dates or timestamps. This allows the full pipeline to reuse the typo-generation and AutoCorrect2 report bodies without duplicating document metadata.
create_typo_generation_report ¶
create_typo_generation_report(
result: TypoGenerationResult,
) -> list[str]
Create the typo-generation report body.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
TypoGenerationResult
|
Aggregated typo-generation result. |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
Report body as individual text lines. |
Source code in hotstring\report.py
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 | |
create_autocorrect2_report ¶
create_autocorrect2_report(
result: AutoCorrect2CheckResult,
) -> list[str]
Create the AutoCorrect2 conflict-check report body.
Candidate names are displayed with their semantic trigger, while an existing conflict's rendered source line uses its canonical AHK trigger.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
AutoCorrect2CheckResult
|
AutoCorrect2 candidate-check result. |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
Report body as individual text lines. |
Source code in hotstring\report.py
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 | |
create_full_pipeline_report ¶
create_full_pipeline_report(
typo_result: TypoGenerationResult,
autocorrect2_result: AutoCorrect2CheckResult,
) -> list[str]
Create a full report by composing both stage-specific report bodies.
Source code in hotstring\report.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
build_report_document ¶
Wrap a report body with run-level document framing.
Source code in hotstring\report.py
145 146 147 148 149 | |
File I/O¶
file_io ¶
Provide small generic text-file I/O helpers.
read_text ¶
Read a text file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
File to read. |
required |
encoding
|
str
|
Text encoding. |
'utf-8'
|
Returns:
| Type | Description |
|---|---|
str
|
File contents. |
Raises:
| Type | Description |
|---|---|
OSError
|
If the file cannot be read. |
Source code in hotstring\file_io.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
write_text ¶
write_text(
path: Path,
text: str,
*,
append: bool = False,
encoding: str = "utf-8",
create_parents: bool = True,
) -> None
Write or append text to a file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Destination file. |
required |
text
|
str
|
Text to write. |
required |
append
|
bool
|
Append instead of replacing the current contents. |
False
|
encoding
|
str
|
Text encoding. |
'utf-8'
|
create_parents
|
bool
|
Create missing parent directories before writing. |
True
|
Raises:
| Type | Description |
|---|---|
OSError
|
If the destination cannot be written. |
Source code in hotstring\file_io.py
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 | |
Constants¶
Typo generation
Typo generation API¶
hotstring.typo_generation contains typo-generation models, generation logic,
execution strategies, and aggregation helpers.
Typo-generation models¶
models ¶
Define task, configuration, and result models for typo generation.
REPLACE_ONLY_TYPO_DISTRIBUTION
module-attribute
¶
REPLACE_ONLY_TYPO_DISTRIBUTION = TypoWeightDistribution(
replace=1.0
)
Distribution that selects only replacement errors.
TRANSPOSE_ONLY_TYPO_DISTRIBUTION
module-attribute
¶
TRANSPOSE_ONLY_TYPO_DISTRIBUTION = TypoWeightDistribution(
transpose=1.0
)
Distribution that selects only transposition errors.
DELETE_ONLY_TYPO_DISTRIBUTION
module-attribute
¶
DELETE_ONLY_TYPO_DISTRIBUTION = TypoWeightDistribution(
delete=1.0
)
Distribution that selects only deletion errors.
INSERT_ONLY_TYPO_DISTRIBUTION
module-attribute
¶
INSERT_ONLY_TYPO_DISTRIBUTION = TypoWeightDistribution(
insert=1.0
)
Distribution that selects only insertion errors.
DEFAULT_SINGLE_ERROR_TYPO_DISTRIBUTIONS
module-attribute
¶
DEFAULT_SINGLE_ERROR_TYPO_DISTRIBUTIONS: tuple[
TypoWeightDistribution, ...
] = (
REPLACE_ONLY_TYPO_DISTRIBUTION,
TRANSPOSE_ONLY_TYPO_DISTRIBUTION,
DELETE_ONLY_TYPO_DISTRIBUTION,
INSERT_ONLY_TYPO_DISTRIBUTION,
)
Default single-error distributions, one for each supported operation type.
DEFAULT_MIXED_ERROR_TYPO_DISTRIBUTION
module-attribute
¶
DEFAULT_MIXED_ERROR_TYPO_DISTRIBUTION = (
TypoWeightDistribution(
replace=0.28,
transpose=0.28,
delete=0.28,
insert=0.15,
)
)
Mixed distribution mirroring MULTYPO's built-in operation weights.
TypoWeightDistribution
dataclass
¶
Represent the weight mapping of the MULTYPO typo operations.
Values are non-negative weights. MULTYPO normalizes the supplied mapping, so they do not need to sum to one.
Attributes:
| Name | Type | Description |
|---|---|---|
replace |
float
|
Replacement-operation weight. |
transpose |
float
|
Transposition-operation weight. |
delete |
float
|
Deletion-operation weight. |
insert |
float
|
Insertion-operation weight. |
Source code in hotstring\typo_generation\models.py
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 | |
distribution
property
¶
__post_init__ ¶
__post_init__() -> None
Validate typo-distribution weights.
Raises:
| Type | Description |
|---|---|
TypeError
|
If a weight is not a real number or is a boolean. |
ValueError
|
If a weight is negative or all weights are zero. |
Source code in hotstring\typo_generation\models.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | |
TypoGenerationTask
dataclass
¶
Describe one independently executable typo-generation task.
Attributes:
| Name | Type | Description |
|---|---|---|
distribution |
TypoWeightDistribution
|
Typo-operation distribution used by the task. |
typo_rate |
float
|
MULTYPO typo rate passed directly to |
generation_attempts_per_word |
int
|
Number of independent samples requested for each eligible word. |
minimum_word_length |
int
|
Minimum source-word length eligible for this task. |
Source code in hotstring\typo_generation\models.py
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 | |
__post_init__ ¶
__post_init__() -> None
Validate the task definition.
Raises:
| Type | Description |
|---|---|
TypeError
|
If a field has an invalid type. |
ValueError
|
If the typo rate, attempt count, or minimum length is invalid. |
Source code in hotstring\typo_generation\models.py
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 | |
TypoGenerationConfig
dataclass
¶
Configure generator settings shared by every task in one run.
Attributes:
| Name | Type | Description |
|---|---|---|
language |
str
|
MULTYPO language identifier. |
use_excluding_set |
bool
|
Whether MULTYPO's language excluding set is enabled. |
horizontal_vs_vertical |
tuple[float, float]
|
Relative horizontal and vertical keyboard-neighbor weights. |
Source code in hotstring\typo_generation\models.py
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 | |
__post_init__ ¶
__post_init__() -> None
Validate shared typo-generation configuration.
Source code in hotstring\typo_generation\models.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | |
RawTypoSample
dataclass
¶
Represent one successful noisy-word sample.
Attributes:
| Name | Type | Description |
|---|---|---|
noisy_word |
str
|
Generated typo candidate. |
target_word |
str
|
Correct source word the typo should map back to. |
Source code in hotstring\typo_generation\models.py
220 221 222 223 224 225 226 227 228 229 230 231 232 | |
TypoGenerationResult
dataclass
¶
Represent aggregated output of the typo-generation stage.
Attributes:
| Name | Type | Description |
|---|---|---|
config |
TypoGenerationConfig
|
Shared generator configuration used for generation. |
tasks |
tuple[TypoGenerationTask, ...]
|
Ordered generation tasks that were executed. |
source_word_count |
int
|
Number of source words supplied before per-task length filtering. |
generated_sample_count |
int
|
Number of successful raw samples before deduplication. |
candidates |
dict[str, str]
|
Unique noisy-word to target-word mappings. |
clashes |
dict[str, tuple[str, ...]]
|
Noisy words that mapped to more than one target word. |
Source code in hotstring\typo_generation\models.py
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 | |
create_default_typo_generation_tasks ¶
create_default_typo_generation_tasks(
*,
single_error_attempts_per_word: int,
multi_error_attempts_per_word: int,
multi_error_minimum_word_length: int,
) -> tuple[TypoGenerationTask, ...]
Create the project's default single- and two-error task set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
single_error_attempts_per_word
|
int
|
Sampling attempts per eligible word for each forced single-error task. |
required |
multi_error_attempts_per_word
|
int
|
Sampling attempts per eligible word for the mixed two-error task. |
required |
multi_error_minimum_word_length
|
int
|
Minimum word length for the mixed two-error task. |
required |
Returns:
| Type | Description |
|---|---|
tuple[TypoGenerationTask, ...]
|
Ordered default task tuple. |
Source code in hotstring\typo_generation\models.py
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 | |
Typo generation¶
generation ¶
Perform low-level typo sampling for one generation task with MULTYPO.
generate_typos_for_task ¶
generate_typos_for_task(
word_list: Sequence[str],
task: TypoGenerationTask,
config: TypoGenerationConfig,
*,
logger: Logger | None = None,
) -> list[RawTypoSample]
Generate noisy samples for all words eligible for one task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
word_list
|
Sequence[str]
|
Shared source words to consider. |
required |
task
|
TypoGenerationTask
|
Task-specific distribution and sampling settings. |
required |
config
|
TypoGenerationConfig
|
Shared MULTYPO generator configuration. |
required |
logger
|
Logger | None
|
Optional logger for progress and diagnostics. |
None
|
Returns:
| Type | Description |
|---|---|
list[RawTypoSample]
|
Successful raw typo samples. |
Source code in hotstring\typo_generation\generation.py
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 | |
_create_generator ¶
_create_generator(
task: TypoGenerationTask, config: TypoGenerationConfig
) -> MultiTypoGenerator
Create a configured MULTYPO generator for one task.
Source code in hotstring\typo_generation\generation.py
66 67 68 69 70 71 72 73 74 75 76 | |
_normalize_source_word ¶
Validate and normalize one source word to lowercase.
Source code in hotstring\typo_generation\generation.py
79 80 81 82 83 84 85 86 87 88 89 | |
Typo execution¶
execution ¶
Execute typo-generation tasks serially or with a spawned process pool.
execute_typo_generation_tasks ¶
execute_typo_generation_tasks(
word_list: Sequence[str],
tasks: Sequence[TypoGenerationTask],
config: TypoGenerationConfig,
*,
n_workers: int | None = None,
logger: Logger | None = None,
) -> list[RawTypoSample]
Execute all typo-generation tasks and collect their raw samples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
word_list
|
Sequence[str]
|
Shared source words considered by every task. |
required |
tasks
|
Sequence[TypoGenerationTask]
|
Ordered typo-generation tasks to execute. |
required |
config
|
TypoGenerationConfig
|
Shared generator configuration. |
required |
n_workers
|
int | None
|
Requested process-pool size, or |
None
|
logger
|
Logger | None
|
Optional orchestration logger. |
None
|
Returns:
| Type | Description |
|---|---|
list[RawTypoSample]
|
Concatenated raw samples in input task order. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If no tasks are supplied or |
RuntimeError
|
If a parallel generation task fails. |
Source code in hotstring\typo_generation\execution.py
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 | |
_execute_tasks_serial ¶
_execute_tasks_serial(
word_list: list[str],
tasks: tuple[TypoGenerationTask, ...],
config: TypoGenerationConfig,
*,
logger: Logger | None,
) -> list[RawTypoSample]
Execute every task in the current process.
Source code in hotstring\typo_generation\execution.py
82 83 84 85 86 87 88 89 90 91 92 93 | |
_execute_tasks_parallel ¶
_execute_tasks_parallel(
word_list: list[str],
tasks: tuple[TypoGenerationTask, ...],
config: TypoGenerationConfig,
*,
n_workers: int | None,
logger: Logger | None,
) -> list[RawTypoSample]
Execute tasks with a spawned process pool.
Source code in hotstring\typo_generation\execution.py
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 | |
_multi_worker_typo_generation ¶
_multi_worker_typo_generation(
word_list: list[str],
tasks: tuple[TypoGenerationTask, ...],
config: TypoGenerationConfig,
*,
n_workers: int | None,
mp_context: BaseContext,
proxy_queue: Any | None,
root_level: int,
manager_logger_name: str,
) -> list[RawTypoSample]
Submit every generation task to a process pool and collect results.
Source code in hotstring\typo_generation\execution.py
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 | |
_worker_logger_initialization ¶
_worker_logger_initialization(
root_level: int,
proxy_queue: Any | None,
manager_logger_name: str | None,
) -> None
Initialize logging inside one spawned worker process.
Source code in hotstring\typo_generation\execution.py
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | |
_initialize_worker ¶
_initialize_worker(
root_level: int,
proxy_queue: Any | None = None,
manager_logger_name: str | None = None,
) -> None
Initialize process-global state inside a spawned worker process.
Source code in hotstring\typo_generation\execution.py
199 200 201 202 203 204 205 | |
_generate_task_in_worker ¶
_generate_task_in_worker(
word_list: list[str],
task: TypoGenerationTask,
config: TypoGenerationConfig,
) -> list[RawTypoSample]
Execute one task inside a process-pool worker.
Source code in hotstring\typo_generation\execution.py
208 209 210 211 212 213 214 | |
_normalize_tasks ¶
_normalize_tasks(
tasks: Sequence[TypoGenerationTask],
) -> tuple[TypoGenerationTask, ...]
Validate and freeze the task sequence for one execution run.
Source code in hotstring\typo_generation\execution.py
217 218 219 220 221 222 223 224 225 226 227 | |
_validate_worker_count ¶
_validate_worker_count(n_workers: int | None) -> None
Validate an optional process-pool worker count.
Source code in hotstring\typo_generation\execution.py
230 231 232 233 234 235 236 237 | |
Typo aggregation¶
aggregation ¶
Aggregate raw typo samples and remove internally ambiguous candidates.
aggregate_typo_samples ¶
aggregate_typo_samples(
samples: Sequence[RawTypoSample],
*,
config: TypoGenerationConfig,
tasks: Sequence[TypoGenerationTask],
source_word_count: int,
) -> TypoGenerationResult
Deduplicate raw samples and separate valid candidates from clashes.
Source code in hotstring\typo_generation\aggregation.py
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 | |
AutoCorrect2
AutoCorrect2 API¶
hotstring.autocorrect2 contains the AutoCorrect2-specific integration layer.
It builds on the generic hotstring functionality in hotstring.core.
Source discovery, parsing, caching, and loading are grouped under the
source_loading subpackage.
AutoCorrect2 models¶
This module contains the concrete AutoCorrect2CandidateHotstring model.
models ¶
Define AutoCorrect2-specific hotstring and result models.
AutoCorrect2CandidateHotstring
dataclass
¶
Bases: CandidateHotstring
Represent a candidate rendered using AutoCorrect2's f() helper.
The inherited constructor trigger input is semantic trigger text. The
semantic replacement is converted to a safe AutoHotkey string literal and
passed as the single argument to f().
Source code in hotstring\autocorrect2\models.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
compute_content ¶
Compute AutoCorrect2 executable content for a replacement.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
replacement
|
str
|
Intended replacement text. |
required |
Returns:
| Type | Description |
|---|---|
str
|
AutoHotkey expression calling |
Source code in hotstring\autocorrect2\models.py
20 21 22 23 24 25 26 27 28 29 30 | |
AutoCorrect2CheckResult
dataclass
¶
Represent the result of checking candidates against AutoCorrect2.
Attributes:
| Name | Type | Description |
|---|---|---|
accepted |
tuple[AutoCorrect2CandidateHotstring, ...]
|
Candidates with no detected conflict. |
rejected |
tuple[CandidateAssessment, ...]
|
Assessments for candidates with one or more conflicts. |
Source code in hotstring\autocorrect2\models.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | |
Source loading
Source loading API¶
hotstring.autocorrect2.source_loading contains the components responsible for
loading existing AutoCorrect2 hotstrings from source files.
The subpackage separates source parsing, cache management, and the higher-level loading workflow into dedicated modules.
Source parser¶
parser ¶
Parse static AutoCorrect2 hotstring declarations from source text.
The parser treats trigger source spelling as AutoHotkey syntax rather than as
plain text. In particular, an escaped colon (`:) is part of the trigger
and must not be mistaken for the closing :: delimiter. Parsed trigger text
is passed to ExistingHotstring in AHK
source form; the model then derives semantic and canonical source forms.
LOGGER
module-attribute
¶
Module logger used for parser diagnostics.
HOTSTRING_PREFIX_PATTERN
module-attribute
¶
Pattern capturing a static declaration's indentation and option prefix.
extract_hotstrings ¶
extract_hotstrings(
content: str, *, source: str | Path
) -> list[ExistingHotstring]
Extract static hotstring declarations from decoded AutoCorrect2 text.
The function performs no filesystem I/O. Each source line is checked for a
leading :options: prefix. The trigger is then scanned character by
character so escaped characters cannot terminate it accidentally.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content
|
str
|
Decoded AutoCorrect2 source text. |
required |
source
|
str | Path
|
Source identifier stored on each extracted definition. |
required |
Returns:
| Type | Description |
|---|---|
list[ExistingHotstring]
|
Existing hotstrings in declaration order. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the supplied source data has an invalid type. |
ValueError
|
If a recognized declaration contains invalid options or invalid AHK trigger escaping. |
Source code in hotstring\autocorrect2\source_loading\parser.py
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 | |
_find_trigger_delimiter ¶
Locate the first unescaped :: trigger delimiter on one source line.
A backtick escapes the next source character, so a colon immediately after
a backtick cannot begin the delimiter. Two consecutive backticks represent
one literal backtick; scanning the pair as one escaped unit naturally lets
a following :: terminate the trigger.
An unescaped semicolon preceded by horizontal whitespace begins an AutoHotkey comment. If such a comment starts before a closing delimiter, the line does not contain a complete static hotstring declaration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
line
|
str
|
One source line without its newline terminator. |
required |
start
|
int
|
Index immediately after the |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
Index of the first colon in the closing delimiter, or |
int | None
|
valid delimiter occurs before the end of the source line. |
Source code in hotstring\autocorrect2\source_loading\parser.py
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 | |
Source cache¶
cache ¶
Persist AutoCorrect2 source fingerprints and extracted hotstrings.
The cache is an optimization only. SHA-256 of the exact source bytes is the authoritative content identity; filesystem size and modification time are stored as useful metadata but are never trusted as proof that a same-sized source is unchanged.
Cached hotstrings persist only source-derived state: canonical AHK trigger spelling and canonical option text. Semantic trigger text and the case-insensitive semantic comparison key are reconstructed by the domain model on every load so they always reflect the current trigger-normalization implementation.
LOGGER
module-attribute
¶
Module logger used for cache diagnostics.
CACHE_SCHEMA_VERSION
module-attribute
¶
Persistent-cache compatibility version, including parser semantics.
DEFAULT_SOURCE_CACHE_PATH
module-attribute
¶
DEFAULT_SOURCE_CACHE_PATH: Final[Path] = (
PROJECT_ROOT
/ ".cache"
/ "autocorrect2-source-cache.json"
)
Deterministic project-local path used for the persistent source cache.
CachedHotstring
dataclass
¶
Represent the minimal persisted form of one extracted hotstring.
Attributes:
| Name | Type | Description |
|---|---|---|
trigger |
str
|
Canonical AHK source-form trigger text. |
options |
str
|
Canonical hotstring option declaration. |
Source code in hotstring\autocorrect2\source_loading\cache.py
41 42 43 44 45 46 47 48 49 50 51 52 53 | |
SourceCacheEntry
dataclass
¶
Represent cached state for one AutoCorrect2 source file.
Attributes:
| Name | Type | Description |
|---|---|---|
modification_time_ns |
int
|
Source modification time recorded when the entry was refreshed. |
size |
int
|
Source size recorded when the entry was refreshed. |
sha256 |
str
|
SHA-256 digest of the exact source bytes. |
hotstrings |
tuple[CachedHotstring, ...]
|
Extracted hotstrings stored in declaration order. |
Source code in hotstring\autocorrect2\source_loading\cache.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | |
SourceCache
dataclass
¶
Represent the complete persistent AutoCorrect2 source cache.
Attributes:
| Name | Type | Description |
|---|---|---|
project_dir |
str
|
Canonical AutoCorrect2 project directory associated with the cache. This prevents accidental reuse for a different checkout at another path; machine identity is deliberately not part of cache validity. |
files |
dict[str, SourceCacheEntry]
|
Cache entries keyed by source path relative to the AutoCorrect2 project root. |
Source code in hotstring\autocorrect2\source_loading\cache.py
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
canonical_project_dir ¶
Return the canonical project-directory value stored in the cache.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
project_dir
|
Path
|
AutoCorrect2 project directory. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Absolute normalized project-directory string. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the supplied project directory is not a path. |
OSError
|
If path resolution fails. |
Source code in hotstring\autocorrect2\source_loading\cache.py
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
source_cache_key ¶
Return the stable JSON key for a configured source path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Path
|
Source path relative to the AutoCorrect2 project root. |
required |
Returns:
| Type | Description |
|---|---|
str
|
POSIX-style relative path suitable for use as a JSON object key. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the supplied source is not a path. |
Source code in hotstring\autocorrect2\source_loading\cache.py
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | |
compute_content_hash ¶
Compute the SHA-256 digest used as authoritative content identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content
|
bytes
|
Exact source-file bytes. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Lowercase hexadecimal SHA-256 digest. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the supplied content is not bytes. |
Source code in hotstring\autocorrect2\source_loading\cache.py
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | |
create_source_cache_entry ¶
create_source_cache_entry(
hotstrings: Sequence[ExistingHotstring],
*,
modification_time_ns: int,
size: int,
sha256: str,
) -> SourceCacheEntry
Create a cache entry from parsed hotstrings and source state.
Cached triggers use each model's canonical ahk_trigger field, not its
semantic trigger. Restoring the entry therefore feeds exactly the input
representation expected by ExistingHotstring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hotstrings
|
Sequence[ExistingHotstring]
|
Parsed hotstrings in declaration order. |
required |
modification_time_ns
|
int
|
Current source modification time. |
required |
size
|
int
|
Current source size. |
required |
sha256
|
str
|
SHA-256 digest of the exact source bytes. |
required |
Returns:
| Type | Description |
|---|---|
SourceCacheEntry
|
Cache entry ready for persistence. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If source metadata or a hotstring has an invalid type. |
ValueError
|
If source metadata or the digest is invalid. |
Source code in hotstring\autocorrect2\source_loading\cache.py
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 | |
restore_hotstrings ¶
restore_hotstrings(
entry: SourceCacheEntry, *, source: Path
) -> list[ExistingHotstring]
Reconstruct domain hotstrings from one persisted cache entry.
The cached trigger is intentionally fed back to ExistingHotstring as
AHK source-form constructor input. Its semantic trigger, canonical source
representation, parsed options, and case-insensitive semantic key are therefore
rebuilt using the current code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entry
|
SourceCacheEntry
|
Cached source entry to reconstruct. |
required |
source
|
Path
|
Source identifier assigned to each reconstructed hotstring. |
required |
Returns:
| Type | Description |
|---|---|
list[ExistingHotstring]
|
Existing hotstrings in their cached declaration order. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the cache entry or source identifier has an invalid type. |
ValueError
|
If cached hotstring data is invalid under the current model. |
Source code in hotstring\autocorrect2\source_loading\cache.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 | |
load_source_cache ¶
load_source_cache(
cache_path: Path, *, project_dir: Path
) -> SourceCache
Load the persistent source cache or return an empty compatible cache.
Missing, unreadable, malformed, incompatible, or project-mismatched cache files are treated as disposable optimization state. In those cases an empty cache associated with the requested AutoCorrect2 project is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache_path
|
Path
|
JSON cache file to load. |
required |
project_dir
|
Path
|
AutoCorrect2 project directory expected by the caller. |
required |
Returns:
| Type | Description |
|---|---|
SourceCache
|
Loaded compatible cache, or a new empty cache when persisted state |
SourceCache
|
cannot be reused. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a path argument has an invalid type. |
OSError
|
If canonicalizing the project directory fails. |
Source code in hotstring\autocorrect2\source_loading\cache.py
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 | |
save_source_cache ¶
save_source_cache(
cache: SourceCache, cache_path: Path
) -> None
Persist the source cache atomically as UTF-8 JSON.
Each cached hotstring contains exactly trigger and options. The trigger
value is the canonical AHK source representation. Source paths are stored
once as keys in the surrounding files object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache
|
SourceCache
|
Source cache to persist. |
required |
cache_path
|
Path
|
Destination JSON file. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If an argument has an invalid type. |
OSError
|
If the cache directory or cache file cannot be written or replaced. |
Source code in hotstring\autocorrect2\source_loading\cache.py
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 | |
_parse_source_cache_entry ¶
_parse_source_cache_entry(
raw_entry: object,
) -> SourceCacheEntry | None
Parse one untrusted JSON cache entry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw_entry
|
object
|
Decoded JSON value representing a source entry. |
required |
Returns:
| Type | Description |
|---|---|
SourceCacheEntry | None
|
Validated cache entry, or |
Source code in hotstring\autocorrect2\source_loading\cache.py
419 420 421 422 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 449 450 451 452 453 454 455 | |
_parse_cached_hotstring ¶
_parse_cached_hotstring(
raw_hotstring: object,
) -> CachedHotstring | None
Parse one minimal hotstring record from decoded JSON.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw_hotstring
|
object
|
Decoded JSON value representing one cached hotstring. |
required |
Returns:
| Type | Description |
|---|---|
CachedHotstring | None
|
Parsed cached hotstring, or |
Source code in hotstring\autocorrect2\source_loading\cache.py
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 | |
_serialize_source_cache ¶
_serialize_source_cache(
cache: SourceCache,
) -> dict[str, object]
Convert the in-memory source cache to JSON-compatible values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache
|
SourceCache
|
Source cache to serialize. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, object]
|
JSON-compatible cache document. |
Source code in hotstring\autocorrect2\source_loading\cache.py
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | |
_validate_metadata ¶
Validate metadata used to construct a source-cache entry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modification_time_ns
|
int
|
Source modification time. |
required |
size
|
int
|
Source size. |
required |
sha256
|
str
|
Source SHA-256 digest. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a metadata value has an invalid type. |
ValueError
|
If a metadata value is outside its valid domain. |
Source code in hotstring\autocorrect2\source_loading\cache.py
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 | |
_metadata_is_valid ¶
Return whether decoded source metadata has the expected shape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modification_time_ns
|
object
|
Decoded modification-time value. |
required |
size
|
object
|
Decoded file-size value. |
required |
sha256
|
object
|
Decoded digest value. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether all metadata values are valid. |
Source code in hotstring\autocorrect2\source_loading\cache.py
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 | |
_sha256_is_valid ¶
Return whether a string is a lowercase-or-uppercase SHA-256 hex digest.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
Candidate digest string. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether the value contains exactly 64 hexadecimal characters. |
Source code in hotstring\autocorrect2\source_loading\cache.py
577 578 579 580 581 582 583 584 585 586 587 | |
Source loader¶
loader ¶
Load configured AutoCorrect2 hotstring sources through a persistent cache.
LOGGER
module-attribute
¶
Module logger used for source-loading diagnostics.
load_existing_hotstrings ¶
load_existing_hotstrings(
project_dir: Path,
*,
required_source_paths: Sequence[
Path
] = REQUIRED_HOTSTRING_SOURCE_RELATIVE_PATHS,
optional_source_paths: Sequence[
Path
] = OPTIONAL_HOTSTRING_SOURCE_RELATIVE_PATHS,
cache_path: Path | None = DEFAULT_SOURCE_CACHE_PATH,
) -> list[ExistingHotstring]
Load all configured active static AutoCorrect2 hotstrings.
Required sources must exist. Optional sources, including the project-owned generated include file, are scanned only when present. When caching is enabled, SHA-256 is the authoritative content identity. File size and modification time are retained as useful metadata and positive change signals, but matching metadata never suppresses hash verification.
Cache failures are treated as optimization failures rather than source-load failures. The function falls back to parsing authoritative AutoCorrect2 source files when persisted cache data cannot be used.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
project_dir
|
Path
|
AutoCorrect2 project directory. |
required |
required_source_paths
|
Sequence[Path]
|
Relative source paths that must exist. |
REQUIRED_HOTSTRING_SOURCE_RELATIVE_PATHS
|
optional_source_paths
|
Sequence[Path]
|
Relative source paths scanned when present. |
OPTIONAL_HOTSTRING_SOURCE_RELATIVE_PATHS
|
cache_path
|
Path | None
|
Persistent JSON cache path, or |
DEFAULT_SOURCE_CACHE_PATH
|
Returns:
| Type | Description |
|---|---|
list[ExistingHotstring]
|
Existing hotstrings in source-file and declaration order. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a path argument has an invalid type. |
FileNotFoundError
|
If a required source does not exist. |
UnicodeDecodeError
|
If a changed source is not valid UTF-8 text. |
ValueError
|
If a parsed hotstring declaration is invalid. |
OSError
|
If an authoritative source cannot be inspected or read. |
Source code in hotstring\autocorrect2\source_loading\loader.py
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 | |
_load_source_hotstrings ¶
_load_source_hotstrings(
file_path: Path,
*,
source: Path,
cache: SourceCache | None,
) -> tuple[list[ExistingHotstring], bool]
Load one source using cache reuse when its content hash matches.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
Path
|
Authoritative source file to inspect. |
required |
source
|
Path
|
Relative source identifier stored on extracted hotstrings. |
required |
cache
|
SourceCache | None
|
Loaded persistent cache, or |
required |
Returns:
| Type | Description |
|---|---|
list[ExistingHotstring]
|
Pair containing loaded hotstrings and whether the in-memory cache was |
bool
|
modified. |
Raises:
| Type | Description |
|---|---|
UnicodeDecodeError
|
If source bytes requiring parsing are not valid UTF-8 text. |
ValueError
|
If a parsed hotstring declaration is invalid. |
OSError
|
If the source cannot be inspected or read. |
Source code in hotstring\autocorrect2\source_loading\loader.py
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 | |
_parse_and_refresh_source ¶
_parse_and_refresh_source(
file_path: Path,
*,
source: Path,
source_key: str,
source_stat: stat_result,
cache: SourceCache,
content: bytes | None = None,
content_hash: str | None = None,
) -> tuple[list[ExistingHotstring], bool]
Parse one authoritative source and replace its cache entry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
Path
|
Source file used when bytes have not already been read. |
required |
source
|
Path
|
Relative source identifier stored on extracted hotstrings. |
required |
source_key
|
str
|
Stable cache key for the source. |
required |
source_stat
|
stat_result
|
Filesystem metadata captured before parsing. |
required |
cache
|
SourceCache
|
In-memory source cache to update. |
required |
content
|
bytes | None
|
Already-read source bytes when available. |
None
|
content_hash
|
str | None
|
Already-computed source digest when available. |
None
|
Returns:
| Type | Description |
|---|---|
list[ExistingHotstring]
|
Pair containing parsed hotstrings and |
bool
|
was refreshed. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the supplied filesystem metadata is invalid. |
UnicodeDecodeError
|
If source bytes are not valid UTF-8 text. |
ValueError
|
If a parsed hotstring declaration is invalid. |
OSError
|
If source bytes must be read and the read fails. |
Source code in hotstring\autocorrect2\source_loading\loader.py
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 | |
_parse_source_content ¶
_parse_source_content(
content: bytes, *, source: Path
) -> list[ExistingHotstring]
Decode source bytes and delegate static declaration parsing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content
|
bytes
|
Exact source-file bytes. |
required |
source
|
Path
|
Relative source identifier stored on extracted hotstrings. |
required |
Returns:
| Type | Description |
|---|---|
list[ExistingHotstring]
|
Parsed existing hotstrings in declaration order. |
Raises:
| Type | Description |
|---|---|
UnicodeDecodeError
|
If the source is not valid UTF-8 text. |
ValueError
|
If an extracted hotstring declaration is invalid. |
Source code in hotstring\autocorrect2\source_loading\loader.py
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | |
AutoCorrect2 writer¶
writer ¶
Append approved AutoCorrect2 candidates to the generated include file.
GENERATED_FILE_HEADER
module-attribute
¶
GENERATED_FILE_HEADER = "; AUTO-GENERATED BY autocorrect2-hotstring-generation\n; Add this file to AutoCorrect2 with a one-time #Include.\n; Do not edit generated entries manually.\n"
Header written when the generated include file is first created.
append_candidates ¶
append_candidates(
candidates: Sequence[AutoCorrect2CandidateHotstring],
*,
project_dir: Path,
relative_path: Path = GENERATED_HOTSTRINGS_RELATIVE_PATH,
) -> Path
Append accepted candidates to the project-owned AutoCorrect2 include.
Each candidate must explicitly use B0 and X, which are required by the
AutoCorrect2 f()-based generated form. Trigger rendering is delegated to
the hotstring model, which emits its canonical ahk_trigger source form.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidates
|
Sequence[AutoCorrect2CandidateHotstring]
|
Accepted AutoCorrect2 candidates to append. |
required |
project_dir
|
Path
|
AutoCorrect2 project directory. |
required |
relative_path
|
Path
|
Generated include path relative to |
GENERATED_HOTSTRINGS_RELATIVE_PATH
|
Returns:
| Type | Description |
|---|---|
Path
|
Path of the generated include file. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a candidate is not explicitly configured with |
OSError
|
If the generated file cannot be read or written. |
Source code in hotstring\autocorrect2\writer.py
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 | |
_validate_writable_candidate ¶
_validate_writable_candidate(
candidate: AutoCorrect2CandidateHotstring,
) -> None
Validate the AutoCorrect2-specific B0X writing contract.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidate
|
AutoCorrect2CandidateHotstring
|
Candidate that may be appended to the generated include. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If automatic backspacing is not explicitly disabled or execution is not explicitly enabled. |
Source code in hotstring\autocorrect2\writer.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | |
AutoCorrect2 integration¶
integration ¶
Manage custom hotstring includes in AutoCorrect2's autocorrection context.
AutoCorrect2IntegrationError ¶
Bases: RuntimeError
Raised when AutoCorrect2's include structure is inconsistent or ambiguous.
Source code in hotstring\autocorrect2\integration.py
37 38 | |
_IncludeState
dataclass
¶
Store validated source state for one custom include.
Attributes:
| Name | Type | Description |
|---|---|---|
source_path |
Path
|
AutoCorrect2 main script being inspected. |
lines |
list[str]
|
Main-script source lines including newline terminators. |
hotif_start |
int
|
Index of the target |
hotif_end |
int
|
Index of the next |
custom_include_index |
int | None
|
Existing custom include line, or |
Source code in hotstring\autocorrect2\integration.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
has_custom_hotstring_include ¶
Return whether a custom file is included in AutoCorrect2's correction context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
custom_file_path
|
str | Path
|
Custom file to look for. A relative path is interpreted relative to the AutoCorrect2 project directory. |
required |
project_dir
|
str | Path
|
AutoCorrect2 project directory. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
|
bool
|
when the include is completely absent. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If AutoCorrect2's main source file does not exist. |
ValueError
|
If the custom path refers to a protected integration source. |
AutoCorrect2IntegrationError
|
If the expected include/context structure is ambiguous. |
OSError
|
If AutoCorrect2's main source file cannot be read. |
Source code in hotstring\autocorrect2\integration.py
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 | |
add_custom_hotstring_include ¶
Add a custom file to AutoCorrect2's autocorrection context if absent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
custom_file_path
|
str | Path
|
Custom file to include. A relative path is interpreted relative to the AutoCorrect2 project directory. |
required |
project_dir
|
str | Path
|
AutoCorrect2 project directory. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
already correctly present. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If AutoCorrect2's main source file does not exist. |
ValueError
|
If the path is invalid or cannot be represented safely. |
AutoCorrect2IntegrationError
|
If the expected include/context structure is ambiguous. |
OSError
|
If the source file cannot be read or written. |
Source code in hotstring\autocorrect2\integration.py
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 | |
remove_custom_hotstring_include ¶
Remove a custom file from AutoCorrect2's autocorrection context if present.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
custom_file_path
|
str | Path
|
Custom file whose include should be removed. |
required |
project_dir
|
str | Path
|
AutoCorrect2 project directory. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
already absent. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If AutoCorrect2's main source file does not exist. |
ValueError
|
If the custom path refers to a protected integration source. |
AutoCorrect2IntegrationError
|
If the expected include/context structure is ambiguous. |
OSError
|
If the source file cannot be read or written. |
Source code in hotstring\autocorrect2\integration.py
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 | |
_inspect_include_state ¶
_inspect_include_state(
custom_file_path: Path, project_dir: Path
) -> _IncludeState
Read and validate AutoCorrect2's include state for one custom file.
Source code in hotstring\autocorrect2\integration.py
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 | |
_find_autocorrection_hotif ¶
Return the start and end indices of the autocorrection #HotIf block.
Source code in hotstring\autocorrect2\integration.py
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | |
_find_include_indices ¶
Return line indices whose static include resolves to target_path.
Source code in hotstring\autocorrect2\integration.py
288 289 290 291 292 293 294 295 | |
_parse_include_path ¶
Resolve a static AutoHotkey include directive, if the line contains one.
Source code in hotstring\autocorrect2\integration.py
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | |
_resolve_custom_file_path ¶
Resolve a caller-supplied custom path against the AutoCorrect2 project.
Source code in hotstring\autocorrect2\integration.py
320 321 322 323 324 325 326 327 328 | |
_render_include_path ¶
Render a static include path relative to AutoCorrect2's main source file.
Source code in hotstring\autocorrect2\integration.py
331 332 333 334 335 336 337 338 339 340 341 342 | |
_hotif_indentation ¶
_hotif_indentation(state: _IncludeState) -> str
Return the indentation convention used inside the target #HotIf block.
Source code in hotstring\autocorrect2\integration.py
345 346 347 348 349 350 351 | |
_detect_newline ¶
Return the source file's existing newline convention.
Source code in hotstring\autocorrect2\integration.py
354 355 356 357 358 359 360 361 362 363 | |
_same_path ¶
Compare paths using Windows-style case-insensitive semantics.
Source code in hotstring\autocorrect2\integration.py
366 367 368 369 370 | |
AutoCorrect2 constants¶
constants ¶
Define filesystem constants for the AutoCorrect2 integration.
AUTOCORRECT2_MAIN_RELATIVE_PATH
module-attribute
¶
Relative path to AutoCorrect2's main script.
AUTOCORRECT_HOTSTRINGS_RELATIVE_PATH
module-attribute
¶
Relative path to AutoCorrect2's main autocorrection hotstring source.
BOILERPLATE_HOTSTRINGS_RELATIVE_PATH
module-attribute
¶
Relative path to AutoCorrect2's personal boilerplate hotstring source.
DATE_TOOL_HOTSTRINGS_RELATIVE_PATH
module-attribute
¶
Relative path to AutoCorrect2's date-tool hotstring source.
REQUIRED_HOTSTRING_SOURCE_RELATIVE_PATHS
module-attribute
¶
REQUIRED_HOTSTRING_SOURCE_RELATIVE_PATHS: Final[
tuple[Path, ...]
] = (
AUTOCORRECT_HOTSTRINGS_RELATIVE_PATH,
BOILERPLATE_HOTSTRINGS_RELATIVE_PATH,
DATE_TOOL_HOTSTRINGS_RELATIVE_PATH,
)
Existing AutoCorrect2 files expected to contain static hotstrings.
GENERATED_HOTSTRINGS_RELATIVE_PATH
module-attribute
¶
Project-owned generated include file appended by the writer.
OPTIONAL_HOTSTRING_SOURCE_RELATIVE_PATHS
module-attribute
¶
OPTIONAL_HOTSTRING_SOURCE_RELATIVE_PATHS: Final[
tuple[Path, ...]
] = (GENERATED_HOTSTRINGS_RELATIVE_PATH,)
Additional active sources checked when they already exist.