notation: \ am Zeilenende setzt die Zeile fort (SPEC §1, D59)

Eine Zeile trägt alles auf einmal — im mitgelieferten Plan ist die längste
122 Zeichen lang, und seit das Textfeld nicht mehr umbricht (D49) muss man
dafür schieben. Ein `\` am Zeilenende verteilt sie jetzt auf mehrere
Textzeilen, ohne dass ein neuer Knoten entsteht.

Leerraum davor ist Pflicht (`… \`, nicht `…\`) — bewusst gegen die
Shell-Gewohnheit: Ohne die Regel verschluckt ein Label wie `C:\temp\` stumm
den folgenden Knoten, mit ihr bekommt man nur keine Fortsetzung, was man
sofort sieht. Der laute Fehler ist der bessere.

Umgesetzt als Vor-Durchlauf `logicalLines()`: Die Folgezeile ist Teil der
Zeile, bevor irgendetwas aus ihr gelesen wird — die Extraktionsreihenfolge
aus §1 bleibt unangetastet. Alles gehört zur ersten Zeile: Einrückung,
Warnungs-Zeilennummer, Rückschreiber; der Cursor in der Fortsetzung wählt
ihren Knoten aus, wie bei Beschreibungszeilen.

SPEC §1/§9, llms.md, Legende in neun Sprachen, D59; 20 neue Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-24 13:17:26 +02:00
co-authored by Claude Opus 5
parent 257aab08dd
commit 410dacdc6c
8 changed files with 331 additions and 6 deletions
+1
View File
@@ -19,6 +19,7 @@ reverse.
## 2026-08-24
- A line ending in a space and `\` continues on the next line, so a long node no longer has to fit into one
- A star in the header opens What's new: the changes of the last few days, and a link per day that shows the nodes it touched in the diagram
- A warning triangle replaces the question mark as the pointer over faulty line numbers
- The node window replaces the browser tooltip everywhere — at the pointer, on keyboard focus and on touch
+73
View File
@@ -4202,3 +4202,76 @@ Besuchsvergleich darunter bleibt damit das erste, worauf der Blick fällt.
nichts. Der Schlüssel ist trotzdem in allen neun Sprachen angelegt, auch auf
Englisch: Ein Loch in der Tabelle lädt dazu ein, beim nächsten Durchsehen für
einen Fehler gehalten und „repariert" zu werden.
## D59 — Fortsetzungszeilen: `\` am Zeilenende, Leerraum davor Pflicht
Eine Zeile trägt in dieser Notation alles auf einmal — Einrückung, Zeichen,
Statusbox, Label, Größe, URL, Tags, ID, Abhängigkeiten, Fokusmarke, Kommentar.
Im mitgelieferten Plan ist die längste Zeile 122 Zeichen lang (D49), und seit
das Textfeld nicht mehr umbricht, muss man dafür waagerecht schieben. Ein `\`
am Zeilenende verteilt sie jetzt auf mehrere Textzeilen, ohne dass ein neuer
Knoten entsteht.
**Leerraum vor dem `\` ist Pflicht** — `… \` setzt fort, `…\` nicht. Das ist
die entscheidende Festlegung, und sie geht bewusst gegen die Gewohnheit aus
Shell, C und Makefile, wo `foo\` fortsetzt. Der Grund ist die **Asymmetrie der
Fehlerfälle**:
- Ohne die Regel verschluckt ein Label, das selbst auf einen Backslash endet
(`C:\temp\`), **stumm den folgenden Knoten**. Ein Knoten verschwindet aus dem
Diagramm, und im Text sieht die Zeile richtig aus.
- Mit der Regel bekommt, wer aus der Shell `foo\` schreibt, **keine
Fortsetzung**. Die Zeile bleibt stehen, der `\` ist sichtbar, der Fehler
erklärt sich beim Hinsehen.
Der zweite Fehler ist häufiger, der erste ist schlimmer — und dieses Projekt
zieht durchweg den lauten dem stillen vor (SPEC §4, D40). Die Regel ist zudem
keine neue Sorte: `=`, `>`/`<` und `"` verlangen alle Leerraum, nur auf der
**anderen** Seite des Zeichens. Ein `\\`-Escape als Alternative wäre die dritte
Möglichkeit gewesen — verworfen, weil die Notation sonst nirgends escapt und
eine einzige Escape-Regel für einen Randfall mehr Erklärung kostet, als sie
wert ist.
**Verbunden wird mit genau einem Leerzeichen.** Damit ist ein Token nicht über
den Umbruch trennbar — eine zerschnittene URL bleibt zerschnitten. Das ist eine
echte Einschränkung und trotzdem richtig herum: Ohne das Leerzeichen führen
`Backend \` + `Frontend` zu `BackendFrontend`, und *das* wäre die stille
Variante. Wer eine lange URL hat, lässt sie in ihrer Zeile.
**Alles gehört zur ersten Zeile.** Ihre Einrückung bestimmt die Ebene, ihre
Nummer nennen die Warnungen, und alles, was zurückschreibt, fasst nur sie an —
`setFoldMark()` (D38) und `expandShortIds()` (D55) finden Gate und Statusbox
dort. `expandShortIds()` musste dafür lernen, Fortsetzungszeilen zu
**überspringen**: Sonst hätte es eine solche Zeile für eine Wurzelzeile
gehalten (sie hat kein Gate) und den Vorfahren-Stapel verdorben.
**Der Cursor in einer Fortsetzungszeile wählt ihren Knoten aus** — dieselbe
Regel wie bei Beschreibungszeilen (D40-Nachtrag 2), und aus demselben Grund:
Die Zeile trägt keinen eigenen Knoten, gehört aber zu einem, und wer darin
schreibt, arbeitet an genau diesem. Getragen wird das von `node.descLines`, das
damit nicht mehr nur Beschreibungen führt; der Name bleibt, weil eine
Umbenennung durch Renderer, Tests und Snapshots nichts hinzufügte, was der
Kommentar nicht sagt.
**Gilt nur im Baumteil.** Hinter dem `---`-Trenner ist der Zeilenumbruch
Absatzstruktur (§1), und der Inhalt ist ausdrücklich Freitext — ein `\` bleibt
dort gewöhnlicher Text.
**Reihenfolge gegenüber dem Kommentar:** Kommentare fallen zuerst weg (§1,
Schritt 1), das Verbinden ist Schritt 1b. Also setzt `- A \ %% Notiz` fort und
`- A %% Notiz \` nicht — beides ist die natürliche Lesart, und sie fällt ohne
Sonderregel richtig aus.
**Umgesetzt als Vor-Durchlauf** (`logicalLines()` in parser.js): Er liefert
statt roher Zeilen `{raw, line, cont}`, und `parse()` arbeitet unverändert
darauf weiter. Dadurch gibt es genau **eine** Stelle, die die Regel kennt, und
die Extraktionsreihenfolge aus §1 bleibt unangetastet — die Folgezeile ist
schon Teil der Zeile, bevor irgendetwas aus ihr gelesen wird. Ein Sonderfall
steckt darin: Bleibt von der ersten Zeile nur die **Einrückung** übrig (` \`),
darf sie nicht mit weggeputzt werden — sie trägt die Ebene.
**Nachgemessen** im laufenden Editor: `- Ein Knoten mit einem \` + `sehr langen
Titel (L) @anna` ergibt einen Knoten mit `data-line="2"` und
`data-desc-lines="3"`, Größe `L` und Tag `anna` von der zweiten Zeile gelesen,
0 Warnungen; der Cursor auf Zeile 3 hebt denselben Knoten hervor wie auf Zeile
2. 20 neue Tests; die Gegenprobe (Leerraum-Pflicht aus dem Regex entfernt)
lässt genau die zwei danach benannten Zusicherungen fallen.
+38 -2
View File
@@ -14,6 +14,8 @@ Alle Bestandteile außer dem Label sind optional. Die Extraktion erfolgt in
dieser Reihenfolge (wichtig für Kollisionsfreiheit):
1. Kommentar entfernen: alles ab `%%` bis Zeilenende.
1b. Fortsetzung: Endet die Zeile jetzt auf Leerraum + `\`, gehört die
Folgezeile noch dazu (siehe unten). Erst danach ist die Zeile vollständig.
2. Einrückung, Zeichen (`-` / `+` / `|` / `=`), Statusbox `[…]` und Faltmarke
(`>` / `<`) per Zeilen-Regex; `=` nur mit folgendem Leerraum (§3),
die Faltmarke ebenso (siehe unten).
@@ -25,6 +27,38 @@ dieser Reihenfolge (wichtig für Kollisionsfreiheit):
8. Fokusmarke: `!!!` als **alleinstehendes** Token (siehe unten).
9. Rest, whitespace-normalisiert = Label. Leeres Label ⇒ Zeile ignorieren.
**Fortsetzungszeile `\`** — eine lange Zeile darf auf mehrere Textzeilen
verteilt werden, ohne dass ein neuer Knoten entsteht:
- Endet eine Zeile — **nach** dem Entfernen des Kommentars — auf **Leerraum und
dann `\`** als letztem Zeichen, wird die **Folgezeile angehängt**: Der `\`
entfällt, die Einrückung der Folgezeile entfällt, verbunden wird mit **genau
einem Leerzeichen**. Mehrere `\` hintereinander setzen die Zeile über
entsprechend viele Textzeilen fort.
- **Leerraum davor ist Pflicht** (`… \`, nicht `…\`) — dieselbe Sorte Regel wie
bei `=`, `>`/`<` und `"`, nur an der anderen Seite des Zeichens. Sie hält
Labels heraus, die selbst auf einen Backslash enden (`C:\temp\`): Ohne sie
verschluckte so eine Zeile stumm den folgenden Knoten. Der Preis ist die
umgekehrte Verwechslung — wer aus der Shell `…\` gewohnt ist, bekommt keine
Fortsetzung —, und die ist die harmlosere: Die Zeile bleibt stehen, was man
sofort sieht.
- **Alles gehört zur ersten Zeile:** Ihre Einrückung bestimmt die Ebene (§2),
ihre Nummer nennen die Warnungen, und Werkzeuge, die zurückschreiben
(Faltmarke §9, ID-Kurzform §9), fassen nur sie an. Der Cursor in einer
Fortsetzungszeile wählt den Knoten der ersten aus (§9, Sprung).
- Ein Token darf **nicht** über den Umbruch hinweg getrennt werden — verbunden
wird mit einem Leerzeichen, eine zerschnittene URL bleibt zerschnitten.
- Gilt nur im **Baumteil**. Im Beschreibungsteil hinter `---` (siehe unten) sind
Zeilenumbrüche Absatzstruktur; ein `\` bleibt dort gewöhnlicher Text.
- Steht der `\` in der **letzten** Zeile der Datei, gibt es nichts anzuhängen:
Er entfällt, die Zeile bleibt für sich.
Referenz-Regex (Schritt 1b, geprüft auf der kommentarfreien Zeile):
```
(^|[ \t])\\[ \t]*$
```
**Faltmarke `>` / `<`** — bestimmt, wie das Dokument **eröffnet** wird:
- Steht **unmittelbar vor dem Label**, also hinter der Statusbox
@@ -709,8 +743,10 @@ verknüpft (siehe D25):
„hinschauen": Er holt **keine Bildschirmtastatur** herauf — die erscheint erst,
wenn das Textfeld selbst angetippt wird.
- **Text → Diagramm:** Der Knoten der **Cursor-Zeile** wird im Diagramm
hervorgehoben und beim Zeilenwechsel ins Bild gescrollt. **Beschreibungszeilen
zählen zu ihrem Knoten**: Steht der Cursor in einer `"`-Zeile (§1) oder in
hervorgehoben und beim Zeilenwechsel ins Bild gescrollt. **Beschreibungs- und
Fortsetzungszeilen (§1)
zählen zu ihrem Knoten**: Steht der Cursor in einer `"`-Zeile (§1), in einer
Fortsetzung hinter `\` oder in
einem ID-Block des `---`-Beschreibungsteils (Kopfzeile eingeschlossen), gilt
der beschriebene Knoten als ausgewählt — solche Zeilen tragen keinen eigenen
Knoten, gehören aber zu einem, und wer darin schreibt, arbeitet an genau
+7
View File
@@ -8,6 +8,7 @@
- [^] #not.status: Status box, eight states (S)
- [^] #not.size: T-shirt size and the "decompose from M" rule (S)
- [^] #not.people: People tags, bare URLs, %% comments (XS)
- [x] #not.cont: A trailing backslash continues the line (XS) %% space before it is required
- [^] #not.gates: And/or decomposition (S)
- [^] #not.opt: Optional nodes — neither required nor an alternative (S)
- [^] #not.id: Node IDs, (#auth:) before the title (S) %% often the ticket number, see SPEC §11
@@ -206,6 +207,12 @@
label, size, URL, tags, comment. The order in which those are extracted is
fixed, which is what keeps them from colliding with each other.
#not.cont
A long line may be spread over several text lines: ending one with a space
and a backslash makes the next line part of it, so no new node begins. The
space is required, or a label like C:\temp\ would silently swallow the node
below it.
#not.status
Eight states from vague idea to live in production, written as an extended
Markdown task box. The colours follow risk rather than progress: money spent