|
| 1 | +# Spec: Smart Input — week-text boundary and 2-letter English weekday aliases (#230) |
| 2 | + |
| 3 | +## Goal |
| 4 | + |
| 5 | +Fix two parsing defects in `MatchInput`: (1) the week-token regex consumes the first character of the following text, and (2) 2-letter English weekday abbreviations (`mo`, `tu`, `we`, `th`, `fr`) are not recognized. |
| 6 | + |
| 7 | +## Why now |
| 8 | + |
| 9 | +Both defects break user-visible output in the current 1.1.0 milestone. The week-text bug silently corrupts task and memo content; the missing aliases were discovered in the same report. |
| 10 | + |
| 11 | +## In scope |
| 12 | + |
| 13 | +- Fix `weekPattern` in `MatchInput.getExpression()` so it does not consume any character beyond the week token itself. |
| 14 | +- Add `mo`, `tu`, `we`, `th`, `fr` to `getWeekdayPattern()` as recognized English aliases (longest-first ordering; after the 3-letter set). |
| 15 | +- Add regression tests in `src/test/suite/input.test.ts` and/or `week-input.test.ts` covering the exact inputs from the issue report. |
| 16 | + |
| 17 | +## Out of scope |
| 18 | + |
| 19 | +- German 2-letter abbreviation conflicts (`di`, `do`, `fr`, `sa`, `so`) — tracked in #177 (parser rewrite). |
| 20 | +- Locale-based weekday filtering — also #177. |
| 21 | +- Any change to `getDayOfWeekForString` in `dates.ts` (already maps `mo/tu/we/th/fr` correctly). |
| 22 | + |
| 23 | +## Acceptance criteria |
| 24 | + |
| 25 | +1. `parseInput("task week Finalize Shoppinglist")` → `flags="task"`, `text="Finalize Shoppinglist"`, `week` = current week number. |
| 26 | +2. `parseInput("task do the shopping")` — behaviour unchanged (deferred; `do` still fires as German Thursday, text = "the shopping"). No regression. |
| 27 | +3. `parseInput("mo")` → `weekday` group matched, `offset` resolves to next/prev Monday relative to today (same as `parseInput("mon")`). |
| 28 | +4. Same for `tu`, `we`, `th`, `fr`. |
| 29 | +5. `parseInput("w15")` → `week=15` (no regression from week-pattern change). |
| 30 | +6. `parseInput("week")` alone (no following text) → `hasWeek()` true, no crash. |
| 31 | +7. Full test suite green. |
| 32 | + |
| 33 | +## Root causes |
| 34 | + |
| 35 | +### Bug 1 — week pattern consumes first character of text |
| 36 | + |
| 37 | +Current: |
| 38 | +``` |
| 39 | +const weekPattern = '(?<week>w(?:eek)?(?:\\s\\D|$))'; |
| 40 | +``` |
| 41 | +`(?:\\s\\D|$)` alternates between (whitespace + one non-digit character consumed) and end-of-string. For input `"week Finalize…"` the `\\D` captures `"F"`, leaving `"inalize…"` in the text group. |
| 42 | + |
| 43 | +Fix: replace the consuming `\\D` with a lookahead so the non-digit character stays available for the trailing `\\s?` and `textPattern`: |
| 44 | +``` |
| 45 | +const weekPattern = '(?<week>w(?:eek)?)(?=\\s(?!\\d)|$)'; |
| 46 | +``` |
| 47 | +`(?=\\s(?!\\d)|$)` asserts (without consuming) that the week token is followed by whitespace-then-non-digit or end-of-string, which prevents `"week15"` from matching this branch (it falls through to `weekNumPattern`). |
| 48 | + |
| 49 | +### Bug 2 — 2-letter English aliases absent from weekday pattern |
| 50 | + |
| 51 | +`getDayOfWeekForString` (dates.ts:86-90) already maps `mo → 1`, `tu → 2`, `we → 3`, `th → 4`, `fr → 5`. `getWeekdayPattern()` only lists 3-letter English forms (`mon`, `tue`, `wed`, `thu`, `fri`), so the 2-letter variants never reach `resolveWeekday`. |
| 52 | + |
| 53 | +Fix: append `'mo', 'tu', 'we', 'th', 'fr'` after the 3-letter English group in the `alternatives` array (longest-first ordering preserved). |
| 54 | + |
| 55 | +## Entities / interfaces |
| 56 | + |
| 57 | +- `MatchInput.getExpression()` — `weekPattern` constant (one line change). |
| 58 | +- `MatchInput.getWeekdayPattern()` — `alternatives` array (one section addition). |
| 59 | +- No interface or model changes. |
| 60 | + |
| 61 | +## Constraints |
| 62 | + |
| 63 | +- Tests run inside a VS Code Extension Host; pure-regex / pure-parse logic can also be exercised via `node -e` without VS Code. |
| 64 | +- `this.expr` is built once and cached; changing the pattern constants only affects new `MatchInput` instances (no state migration needed). |
| 65 | +- Must not regress existing tests, including the `lone 'do'` and `'Donnerstag'` tests in `input.test.ts`. |
| 66 | + |
| 67 | +## Open questions |
| 68 | + |
| 69 | +None after clarification. |
| 70 | + |
| 71 | +## Related issues |
| 72 | + |
| 73 | +- Blocks: none. |
| 74 | +- Related: #177 (parser rewrite — will supersede the German 2-letter abbreviation side of this report). |
0 commit comments