aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/specs
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-20 12:26:51 +0200
committerDanilo M. <danix@danix.xyz>2026-08-20 12:26:51 +0200
commit0496db64c34763c586ffad7d68ed9845a5395452 (patch)
tree88d77364de8e704faffcdfbf5e4b4ac3b3fdcb28 /docs/superpowers/specs
parent2e1a6df8fd911ce933f24595be0299ffe3b90d70 (diff)
downloadqtmaildir-0496db64c34763c586ffad7d68ed9845a5395452.tar.gz
qtmaildir-0496db64c34763c586ffad7d68ed9845a5395452.zip
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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YDq53rMd3AQp7QmcZzpuBM
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