Text & everyday tools · Text Toolkit
Why a find-and-replace tool must survive a half-typed regex
· Why it matters
find-and-replace regular-expressions text-editing
Typing a pattern is incremental, so a lone opening bracket is a normal state; this post argues that guarding compilation, leaving text untouched and offering undo are correctness features, not polish.
The tool that cleared the box on an unbalanced bracket — how one keystroke can destroy an hour of cleanup
A find-and-replace box often contains work that took much longer to assemble than the search pattern beside it. If an incomplete expression can throw through the interface, clear the editor or leave its state uncertain, the tool has made pattern entry more dangerous than the cleanup task it was meant to simplify.
The repository does not document a specific incident in which ToolAcre erased an hour of work, so that story cannot be presented as fact. The defensible requirement is stronger anyway: user text must remain unchanged whenever pattern compilation fails, regardless of how much text is present or how long it took to prepare.
The destructive failure a find-and-replace tool must prevent
Regular expressions are not usually entered in one perfect keystroke. A person types an opening parenthesis before its closing parenthesis, or starts a character class with an opening bracket before adding its members. During those moments, the field contains a syntactically incomplete pattern even though the editing process is proceeding normally.
Treating that temporary state as exceptional user behaviour produces a brittle editor. The useful response is immediate, local feedback: show that the current pattern cannot compile, preserve every other field, and let the next keystroke repair it. An invalid regular expression error should describe the present draft, not terminate the workflow.
Incomplete patterns are normal while a regular expression is being written
ToolAcre routes every user-supplied search through `compilePattern`. Literal searches first escape regular-expression metacharacters, while Regex mode uses the supplied source directly. Compilation happens inside a `try` block, and failure returns a null pattern plus an error string instead of allowing the JavaScript exception to escape into the interface.
That result controls the replacement path. When compilation reports an error, `findReplace` returns the original text, zero replacements and the error. It does not attempt a partial search or rewrite. The guard therefore protects both interface stability and data integrity: no valid pattern means no mutation of the editor contents.
Reporting what happened — why a replacement count after each run is the fastest sanity check
A successful replacement can still be logically wrong. A broad expression may match more dates than intended, while a case option or whole-word boundary may reduce the set to zero. ToolAcre counts matches before calling the standard string replacement and returns that number with the rewritten text, making the scope visible after each run.
The count is a fast sanity check rather than proof that every match was desirable. If twelve records were expected and the result says 1 or 1,200, stop and inspect the pattern before copying the output. A precise number turns vague suspicion into a concrete reason to undo and revise the search.
Undo as a safety net — every transform reversible, with a documented limit of fifty operations
Compilation safety prevents invalid patterns from changing text, but valid patterns can still express the wrong intention. Undo covers that second category. The Text Toolkit records transformations so a completed replacement can be reversed after the result count or output reveals that the search was too wide, too narrow or incorrectly grouped.
The documented history limit is fifty operations, so undo is a working buffer rather than permanent version control. Use it to experiment in small steps, but do not treat it as archival storage. For important material, retain the original separately and copy the finished output only after reviewing both the text and replacement count.
Worked example — building a date-reformatting pattern character by character and watching the error appear and disappear without losing text
Consider changing dates from `2024-01-02` to `02/01/2024`. Enable Regex and begin with an opening parenthesis. At that instant the browser engine reports an invalid expression, ToolAcre surfaces the message, and the text remains intact. Add `\d{4}` and the closing parenthesis, and that first captured year becomes valid.
Continue until the search is `(\d{4})-(\d{2})-(\d{2})`, then use `$3/$2/$1` as the replacement. The three captures reorder year, month and day without retyping each line. Run Replace all, compare the reported count with the expected rows, and undo immediately if unrelated numeric text also matched.
What this does not cover — regex performance problems such as catastrophic backtracking on huge inputs
The compilation guard addresses syntax errors, not the running time of valid expressions. A pattern can compile successfully yet backtrack heavily on particular input. Because replacement runs on the main thread, a pathological expression applied to a large document can still make the browser tab unresponsive even though no exception was thrown.
The tool also performs Replace all rather than stepping through matches individually, and it does not preview highlighted matches before mutation. Those limits make narrow test data and the replacement count important. Validate an unfamiliar expression on a small representative sample before applying it to the only copy of a large document.
The takeaway — the Text Toolkit treats invalid patterns as information, not failure, so you can experiment safely
An incomplete pattern is information about an editing state, not evidence that the user has failed. ToolAcre keeps that distinction in its return values: compilation can report an error without throwing, replacement can report zero changes without touching the source, and a successful operation can report exactly how many matches it rewrote.
That design supports experimentation without pretending regular expressions are harmless. Preserve input on compilation failure, inspect counts after success, and use undo when a valid pattern was conceptually wrong. Together those behaviours make find and replace predictable enough for occasional regex users who need feedback more than punishment for a half-typed expression.