diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md index 01be5d0..e9f99a4 100644 --- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md +++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md @@ -204,6 +204,7 @@ taking that too literally. | 132 | Every action must have a shortcut, and that no longer serves | policy | S | done, 2026-08-20. `everyActionHasAShortcut` is deleted and nothing replaces it: `everyActionIsReachableFromAMenu()` is the required rule and a shortcut is now a chosen subset. Nothing else needed changing, since `showShortcutReference()` already printed `(unbound)` for an empty sequence. Verified by unbinding `tag_rules` and running the suite green, which would have failed before | | 133 | The composer shows no markdown syntax highlighting | v2 | S | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** A `QSyntaxHighlighter` over the composer's editor, so `**bold**` reads as bold while the buffer stays plain markdown. Standard Qt, no dependency. Deliberately after 123's formatting toolbar: agreeing with the grammar about nesting and about code spans suppressing what is inside them is the expensive part, and the toolbar is what makes the feature usable | | 134 | The busy indicator is built inline and is about to be built twice | maintenance | S | done, 2026-08-20, af902e0. `BusyIndicator` (`src/busyindicator.h`) carries both modes: `MainWindow` uses the indeterminate one, and item 123's send popup takes the determinate half for its undo countdown, switching the same widget over when the command starts. Only the BAR was extracted, not the status label this row paired with it. `m_statusLabel` has 34 uses across `MainWindow` for transient messages, selection counts and sync phases, so it belongs to the window rather than to the indicator, and the send popup owns its own phase text | +| 135 | The formatting toolbar's buttons stack rather than toggle | v2 | S | open, 2026-08-21, asked for by the user during item 123 task 8 and reverted the same session. **A spec change, not a defect**: it conflicts with spec:236 ("deliberately no live toggle") and spec:187-190. Both sites need amending FIRST, and the amendment must resolve what replaces bold-then-italic, which is the gesture spec:187's preserved selection exists to serve and which a toggle makes unreachable. That question is the work; the state machine is understood and written up in the section | Sizes are rough: XS under an hour, S a sitting, M a session. @@ -1098,6 +1099,78 @@ Then Delete a message. Verified by hand on 2026-08-20; this is how it was found. **Size: S.** +## 135. The formatting toolbar's buttons stack rather than toggle + +**Observed (user, 2026-08-21):** pressing Bold a second time on already-bold +text adds another pair of asterisks rather than removing the first, so +`**this**` becomes `****this****`. Quote nests the same way: a second press on +`> one` gives `> > one`. The user asked for both to toggle. + +**A toggle was built and reverted the same session**, and the reason matters +more than the code: it was not unwanted, it **conflicts with the spec**, which +was not checked before the work started. + +- `2026-08-20-compose-and-send-design.md:236` states there is "deliberately no + live toggle that inserts and removes the quote while editing". +- `:187-190` is the complete statement of the wrap behaviour and describes only + wrapping, with no toggle anywhere. + +**Cause.** This is a **spec change, not a defect**, and both sites need +amending before any code is written again. + +Underneath sits a real design question the spec answers one way and a toggle +answers the other, which is why the two cannot simply coexist. `:187` preserves +the selection after a wrap **so that a second press applies a SECOND token** to +the same words: bold, then italic, without touching the mouse. A toggle makes +that gesture unreachable, because the second press now removes the first token +instead. **What replaces bold-then-italic is unanswered**, and answering it is +the substance of this item, not the state machine below. Possible directions, +none chosen: a modifier on the second press, a separate un-format action, or +accepting that the chord is lost and reaching nested emphasis by typing. + +**Approach.** When it is picked up, the transformation half is already +understood, so the notes below exist to stop it being rediscovered. A toggling +`wrap()` must distinguish three states, and a single "it unwraps" test passes +against most of them being broken: + +- **INSIDE** the tokens: `**this**` with `this` selected (2..6). The tokens sit + just outside the selection; the same characters stay selected afterwards. +- **AROUND** them: `**this**` selected whole (0..8). The selection shrinks to + the text that was between them. +- **PARTIALLY overlapping** one: `*this**` (6..13). Neither of the above. It + does not describe a wrapped span, and stripping would have to guess which + half of a token to keep, so wrapping is the predictable answer. + +**INSIDE must be checked before AROUND.** On `***this***` both tests match, and +only INSIDE removes the level the user actually asked for. + +**A naive adjacency test is wrong, and looks right.** Checking only whether the +characters either side of the selection equal the token means pressing *Italic* +on `**this**` finds a `*` on each side, strips one asterisk per side, and +**un-bolds text the user asked to italicise**. A strip must require the adjacent +RUN of token characters to be the token exactly, or the token plus one other +complete emphasis token: `***` is bold+italic and divisible either way, while a +run of two is one indivisible token whose half is not a token at all. This was +found by writing the italic-on-bold test, not by reading the code. + +The quote side is simpler but has one trap: a bare `>` is what the quote path +writes for a blank line, so an unquote that only recognises `"> "` leaves a +stray marker on every blank line in a round trip. Whether a mixed block (some +lines quoted, some not) quotes or unquotes is a decision; quoting it, so one +press makes the block uniform and the next unquotes it, avoids the button doing +two opposite things to two halves of one selection. + +**Constraints.** The spec amendment comes first and must resolve the +bold-then-italic question, or the same conflict recurs. `MarkdownFormat` is +painter-free and widget-free, so the whole state machine is unit-testable +without the composer; keep it that way. The toolbar shortcuts belong to the +composer window and do not touch `KeyMap`, so nothing here interacts with item +132. Note that toggling changes what the preserved selection is FOR, so +`wrappingTwiceNestsTheTokensAroundTheSameWords` and +`quotingAnAlreadyQuotedLineNestsIt` in `tests/test_formattoolbar.cpp` both +assert the current spec behaviour and would be replaced rather than extended. + + ## Deferred, unsized, or split out Items noted while triaging but not part of the original list. Same numbering |
