Add Fountain screenplay projects, exported straight to PDF

A screenplay is its own project rather than a file type mixed in with
prose, so this is one switch in Manuscript details, not a second file
extension threaded through order.rs and the file panel. Files stay `.md`
and keep the same editorial header; only the draft below the marker is
read as Fountain. They list, reorder and header-strip exactly as before.

src/fountain.rs parses the format. Almost nothing in Fountain is marked
up -- what makes a line a character cue is that it is in capitals with
something directly beneath it, and what makes the same words a
transition is a blank line below instead. The forcing characters are all
there for where that is not enough, along with notes, the boneyard and
inline emphasis. Sections and synopses are parsed and kept but never
printed: they are the writer's scaffolding.

src/pdf.rs writes the PDF by hand, for the reason odt.rs writes ODT by
hand -- no pandoc, no LibreOffice at runtime. It costs no dependency
either: a screenplay is set entirely in Courier, which is one of the
fourteen faces every reader must provide, so there is no font to embed
and no metrics to parse. Streams are left uncompressed; a feature script
is a few hundred kilobytes that way and stays readable when something
needs debugging.

src/screenplay.rs does layout. The geometry is the conventional one --
55 lines of 12pt on US Letter, action at 1.5", dialogue 2.5",
parentheticals 3.1", cues 3.7", transitions flush to 7.5" -- because a
page only reads as a minute of screen time if it is. A speech broken by
a page boundary is marked (MORE) and resumed under a repeated cue, a `^`
cue sets two speeches side by side, and a scene heading is never left
stranded at the foot of a page.

Two faults the tests missed and measuring the rendered PDF caught. A
hard-wrapped action paragraph was getting a blank line between every
source line, which on the page reads as a beat the writer never wrote;
consecutive lines are now one paragraph, with the breaks kept. And
reserving one line after a scene heading did not stop it stranding,
because every element that can follow a heading is separated from it by
a blank -- the reserve has to cover both. Both now have tests.

Verified beyond the unit tests: pdffonts confirms base-14 Courier with
nothing embedded, pdftotext -bbox puts every indent within a hundredth
of an inch of standard, and the export was driven through the real UI
against a scratch workspace and an isolated config.

Not built, because they were offered and never asked for: rendering
Fountain in the Preview pane, and exporting a manuscript as a .fountain
file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Bq2fUZNgksdPp3zeHqzSw
This commit is contained in:
2026-08-26 12:02:56 -05:00
parent be6a2d6a8b
commit 5a5017def8
9 changed files with 2580 additions and 25 deletions
+68 -2
View File
@@ -14,12 +14,14 @@ as an ordered manuscript.
in `order.json` inside the workspace, so it syncs along with the files. It
records each file's path, so subfolders travel with it.
* **Export** the whole manuscript as a single concatenated `.odt` file, with a
chapter heading before each file's content.
chapter heading before each file's content — or, for a screenplay project, as
a paginated Fountain-to-PDF script (see
[Screenplays](#screenplays-fountain)).
* **Start a new project** from a cookiecutter template (**File ▸ New project…**),
which builds the whole folder structure and opens its drafting folder.
Built in Rust with [`egui`](https://github.com/emilk/egui)/`eframe`. The ODT
writer is native (no `pandoc`/LibreOffice needed at runtime).
and PDF writers are both native (no `pandoc`/LibreOffice needed at runtime).
## Build
@@ -366,6 +368,70 @@ skips it rather than opening on a blank sheet.
For a chapters-plus-master export the title page goes on the master, not on each
chapter file.
### Screenplays (Fountain)
Tick **Screenplay (Fountain)** in Manuscript details to make the project a
screenplay. Two things change, and nothing else does:
- the draft below each file's marker is read as
[Fountain](https://fountain.io) rather than markdown, and
- **Export ODT** becomes **Export PDF**, writing a paginated screenplay instead
of a word-processor document.
The files stay ordinary `.md` files with the same editorial header
(`# Title:`, `# Slug:`, `### Rough Draft:`), they list and reorder in the left
pane the same way, and the header is stripped on export exactly as it is for
prose. One file per scene or sequence is the natural layout, but nothing
enforces it — the files are joined into one continuous script, because what
divides a screenplay is its scene headings, not its chapters.
Fountain needs no markup for the common elements; the shape of the line is
enough:
```
INT. REYNOLD'S HOUSE - KITCHEN - NIGHT
Rain on the window. Bixby stands at the sink with a plate in
each hand, not washing either of them.
BIXBY
(barely)
I said I'd do it.
MOM (O.S.)
That was Tuesday.
CUT TO:
```
A line starting `INT.`, `EXT.`, `EST.`, `INT./EXT.` or `I/E.` is a scene
heading. A line in capitals with something directly beneath it is a character
cue, and what follows is dialogue until the next blank line; a line in
parentheses inside that block is a parenthetical. A line in capitals ending
`TO:` with blank lines above and below is a transition. Everything else is
action, and consecutive lines are one paragraph.
Where the shape is not enough, force it: `.` for a scene heading, `!` for
action, `@` for a character cue, `>` for a transition. `> text <` centres a
line, `===` starts a new page, `~` marks a lyric. `*italic*`, `**bold**`,
`***both***` and `_underline_` work as they look. `#` sections, `=` synopses,
`[[notes]]` and `/* boneyard */` blocks are for you and never reach the page.
The PDF is the conventional layout, so a page reads as roughly a minute of
screen time: 12pt Courier on US Letter, 55 lines a page, scene headings and
action at 1.5″, dialogue at 2.5″, parentheticals at 3.1″, cues at 3.7″,
transitions flush to the 7.5″ right margin, and page numbers in the top-right
from the second page. A speech broken by a page boundary is marked `(MORE)` and
picked up under the cue again with `(CONT'D)`; a scene heading is never left
stranded at the foot of a page; a `^` cue sets the two speeches side by side.
Courier is one of the fonts every PDF reader is required to provide, so nothing
is embedded and the file stays small.
**Begin exports with a title page** works here too, giving the standard spec
title page: the title a third of the way down, the credit beneath it, and the
contact details at the foot. **Standard manuscript format** has no effect on a
screenplay — a script is always set in screenplay format.
### Exporting chapter files (File ▸ Export chapters + master)
Writes one `.odt` per chapter into a `chapters/` folder, plus an `.odm` master