Skip to main content

Construct & Filter

show::pipeline::build_show_from_text is the top-level entry point:

pub fn build_show_from_text(text: &str, config: &TextParseConfig) -> Show

It classifies each line, constructs the tree, and filters the result.

Construct​

construct_show walks the classified lines and maintains an active act and scene, accumulating dialogue between structural markers.

Structural handling​

  • Act header — closes the current scene and act, then starts a new act.
  • Scene header — closes the current scene, then starts a new scene under the active act (or at the top level if there is no act).
  • Division header (PROLOGUE, INTERMISSION, …) — treated as a top-level scene.
  • Stage directions — not stored, but they mark that structure has been seen (so title/front-matter before the first marker can be discarded).

Dialogue accumulation​

  • Dialog lines are concatenated into a dialogue buffer (space-separated).
  • A blank line flushes the buffer into the active scene, so each paragraph becomes its own group of cues.
  • Over-long dialogue is split into cues by split_cue_text.

Implicit scenes and fallbacks​

  • Dialogue collected inside an act before any scene header becomes an implicit scene (Scene 1, Scene 2, …) so an act always contains child sections rather than cues.
  • If no act or scene headers are found at all, all text becomes a single default Scene 1, so nothing is dropped.
  • The parser uses a has_structure flag to discard title-page and front-matter lines that appear before the first structural element.

Invariants​

  • A section is a leaf (cues) or a container (child sections), never both.
  • Every generated section and cue gets a fresh v4 UUID.

Filter​

filter_show(show, &FilterConfig) is a separate cleanup pass over the constructed tree:

FilterConfig fieldDefaultEffect
drop_empty_sectionsfalseDrop sections with no cues and no child sections.
drop_noise_cuestrueDrop cues that are only punctuation, digits, or whitespace.

Filtering recurses into nested sections, so a container is kept if any descendant survives.

Cue splitting​

split_cue_text(text, &TextParseConfig) (in parse.rs) turns a dialogue block into crisp cues:

  1. Split sentences on ., !, and ?, keeping the terminator.
  2. Split long sentences that exceed max_cue_length at the strongest nearby punctuation (;, :, —, ,), searching right-to-left so the latest occurrence wins; falls back to the last whitespace so words are never cut.
  3. Merge small fragments below min_cue_length into a neighboring cue.

See TextParseConfig for defaults and tuning.