Skip to main content

git_lfs/
man.rs

1//! Per-subcommand documentation extras (man pages + mdbook).
2//!
3//! The clap derive in [`crate::args`] is the source of truth for the
4//! NAME / SYNOPSIS / OPTIONS surface — xtask renders that automatically
5//! into both groff (man pages) and markdown (mdbook). This module owns
6//! everything richer: DESCRIPTION prose, EXAMPLES, NOTES, FILES,
7//! SEE ALSO.
8//!
9//! **Bodies are authored in markdown.** xtask passes them through
10//! verbatim for the markdown output and converts them to groff for the
11//! man pages, so a single source feeds both formats. The supported
12//! markdown vocabulary is intentionally small — paragraphs, bold/italic,
13//! code spans / fenced code blocks, bulleted and numbered lists. Stick
14//! to that and the groff conversion stays predictable.
15//!
16//! Each subcommand exposes its extras here as a [`ManContent`] entry in
17//! [`extras_for`]. Bodies live under `cli/man/<sub>/*.md` and are pulled
18//! in via [`include_str!`], keeping prose out of `man.rs`.
19//!
20//! Onboarding a new section is two-step:
21//! 1. Drop one or more `.md` files into `cli/man/<subcommand>/`.
22//! 2. Add a match arm in [`extras_for`] referencing them.
23//!
24//! Subcommands without an entry get the auto-generated page with no
25//! extras — still useful, just shorter.
26
27/// Hand-authored extras for a single command's documentation. Returned
28/// by [`extras_for`] keyed on the subcommand name (or `""` for the top-
29/// level `git-lfs` page). Both fields are markdown — xtask renders them
30/// to either groff or markdown depending on output format.
31#[derive(Debug)]
32pub struct ManContent {
33    /// Replaces the auto-generated DESCRIPTION (which is just the short
34    /// `about` from the clap derive). Markdown.
35    pub description: Option<&'static str>,
36
37    /// Sections appended after OPTIONS, in order. Each entry is
38    /// `(title, markdown body)`. Conventional titles: `EXAMPLES`,
39    /// `FILES`, `ENVIRONMENT`, `NOTES`, `BUGS`, `SEE ALSO`. The title
40    /// becomes a `.SH` in groff and a top-level `##` in markdown.
41    pub extra_sections: &'static [(&'static str, &'static str)],
42}
43
44impl ManContent {
45    pub const fn empty() -> Self {
46        Self {
47            description: None,
48            extra_sections: &[],
49        }
50    }
51}
52
53const EMPTY: ManContent = ManContent::empty();
54
55/// Look up the doc extras for `subcommand` (e.g. `"fetch"`,
56/// `"checkout"`). Pass `""` for the top-level `git-lfs` page.
57/// Returns a reference to [`ManContent::empty`] when there's no entry,
58/// so the caller can always splice unconditionally.
59pub fn extras_for(_subcommand: &str) -> &'static ManContent {
60    // No entries yet. As we author content, replace this with a
61    // match on `subcommand`:
62    //
63    //     match subcommand {
64    //         "fetch" => &FETCH_DOCS,
65    //         "checkout" => &CHECKOUT_DOCS,
66    //         _ => &EMPTY,
67    //     }
68    &EMPTY
69}