Function EXAMPLE blocks now render as their own fish fence titled
"Examples" (matching the existing "Usage" title on the Synopsis fence),
triggered by a flat Example: label line mirroring the Synopsis: prefix.
Prose pages get two new generic titling signals in _render_para: a bare
indented path ending in a known extension is titled by its basename, and
a leading "# in <file>" / "# <file>" comment on a shell paragraph is
promoted to the fence title and stripped from the body. This picks up
local.fish/secrets.fish path displays and override examples in
07-customization.md for free, plus a bonus .logging_disabled hit.
10-personalization.md's secrets.fish block gets an explicit "# secrets.fish"
comment to title it the same way. The four local.fish examples keep their
existing descriptive comments rather than a redundant local.fish title.
Function documentation now comes from functions/*.fish comment headers;
everything else stays in docs/manual/**. Records that split in the three
places a contributor looks:
- AGENTS.md "Documentation Policy" and Coding Convention #4, which now
spells out the full label set and flags CATEGORY as required-to-publish.
- Manual section 11, which pointed readers at docs/manual/ for everything.
- README, same.
The man-page-style comment header above each function in functions/*.fish
becomes the SSOT for that function's documentation. Writing a new function
and documenting it are now the same act.
- manualtools.parse_functions() parses every header carrying a # CATEGORY;
absence of one is the opt-in, keeping bundled-plugin and prompt internals
out of the manual with no exclusion list to maintain.
- build-manual.py generates entries for both --concat and --site, with
**Dependencies:** rendered as links and a **Used by:** reverse index
computed in one pass. Cross-category links are the navigation win.
- docs/manual/05-functions/*.md reduced to frontmatter-only stubs. Every
intro measured zero words, so the category files were pure entry
containers; ordering, titles, and helpKeywords routing are untouched.
- _first_sentence() unwraps the leading hard-wrapped paragraph and skips
the whole Synopsis block, not just its label line. Site cards no longer
truncate mid-clause or show a synopsis as their description.
Verification, per the design spec:
- test_concat_roundtrips_original scoped to sections 0-4 and 6-11. It
guarded a format migration; this is a content migration.
- replaced by structural checks: one entry per categorised function, the
required sections present, every category resolving to a stub with no
stub empty, and every declared dependency resolving to a real function
or a type -q-guarded binary.
- public functions lacking # CATEGORY warn rather than fail, so a new
user-facing function going undocumented stays visible in CI.
24/24 checks pass. 94 entries generated from 94 parsed headers.
Also drops a stale claim from open-url's NOTES: config-help --html calls
xdg-open directly and has never called open-url.
docs/manual/** plus the Astro Starlight site (https://fish-config-docs.pages.dev/)
replace the Gitea wiki (docs/wiki/) and chunked offline HTML (docs/html/,
docs/html-style.html) as the published documentation surface. Retires the
now-unused docs/split-wiki.py and docs/split-manual.py generators alongside them.
- config-help --html now opens the published site root instead of resolving
a local sitemap anchor; when a keyword was given it prints a note that deep
links aren't available yet and to use the site's search box.
- open-url and docs/manual/05-functions/14-miscellaneous.md examples
repointed from docs/html/index.html to the site URL.
- docs/manual/11-viewing-this-manual.md rewritten to document the four
access paths: the website, the man page, in-terminal pager, and reading
docs/manual/** directly. fish-config.index updated to match the new
headings.
- README.md documentation section and Zoxide attribution link repointed at
the site; corrected the stale "single source file" claim about
fish-config.md.
- Regenerated docs/fish-config.md via build-manual.py --concat.
index.md is both the man-page LANDING section and a Starlight content
page. Astro errors on any frontmatter key outside the fixed
man/site/manTitle/helpKeywords schema, so folding the source
fish-config.md pandoc header (title/section/header/date/author) onto
index.md under a fifth "pandoc" key would break the docs-site build
the moment it's scaffolded.
Relocate that block to docs/manual/_pandoc.yml: a plain, fence-free
YAML file that Astro content collections ignore (leading underscore).
split-manual.py now extracts it as raw text (no yaml.safe_load/
safe_dump round-trip) so build-manual.py's --concat re-emits it
byte-for-byte instead of merely "verbatim" in comment only. Also guard
build_concat against a manual/ tree with no _pandoc.yml/index.md,
removing the unconditional index.md parse that previously raised
FileNotFoundError on such a tree.
Regenerated docs/manual/ via split-manual.py; concat output remains
byte-identical to the pre-migration docs/fish-config.md.
Adds docs/build-manual.py (--concat) and a round-trip test in
verify-manual.py that reproduces the pre-migration fish-config.md
exactly from docs/manual/.
Fixes found by the round-trip check, applied in split-manual.py and
re-run to regenerate docs/manual/:
- NAME/SYNOPSIS/TABLE OF CONTENTS had no sidebar.order, so they sorted
after every numbered section instead of interleaving with DESCRIPTION
in original document order. All manual pages now get sidebar.order
from a single position counter matching source order.
- split_h1/split_h2 used .strip() on section bodies, which also ate
leading indentation on the first body line, corrupting the 4-space
indented code blocks that open SYNOPSIS and TABLE OF CONTENTS.
- The source's leading pandoc metadata block (title/section/header/
date/author) was discarded entirely by the splitter. It's now parsed
off via manualtools.parse and stashed on index.md under a "pandoc"
key; build-manual.py re-emits it verbatim ahead of the first heading.