aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers
diff options
context:
space:
mode:
Diffstat (limited to 'docs/superpowers')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md5
-rw-r--r--docs/superpowers/specs/2026-08-20-compose-and-send-design.md55
2 files changed, 56 insertions, 4 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 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