help documentation
This commit is contained in:
@@ -278,6 +278,8 @@ pub struct App {
|
|||||||
settings_test_status: String,
|
settings_test_status: String,
|
||||||
/// Whether the markdown cheatsheet window is open.
|
/// Whether the markdown cheatsheet window is open.
|
||||||
show_cheatsheet: bool,
|
show_cheatsheet: bool,
|
||||||
|
/// Whether the User Guide window is open.
|
||||||
|
show_user_guide: bool,
|
||||||
/// Whether the find/replace bar above the editor is visible.
|
/// Whether the find/replace bar above the editor is visible.
|
||||||
show_find: bool,
|
show_find: bool,
|
||||||
/// The search text.
|
/// The search text.
|
||||||
@@ -510,6 +512,7 @@ impl App {
|
|||||||
settings_test_rx: None,
|
settings_test_rx: None,
|
||||||
settings_test_status: String::new(),
|
settings_test_status: String::new(),
|
||||||
show_cheatsheet: false,
|
show_cheatsheet: false,
|
||||||
|
show_user_guide: false,
|
||||||
show_find: false,
|
show_find: false,
|
||||||
find_query: String::new(),
|
find_query: String::new(),
|
||||||
replace_query: String::new(),
|
replace_query: String::new(),
|
||||||
@@ -788,6 +791,9 @@ impl eframe::App for App {
|
|||||||
if self.show_cheatsheet {
|
if self.show_cheatsheet {
|
||||||
crate::help::cheatsheet_window(ctx, &mut self.show_cheatsheet);
|
crate::help::cheatsheet_window(ctx, &mut self.show_cheatsheet);
|
||||||
}
|
}
|
||||||
|
if self.show_user_guide {
|
||||||
|
crate::help::user_guide_window(ctx, &mut self.show_user_guide);
|
||||||
|
}
|
||||||
|
|
||||||
if self.pending_repo.is_some() {
|
if self.pending_repo.is_some() {
|
||||||
self.repo_prompt(ctx);
|
self.repo_prompt(ctx);
|
||||||
|
|||||||
@@ -438,6 +438,10 @@ impl App {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
ui.menu_button("Help", |ui| {
|
ui.menu_button("Help", |ui| {
|
||||||
|
if ui.button("📖 User Guide").clicked() {
|
||||||
|
ui.close_menu();
|
||||||
|
self.show_user_guide = true;
|
||||||
|
}
|
||||||
if ui.button("📝 Markdown cheatsheet").clicked() {
|
if ui.button("📝 Markdown cheatsheet").clicked() {
|
||||||
ui.close_menu();
|
ui.close_menu();
|
||||||
self.show_cheatsheet = true;
|
self.show_cheatsheet = true;
|
||||||
|
|||||||
+386
-5
@@ -1,9 +1,10 @@
|
|||||||
//! In-app **Markdown cheatsheet** window: a quick reference for the markdown
|
//! In-app documentation, reached from the **Help** menu: a **Markdown
|
||||||
//! md-manuscript understands, plus the manuscript-specific conventions (YAML frontmatter
|
//! cheatsheet** (the markdown/frontmatter syntax md-manuscript understands)
|
||||||
//! metadata and comments) applied at export time.
|
//! and a broader **User Guide** (what every window, menu item and setting
|
||||||
|
//! actually does).
|
||||||
//!
|
//!
|
||||||
//! Pure rendering — the caller owns the `open` flag so the window's ✕ works via
|
//! Pure rendering — the caller owns the `open` flag so each window's ✕ works
|
||||||
//! [`egui::Window::open`].
|
//! via [`egui::Window::open`].
|
||||||
|
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
|
|
||||||
@@ -19,6 +20,369 @@ pub fn cheatsheet_window(ctx: &egui::Context, open: &mut bool) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The User Guide window: what every window, menu item and setting does.
|
||||||
|
/// Complements the Markdown Cheatsheet, which covers syntax rather than
|
||||||
|
/// features.
|
||||||
|
pub fn user_guide_window(ctx: &egui::Context, open: &mut bool) {
|
||||||
|
egui::Window::new("📖 User Guide")
|
||||||
|
.open(open)
|
||||||
|
.resizable(true)
|
||||||
|
.default_width(640.0)
|
||||||
|
.default_height(620.0)
|
||||||
|
.show(ctx, |ui| {
|
||||||
|
egui::ScrollArea::vertical().show(ui, user_guide_body);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn user_guide_body(ui: &mut egui::Ui) {
|
||||||
|
intro(
|
||||||
|
ui,
|
||||||
|
"What every window, menu item and setting does. For markdown and \
|
||||||
|
frontmatter syntax, see Help ▸ 📝 Markdown Cheatsheet instead.",
|
||||||
|
);
|
||||||
|
|
||||||
|
guide_getting_started(ui);
|
||||||
|
guide_organizing(ui);
|
||||||
|
guide_focus_and_pace(ui);
|
||||||
|
guide_planning_tools(ui);
|
||||||
|
guide_staying_on_track(ui);
|
||||||
|
guide_revision_and_safety(ui);
|
||||||
|
guide_exporting(ui);
|
||||||
|
guide_projects_and_templates(ui);
|
||||||
|
guide_proofing(ui);
|
||||||
|
guide_plot_beats(ui);
|
||||||
|
guide_settings_reference(ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_getting_started(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Getting started");
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"Set the Workspace path in the top bar (📂 to browse) and press Open — \
|
||||||
|
the folder is created if it doesn't exist. + New (type a name, \
|
||||||
|
optionally with folders like part-1/ch-01) or + New Scene creates a \
|
||||||
|
file; edit on the right and Ctrl+S (or Save) writes it to disk.",
|
||||||
|
);
|
||||||
|
note(
|
||||||
|
ui,
|
||||||
|
"Opening a folder that contains a 05-First Draft-style subfolder puts \
|
||||||
|
the app in Project mode: that subfolder's files are the book \
|
||||||
|
(ordered, numbered, exported); everything else — characters, \
|
||||||
|
outline, scratch pad — is reference material, reached through the \
|
||||||
|
Tools menu windows below rather than listed in the file panel. View \
|
||||||
|
▸ Show reference files lists it anyway, dimmed.",
|
||||||
|
);
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"File ▸ ⟳ Sync (git) commits everything, pulls --rebase, and pushes. \
|
||||||
|
Init git first if the workspace isn't a repository yet; Settings ▸ \
|
||||||
|
Git remote… attaches it to a server (and can create the repository \
|
||||||
|
on Gitea for you, given a server URL, user and token).",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_organizing(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Organizing the manuscript");
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"The file list is a tree: give a new file a path (part-2/ch-03) to \
|
||||||
|
nest it, and drag its ⠿ handle onto a folder — or among its files — \
|
||||||
|
to move it. Drop on “↥ drop here for the top level” to pull it back \
|
||||||
|
out. A folder exists only as long as it holds a file.",
|
||||||
|
);
|
||||||
|
note(
|
||||||
|
ui,
|
||||||
|
"Order is set by dragging and saved in order.json. A folder's files \
|
||||||
|
always stay together as a block, positioned by whichever of them \
|
||||||
|
sorts earliest — and the export is the tree read top to bottom, so \
|
||||||
|
this is also the chapter order.",
|
||||||
|
);
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"The Chapter title field overrides a file's auto-derived title (a \
|
||||||
|
Title: header field, or its position — “3.” — if there is none). \
|
||||||
|
Right-click a file for Rename…, Copy path, 🗄 Archive and 🗑 Delete….",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_focus_and_pace(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Focus & pace");
|
||||||
|
entries(
|
||||||
|
ui,
|
||||||
|
&[
|
||||||
|
(
|
||||||
|
"Ctrl/Cmd + D",
|
||||||
|
"Distraction-free: folds the toolbar and file list away, leaving \
|
||||||
|
the page. Again to bring them back.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"View ▸ Typewriter scrolling & focus",
|
||||||
|
"While Distraction-free is on: keeps the caret's line centred \
|
||||||
|
and dims every paragraph but the current one.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Zoom / Contrast sliders",
|
||||||
|
"Above the editor — scale the editor text, or brighten it \
|
||||||
|
against the theme background.",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"Tools ▸ ⏱ Sprint… tracks a daily whole-manuscript word goal \
|
||||||
|
(default 500, resets at the day boundary) with a progress bar, plus \
|
||||||
|
a start/stop Pomodoro-style sprint timer with a live words/minute \
|
||||||
|
readout. In Distraction-free mode, an active sprint's countdown \
|
||||||
|
also shows compactly in the status bar.",
|
||||||
|
);
|
||||||
|
note(
|
||||||
|
ui,
|
||||||
|
"The status bar's 🔥 N-day streak counts consecutive calendar days \
|
||||||
|
the manuscript's total word count grew — a day with no growth, or a \
|
||||||
|
skipped day, breaks it. It's recorded automatically on every save.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_planning_tools(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Planning & reference");
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"These read a project's other parts — everything that isn't the \
|
||||||
|
draft itself.",
|
||||||
|
);
|
||||||
|
entries(
|
||||||
|
ui,
|
||||||
|
&[
|
||||||
|
(
|
||||||
|
"Tools ▸ ☑ Outline…",
|
||||||
|
"Reads the outline scaffold's HTML-comment beats and shows a \
|
||||||
|
progress bar per section, nested by heading. A beat with a \
|
||||||
|
matching chapter name gets a “→ open draft” link.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Tools ▸ 👥 Characters…",
|
||||||
|
"Every character sheet, which scenes they appear in (by \
|
||||||
|
matching Characters: fields), and ▦ Rebuild grid to \
|
||||||
|
regenerate character_grid.md.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Tools ▸ 📖 Story Bible…",
|
||||||
|
"Indexes character/location/lore sheets and auto-links \
|
||||||
|
mentions of them in the draft — no markup needed, though \
|
||||||
|
[[Name]] and @Name both work too. Hover a highlighted name \
|
||||||
|
for a summary card; click its window entries to jump to \
|
||||||
|
references.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Tools ▸ 📖 Story Bible editor…",
|
||||||
|
"A breakout window for editing Story Bible sheets directly: \
|
||||||
|
the full tree on the left, a text editor on the right. \
|
||||||
|
Saving refreshes the index automatically.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Tools ▸ 🗂 Corkboard…",
|
||||||
|
"One card per chapter — title and synopsis — drag to reorder \
|
||||||
|
the manuscript itself, the same reorder a file-panel drag \
|
||||||
|
does.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Tools ▸ 🧾 Synopsis…",
|
||||||
|
"Every chapter's Slug: line in one scrollable list, for \
|
||||||
|
scanning the whole manuscript's shape at a glance.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Snowflake progress",
|
||||||
|
"Collapsible strip at the top of the file panel: a ○/◐/● \
|
||||||
|
reading per snowflake-template stage folder, by word count. \
|
||||||
|
A nudge, not a gate — folders the current template doesn't \
|
||||||
|
have are simply left out.",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_staying_on_track(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Staying organized while drafting");
|
||||||
|
entries(
|
||||||
|
ui,
|
||||||
|
&[
|
||||||
|
(
|
||||||
|
"Tools ▸ 🔍 Placeholders…",
|
||||||
|
"Finds bracketed markers left mid-draft — [TODO], [TK], \
|
||||||
|
[FIXME], [XXX], [NOTE], [???] — grouped by file, click to \
|
||||||
|
jump to one.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Tools ▸ 📥 Quick note… (Ctrl+Shift+N)",
|
||||||
|
"A small popup for jotting a stray idea without losing your \
|
||||||
|
place — appended, timestamped, to Quick Notes.md in the \
|
||||||
|
project's Scratch Pad folder.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Misc Scenes",
|
||||||
|
"A dumping ground for scenes not yet placed (under \
|
||||||
|
05-First Draft in the bundled template) — visible, editable \
|
||||||
|
and word-counted like any other folder, but left out of \
|
||||||
|
every export. Configurable as export_exclude_folders in \
|
||||||
|
config.json.",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_revision_and_safety(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Revision & safety");
|
||||||
|
entries(
|
||||||
|
ui,
|
||||||
|
&[
|
||||||
|
(
|
||||||
|
"Edit ▸ 📸 Snapshots…",
|
||||||
|
"Automatic git commits at a configurable word-count interval \
|
||||||
|
(default every 250 words), plus a manual snapshot button and \
|
||||||
|
one-click rollback to any of them.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Edit ▸ ⇄ Changes since last commit…",
|
||||||
|
"Diffs the open file against its last committed version, \
|
||||||
|
coloured the way git colours a diff.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Edit ▸ 🔎 Search workspace… (Ctrl+Shift+F)",
|
||||||
|
"Find — and optionally replace — across every file in the \
|
||||||
|
workspace at once, not just the open one. A safety commit is \
|
||||||
|
made automatically before a workspace-wide replace.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Status: header field",
|
||||||
|
"Gives a file a badge in the file panel (initials, so \
|
||||||
|
“Structural Edit” shows as “SE”) and a Status filter above \
|
||||||
|
the list, to narrow it to one revision stage.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"🗄 Archive",
|
||||||
|
"Moves a file into the project's archive folder (kept out of \
|
||||||
|
the file panel and the export) without deleting it — for \
|
||||||
|
material you've moved past, not material you want gone.",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_exporting(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Exporting");
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"File ▸ Export ODT concatenates every manuscript file into one \
|
||||||
|
document, each starting a new page, headed by its chapter title and \
|
||||||
|
optional Slug: caption. File ▸ Export chapters + master (.odm) \
|
||||||
|
instead writes one .odt per chapter plus a linking master — treat \
|
||||||
|
the master as a starting point to relink, not the assembled book.",
|
||||||
|
);
|
||||||
|
note(
|
||||||
|
ui,
|
||||||
|
"Settings ▸ Manuscript details…'s Standard manuscript format lays \
|
||||||
|
the export out the way a submission is expected to arrive (12pt \
|
||||||
|
Courier, double-spaced, page headers, chapters a third of the way \
|
||||||
|
down their page); Begin exports with a title page adds a title page \
|
||||||
|
in front, built from the title/author/contact fields there.",
|
||||||
|
);
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"Tick Screenplay (Fountain) in Manuscript details to make the \
|
||||||
|
project a screenplay instead: each file's body is read as Fountain, \
|
||||||
|
and Export ODT becomes Export PDF — a conventionally paginated \
|
||||||
|
screenplay, joined into one continuous script across files.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_projects_and_templates(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Projects & templates");
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"File ▸ ✨ New project… scaffolds a whole project from a template \
|
||||||
|
(the bundled “snowflake” layout — premise, synopsis, story bible, \
|
||||||
|
outline, first draft, revisions, final — by default, compiled into \
|
||||||
|
the binary so nothing needs installing alongside it) and opens it \
|
||||||
|
straight into its drafting folder.",
|
||||||
|
);
|
||||||
|
note(
|
||||||
|
ui,
|
||||||
|
"Settings ▸ New-project settings… points Template at an external \
|
||||||
|
folder with its own cookiecutter.json to use instead — blank uses \
|
||||||
|
the bundled one, and a broken override falls back to it rather than \
|
||||||
|
failing project creation. Manuscript folder sets which project \
|
||||||
|
subfolder is the book (default 05-First Draft).",
|
||||||
|
);
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"Tick Publish to Gitea after creation there (with a server URL, user \
|
||||||
|
and token filled in) to have a new project pushed to a fresh Gitea \
|
||||||
|
repository automatically; Settings ▸ Git remote… does the same for \
|
||||||
|
a workspace you already have.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_proofing(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Proofing");
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"Spelling is checked live, offline, as you type — no server, no \
|
||||||
|
network. Right-click an underlined word for corrections, or to add \
|
||||||
|
it to Settings ▸ Word list…, which also offers 👤 Add character \
|
||||||
|
names to pull in your whole cast at once. Canadian and British \
|
||||||
|
English are built in; pick one from the Spelling row's dropdown.",
|
||||||
|
);
|
||||||
|
note(
|
||||||
|
ui,
|
||||||
|
"Settings ▸ LanguageTool… connects a grammar-and-style server (a \
|
||||||
|
local instance keeps your manuscript off the network). Press ✓ \
|
||||||
|
Check to run it on the open file — its results take over the \
|
||||||
|
underlines until you next edit, then the offline spell checker \
|
||||||
|
resumes.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_plot_beats(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Plot beats (Mistral)");
|
||||||
|
body(
|
||||||
|
ui,
|
||||||
|
"Tools ▸ ✨ Generate plot beats (Mistral)… turns a rough proposal \
|
||||||
|
file (characters, setting, a loose summary) into three-act plot \
|
||||||
|
beats, using the Mistral API. Set an API key first in Settings ▸ \
|
||||||
|
Mistral…. Results open in a window to edit, save as a new file, or \
|
||||||
|
copy.",
|
||||||
|
);
|
||||||
|
note(
|
||||||
|
ui,
|
||||||
|
"If the proposal's acts are already partly beaten out (three or more \
|
||||||
|
numbered beats under a heading counts as drafted), the generator \
|
||||||
|
writes only the missing acts instead of a whole sheet, treating the \
|
||||||
|
drafted ones as canon to work backwards from.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn guide_settings_reference(ui: &mut egui::Ui) {
|
||||||
|
section(ui, "Settings, at a glance");
|
||||||
|
entries(
|
||||||
|
ui,
|
||||||
|
&[
|
||||||
|
("LanguageTool…", "Grammar/spelling server connection (scheme, host, port, token, language)."),
|
||||||
|
("Mistral…", "API key, model and base URL for plot-beat generation."),
|
||||||
|
("New-file template…", "The frontmatter + New from template seeds a file with."),
|
||||||
|
("New-project settings…", "Template override, manuscript folder name, Gitea publishing defaults."),
|
||||||
|
("Git remote…", "Attach (or create on Gitea) the current workspace's remote."),
|
||||||
|
("Manuscript details…", "Title/author/contact, standard format, title page, screenplay toggle."),
|
||||||
|
("Spelling…", "The word list — names and invented terms the checker accepts."),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
note(
|
||||||
|
ui,
|
||||||
|
"All settings live in ~/.config/md-manuscript/config.json and apply \
|
||||||
|
machine-wide; per-workspace data (order, titles, word list, word \
|
||||||
|
log) is committed alongside the manuscript in the workspace itself.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn cheatsheet_body(ui: &mut egui::Ui) {
|
fn cheatsheet_body(ui: &mut egui::Ui) {
|
||||||
intro(
|
intro(
|
||||||
ui,
|
ui,
|
||||||
@@ -235,3 +599,20 @@ fn syntax(ui: &mut egui::Ui, id: &str, rows: &[(&str, &str)]) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A `label`/description list, stacked (label, then a wrapped paragraph)
|
||||||
|
/// rather than side by side — for descriptions too long to sit in
|
||||||
|
/// `syntax`'s two-column grid without either overflowing or forcing the
|
||||||
|
/// whole window wider to avoid wrapping, since a `Grid` sizes each column to
|
||||||
|
/// its widest cell instead of wrapping.
|
||||||
|
fn entries(ui: &mut egui::Ui, rows: &[(&str, &str)]) {
|
||||||
|
for (label, desc) in rows {
|
||||||
|
ui.label(
|
||||||
|
egui::RichText::new(*label)
|
||||||
|
.monospace()
|
||||||
|
.color(egui::Color32::from_rgb(120, 170, 120)),
|
||||||
|
);
|
||||||
|
ui.label(*desc);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user