feat: Add support for text snippets - #150
Conversation
There was a problem hiding this comment.
@Mr-Sunglasses Solid first cut at snippet expansion, and the longest-trigger-first sort plus the escapedTemplate guard show you anticipated the obvious regex traps.
A few things to tighten before merge: the \b word-boundary pattern silently drops triggers ending in punctuation, the expansion logic sits in AppState rather than a service, and the bundled ServiceTests.swift CI-skip/timeout changes look unrelated and probably belong in their own PR. Details inline.
@jatinkrmalik I've done the suggested changes please review..... |
jatinkrmalik
left a comment
There was a problem hiding this comment.
Thanks for the follow-up fixes. I left a few focused inline comments, mostly around persistence behavior and small polish items.
|
@Mr-Sunglasses heads up: since I merged your PR #148, you may need to rebase this branch onto the latest |
Hey @jatinkrmalik I've address all the suggestions and rebase the PR. 😊 |
|
@Mr-Sunglasses thanks for the Aug 4 follow-up. The willSet persistence bug, I still can't review this as a mergeable PR. GitHub is CONFLICTING ( When you resolve conflicts:
On the expander, two leftovers after the
Smaller: duplicate triggers can be saved with no warning; |
- Auto-save sink now encodes the emitted array: @published fires on willSet, so re-reading self.snippets saved the previous state and left the latest change (e.g. deleting all snippets) unpersisted. Added testAutoSavePersistsDeletion to pin this down. - Store the expansion as entered (trim only for validation and the trigger) so intentional leading/trailing whitespace survives. - Make SnippetExpander final. - SnippetTests now clears the vocamac.snippets defaults key in setUp/tearDown so state cannot leak between tests; the round-trip test no longer clears snippets mid-test (that clear relied on the old one-save-behind behavior to pass).
Upstream replaced the settings TabView with a sidebar/detail shell, so the snippets page needed reworking rather than a straight port. - Expand snippets *after* DictationOutputFormatter, not before. Snippet expansions are literal text the user authored, so auto-capitalization must not rewrite them — expanding first turned an email snippet at the start of a sentence into "Me@example.com". Trigger matching is case-insensitive, so capitalizing the trigger first still matches. Pinned by testSnippetExpansionIsNotRewrittenByAutoCapitalize. - Rebuild SnippetsSettingsTab as a grouped Form to match every other detail page; the old List(.inset) plus bottom action bar was styled for the tab layout and looked foreign in the sidebar. - Give each row an explicit destructive remove button. Deletion previously relied on .onDelete with no selection binding, which has no affordance on macOS. Mirrors the existing Auto-Pause app list. - Drop the unused newTrigger/newExpansion state.
b84e0cc to
f27adc2
Compare
✅ Deploy Preview for voca-mac canceled.
|
|
@jatinkrmalik I have tested this and we are good to go. 🔥 |
fix: #149
Now user can add snippets and then when they dictate the phase, it is replaced by the snippet.
Demo
output.mp4
AI and LLM's Assistance
I've used Gemini CLI to assist with this issue, but I personally reviewed all the generated changes before submitting the PR. I also added tests to cover the code introduced in this contribution.
Model used: Auto -- Gemini CLI selects the best model for each task automatically, choosing between gemini-3.1-pro and gemini-3-flash.