From 0496db64c34763c586ffad7d68ed9845a5395452 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Thu, 20 Aug 2026 12:26:51 +0200 Subject: docs: specify the composer's formatting toolbar, item 123 The spec said "the editor is plain text" and left it there, which reads as "you are on your own with the syntax". Storage format and editing affordances are separate decisions and only the first was stated. The toolbar is text transformation over the markdown source, not rich-text editing: bold, italic, code, strikethrough, link and quote, selection-aware, with the cursor landing between the tokens when there is no selection. Its shortcuts belong to the composer window's own scope and do not touch KeyMap, which matters for item 132: the two namespaces should not be conflated when that rule is revisited. Live syntax highlighting is a follow-up (item 133) rather than part of this: agreeing with the grammar about nesting and about code spans is the expensive half, and it is better judged after living with the toolbar. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YDq53rMd3AQp7QmcZzpuBM --- .../plans/2026-08-03-post-0.1.0-usability.md | 5 +- .../specs/2026-08-20-compose-and-send-design.md | 55 ++++++++++++++++++++-- 2 files changed, 56 insertions(+), 4 deletions(-) (limited to 'docs') 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 165f96e..f01c94e 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 @@ -202,6 +202,7 @@ taking that too literally. | 130 | A message cannot be attached to another message directly | v2 | S | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** A `message/rfc822` part, which GMime builds natively. The manual route exists from 123's first commit: `save_message` writes the `.eml` and it is attached as a file | | 131 | The markdown dialect and extensions are fixed | v2 | S | open, 2026-08-20, from the item 123 brainstorm. **Blocked on 123.** Configurable in the shape Hugo's config uses. Deliberately fixed initially: CommonMark plus autolink, strikethrough and tasklist | | 132 | Every action must have a shortcut, and that no longer serves | policy | S | open, 2026-08-20, raised by the user during the item 123 brainstorm. `everyActionHasAShortcut` was written when the action list was short; item 123 adds six more, and each new action consumes a chord whether or not anyone would press it. Replacement is the shape `everyActionIsReachableFromAMenu()` already has: menu reachability required, shortcuts a chosen subset. **Not** done inside 123, which would confuse two changes | +| 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 | Sizes are rough: XS under an hour, S a sitting, M a session. @@ -1029,7 +1030,9 @@ by the user's own note. The brainstorm opened items 128 to 132: an outbox, inline images, attaching a message to a message, a configurable markdown dialect, and a review of the every-action-has-a-shortcut rule. -**Size: L.** Four new units, six new actions, and one new build dependency, +**Size: L.** Four new units, six new actions, a formatting toolbar over the +markdown source (whose shortcuts live in the composer's own scope and do not +touch `KeyMap`), and one new build dependency, `cmark-gfm`. That dependency is cheap: it ships in stock Slackware (`cmark-gfm-0.29.0.gfm.13-x86_64-3`, verified 2026-08-20), so it needs a `pkg_check_modules` line here and **no** `REQUIRES` entry in the SlackBuild, diff --git a/docs/superpowers/specs/2026-08-20-compose-and-send-design.md b/docs/superpowers/specs/2026-08-20-compose-and-send-design.md index 3171280..28a025a 100644 --- a/docs/superpowers/specs/2026-08-20-compose-and-send-design.md +++ b/docs/superpowers/specs/2026-08-20-compose-and-send-design.md @@ -125,9 +125,14 @@ knowing what is actually on disk. ### The body is markdown, rendered by cmark-gfm -The editor is plain text. What is typed is markdown, and it is what the -`text/plain` part carries, unmodified. The `text/html` part is generated from -it. +The editor holds plain text and what is typed is markdown. That source is what +the `text/plain` part carries, unmodified; the `text/html` part is generated +from it. + +**Plain-text storage does not mean a bare text box.** The two are separate +decisions and it is worth stating the second explicitly, because "the editor is +plain text" reads as "you are on your own with the syntax". The composer carries +a formatting toolbar with `Ctrl+B`-style shortcuts, described below. **cmark-gfm, not a hand-written parser for a limited set.** A three-rule parser and a real markdown parser share no code, so the first is deleted entirely when @@ -164,6 +169,39 @@ markdown is a display facility whose `toHtml()` emits markup styled for `QTextEdit`, which would need unpicking before it is fit to send: the same throwaway problem one level up. +### The composer has a formatting toolbar + +Each button is a **text transformation over the markdown source**, not +rich-text editing. Nothing about the buffer changes: it stays markdown that the +user can also type by hand. + +| Button | Wraps in | Shortcut | +|---|---|---| +| Bold | `**` | `Ctrl+B` | +| Italic | `*` | `Ctrl+I` | +| Code | `` ` `` | `Ctrl+`` ` `` | +| Strikethrough | `~~` | none | +| Link | `[text](url)` | `Ctrl+K` | +| Quote | `> ` per line | none | + +**Selection-aware.** With a selection, the tokens wrap it and the selection is +preserved. With none, the pair is inserted with the cursor between them, so +typing continues inside. Quote is line-based rather than a wrap, applying to +every line the selection touches. + +**These shortcuts do not touch `KeyMap`.** They belong to the composer window, +which is a separate shortcut scope, so `Ctrl+B` here does not consume `Ctrl+B` +from the main window's map and does not participate in the +every-action-has-a-shortcut rule. Keeping the two namespaces apart matters for +item 132. + +**No live syntax highlighting** in this design. A `QSyntaxHighlighter` colouring +`**bold**` in the editor is standard Qt and needs no dependency, but it has to +agree with the markdown grammar about nesting and about code spans suppressing +what is inside them, which is the sort of thing that looks nearly right and +stays annoying for years. It is a follow-up, better judged after living with the +toolbar. + ### Whether the HTML part is sent is per-message `sendHtml` decides whether the message is `multipart/alternative` (plain + @@ -511,6 +549,12 @@ and it is pure logic, so it is tested apart from the window. All five of the user's addresses stripped from a reply-all; every account-resolution rule including the multi-maildir ambiguity; subject prefixing. +**The formatting toolbar** is tested through its transformations, not through +the widget: wrap with a selection, insert with none, quote applying per line, +and the cursor landing between the tokens in the empty-selection case. That last +one is the property a user notices immediately when it is wrong, and it is +invisible to a test that only compares the resulting text. + **In `test_mainwindow`**: action enablement against a receive-only account, the ribbon appearing, and `everyActionIsReachableFromAMenu()` covering the six new actions for free. `WorkerBackedWindow` gains a knob for writing an account @@ -536,6 +580,11 @@ Deliberately out of scope here, each worth its own backlog entry. `save_message` exists from the first commit. - **Configurable markdown dialect and extensions**, in the shape Hugo's configuration uses. +- **Live markdown syntax highlighting in the composer.** A + `QSyntaxHighlighter` over the editor, so `**bold**` reads as bold while the + buffer stays plain markdown. Deliberately after the toolbar: the grammar + agreement it needs is the expensive part, and the toolbar is what makes the + feature usable. - **Review "every action has a shortcut".** `everyActionHasAShortcut` was written when the action list was short. Six more actions takes the count past the point where a chord for everything is useful, and each new action consumes -- cgit v1.2.3