aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/specs
diff options
context:
space:
mode:
Diffstat (limited to 'docs/superpowers/specs')
-rw-r--r--docs/superpowers/specs/2026-08-20-compose-and-send-design.md55
1 files changed, 52 insertions, 3 deletions
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