diff --git a/README.md b/README.md index f3713e4..22fdf30 100644 --- a/README.md +++ b/README.md @@ -146,9 +146,12 @@ Contributing to the docs? There are two sources, split by content type: above each function in `functions/*.fish`. Edit the function; the entry and its site page are generated from the header. - **Everything else** lives under `docs/manual/**`. +- **Testing, Contributing, Attribution, and License** are pulled straight + from this README (the sections below) rather than authored twice — edit + them here and the manual, man page, and site all pick up the change. -Never edit the generated `docs/fish-config.md` — it's rebuilt from both -sources and any hand-edits are discarded. +Never edit the generated `docs/fish-config.md` — it's rebuilt from all +three sources and any hand-edits are discarded. To browse the docs from the terminal: @@ -348,6 +351,14 @@ Interested in contributing? See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the branching/PR workflow, commit conventions, fish coding standards, and the docs/testing pipeline this repo follows. +**Preferred forge:** [git.rootiest.dev/rootiest/fish-config](https://git.rootiest.dev/rootiest/fish-config) +is the base repository. [github.com/rootiest/fish-config](https://github.com/rootiest/fish-config) +is a push-mirror of it — identical content, but one-way and read-only from a +contributor's perspective. Branches, forks, and merges made on the GitHub +side aren't fed back upstream, so they risk being silently overwritten by +the next mirror push. Until two-way sync exists, please fork, branch, and +open issues/PRs from the Gitea repository rather than the GitHub mirror. + --- ## Attribution diff --git a/docs/build-manual.py b/docs/build-manual.py index e4b81ad..b383eea 100644 --- a/docs/build-manual.py +++ b/docs/build-manual.py @@ -23,6 +23,8 @@ DOCS = Path(__file__).parent MANUAL = DOCS / "manual" FUNCTIONS = DOCS.parent / "functions" COMPLETIONS = DOCS.parent / "completions" +README = DOCS.parent / "README.md" +REPO_BLOB_BASE = "https://git.rootiest.dev/rootiest/fish-config/src/branch/main/" SLUG_DIR = "reference" # File-tree branches whose real directory contents get listed inline on the @@ -80,10 +82,104 @@ def _with_abbreviations(body: str, abbrs: dict[str, list[dict]]) -> str: for cat, table in rendered_abbrs.items(): placeholder = f"" body = body.replace(placeholder, table) - + return body +TOC_PLACEHOLDER = "" +TOC_SKIP_STEMS = {"index"} + + +def _build_toc(root: Path) -> str: + """Render the section list for docs/manual/00-table-of-contents.md. + + Walks the same tree `build_concat` does, so it can never drift from the + man page's actual section order. `index.md` and the `00-*` front-matter + pages (Name, Synopsis, this page) sit before section 1 and are excluded, + same as any `man: false` page (currently only 404). + """ + lines: list[str] = [] + n = 0 + for path, depth in mt.walk(root): + rel = path.relative_to(root) + # len(rel.parts) == 1 means a root-level file, not a directory's own + # index page (e.g. 04-abbreviations/index.md), which must keep its + # own numbered line even though its stem is also "index". + if depth == 0 and len(rel.parts) == 1 and (rel.stem in TOC_SKIP_STEMS or rel.stem.startswith("00-")): + continue + fm, _ = mt.parse(path) + if not fm.get("man", True): + continue + title = fm.get("title", path.stem) + if depth == 0: + n += 1 + lines.append(f" {n}. {title}") + else: + lines.append(f" - {title}") + return "\n".join(lines) + + +def _with_toc(body: str, root: Path) -> str: + """Inject the `` placeholder with the built section list.""" + return body.replace(TOC_PLACEHOLDER, _build_toc(root)) if TOC_PLACEHOLDER in body else body + + +README_LINK_RE = re.compile(r"\]\((?!https?://|#|mailto:)([^)]+)\)") +README_FENCE_RE = re.compile(r"```[^\n]*\n(.*?)```\n?", re.DOTALL) +README_PLACEHOLDER_RE = re.compile(r"") + + +def _rewrite_repo_links(text: str) -> str: + """Point a README-relative link (`CONTRIBUTING.md`, `LICENSE`) at its file on Gitea.""" + return README_LINK_RE.sub(lambda m: f"]({REPO_BLOB_BASE}{m.group(1)})", text) + + +def _defence(text: str) -> str: + """Rewind a README fenced code block into the manual's indented-block form. + + `docs/manual` bodies are authored man-page style (4-space indent), never + fenced: `codespans`/pandoc pair backticks per line, and a fence line's + triple backtick throws that count off. README.md is ordinary markdown + and fences its examples, so an injected section is converted back. + """ + def repl(m: re.Match) -> str: + block = m.group(1).rstrip("\n") + return "\n".join(" " + line for line in block.split("\n")) + "\n" + + return README_FENCE_RE.sub(repl, text) + + +@functools.lru_cache(maxsize=1) +def _readme_sections() -> dict[str, str]: + """Split README.md into {H2 heading: body}, links rewritten to point at the repo. + + Lets a manual stub pull one README section in verbatim via a + `` placeholder, so the README stays the single + source of truth for sections that describe the repo itself rather than + the shell config (Testing, Contributing, Attribution, License). + """ + sections: dict[str, str] = {} + heading: str | None = None + lines: list[str] = [] + for line in README.read_text().split("\n") + ["## "]: + if line.startswith("## "): + if heading is not None: + body = "\n".join(lines).strip() + if body.endswith("---"): + body = body[:-3].rstrip() + sections[heading] = _defence(_rewrite_repo_links(body)) + heading = line[3:].strip() + lines = [] + else: + lines.append(line) + return sections + + +def _with_readme(body: str) -> str: + """Inject `` placeholders with that README section's body.""" + return README_PLACEHOLDER_RE.sub(lambda m: _readme_sections().get(m.group(1), ""), body) + + def build_concat(root: Path) -> str: """Concatenate the manual into one ordered markdown document. @@ -123,6 +219,8 @@ def build_concat(root: Path) -> str: elif "04-abbreviations" in path.parts: abbrs = mt.parse_abbreviations(DOCS.parent / "conf.d") body = _with_abbreviations(body, abbrs) + body = _with_readme(body) + body = _with_toc(body, root) if body: body = re.sub(r"\n*", "", body, flags=re.DOTALL) body = re.sub(r"\n*", "", body, flags=re.DOTALL) @@ -749,6 +847,7 @@ def build_site(root: Path, out: Path) -> list[dict]: if "04-abbreviations" in path.parts: abbrs = mt.parse_abbreviations(DOCS.parent / "conf.d") body = _with_abbreviations(body, abbrs) + body = _with_readme(body) target.parent.mkdir(parents=True, exist_ok=True) body = _inject_subheading_cards(body) _write_prettified(target, _page_fm(fm), prettify(body)) diff --git a/docs/fish-config.index b/docs/fish-config.index index f222056..b20aa0f 100644 --- a/docs/fish-config.index +++ b/docs/fish-config.index @@ -403,4 +403,23 @@ site=## The documentation website source=## Reading the source directly raw-source=## Reading the source directly +# ── Section 14: Testing ─────────────────────────────────────── +testing=# 14. TESTING +tests=# 14. TESTING + +# ── Section 15: Contributing ────────────────────────────────── +contributing=# 15. CONTRIBUTING +contribute=# 15. CONTRIBUTING +forge=# 15. CONTRIBUTING + +# ── Section 16: Attribution ─────────────────────────────────── +attribution=# 16. ATTRIBUTION +credits=# 16. ATTRIBUTION + +# ── Section 17: License ─────────────────────────────────────── +license=# 17. LICENSE +licensing=# 17. LICENSE +agpl=# 17. LICENSE +copyright=# 17. LICENSE + diff --git a/docs/fish-config.md b/docs/fish-config.md index da0ede4..2dccaed 100644 --- a/docs/fish-config.md +++ b/docs/fish-config.md @@ -82,52 +82,54 @@ The configuration uses a structured file tree: # TABLE OF CONTENTS - 1. Configuration Variables - 2. PATH Setup - 3. Key Bindings - 4. Abbreviations - 4.1 Editors - 4.2 Navigation and Listing - 4.3 Git - 4.4 Terminal Windows, Tabs, and Panes - 4.5 Chezmoi - 4.6 Docker - 4.7 Systemctl - 4.8 AI Assistants - 4.9 History Expansion - 4.10 Miscellaneous - 4.11 Shell Aliases - 5. Functions Reference - 5.1 File and Directory - 5.2 Navigation - 5.3 Editors and Viewers - 5.4 Git and Version Control - 5.5 Package Management - 5.6 Dependency Management - 5.7 System and Monitoring - 5.8 Terminal Management - 5.9 Clipboard - 5.10 Network - 5.11 Pager and Logging - 5.12 AI and Developer Tools - 5.13 Media and Utilities - 5.14 Miscellaneous - 6. Dependency Catalog - 7. Customization - 8. Fisher Plugins - 9. Installation - 10. Personalization - 11. Troubleshooting - 11.1 Uninstalling and Reverting to Backup - 11.2 Fish Version Requirement - 11.3 Enable or Disable Session Logging - 11.4 Change or Disable the Greeting - 11.5 Secrets and Machine-Local Configuration - 11.6 Tool Init Does Nothing (Return Sentinel) - 11.7 Missing Dependencies - 11.8 Vi Mode Keybindings - 11.9 What's with the C1-C6 stuff? - 12. Viewing This Manual + 1. Configuration Variables + 2. PATH Setup + 3. Key Bindings + 4. Abbreviations + - Editors + - Navigation and Listing + - Git + - Terminal Windows, Tabs, and Panes + - Chezmoi + - Docker + - Systemctl + - AI Assistants + - History Expansion + - Miscellaneous + - Shell Aliases + 5. Functions Reference + - File and Directory + - Navigation + - Editors and Viewers + - Git and Version Control + - Package Management + - Dependency Management + - System and Monitoring + - Terminal Management + - Clipboard + - Network + - Pager and Logging + - AI and Developer Tools + - Media and Utilities + - Miscellaneous + 6. Dependency Catalog + 7. Customization + 8. Components Reference + - C1 — Command Shadows + - C2 — Startup Side-Effects + - C3 — Key and Environment Overrides + - C4 — Terminal and Tool Integration + - C5 — Logging and Capture + - C6 — Greeting and First-Run UI + 9. Fisher Plugins + 10. Installation + 11. Personalization + 12. Troubleshooting + 13. Viewing This Manual + 14. Testing + 15. Contributing + 16. Attribution + 17. License --- @@ -4309,3 +4311,34 @@ to correct its documentation, open the function itself: The files under `docs/manual/05-functions/` carry only the category titles, ordering, and search keywords. + +# 14. TESTING + + fish tests/run-tests.fish + +Runs before every push (and gates the [documentation build](https://git.rootiest.dev/rootiest/fish-config/src/branch/main/.github/workflows/ci.yml) in CI, so a broken config can't get published): syntax-lints every `.fish` file, then loads the config in an isolated `HOME`/XDG sandbox — never this checkout itself, since it doubles as a real `~/.config/fish` — and runs functional checks against foundational behavior (XDG/PATH/CDPATH setup, key bindings, abbreviations, core functions, the opinionated-component registry, and more). + +# 15. CONTRIBUTING + +Interested in contributing? See [`CONTRIBUTING.md`](https://git.rootiest.dev/rootiest/fish-config/src/branch/main/CONTRIBUTING.md) for the +branching/PR workflow, commit conventions, fish coding standards, and the +docs/testing pipeline this repo follows. + +**Preferred forge:** [git.rootiest.dev/rootiest/fish-config](https://git.rootiest.dev/rootiest/fish-config) +is the base repository. [github.com/rootiest/fish-config](https://github.com/rootiest/fish-config) +is a push-mirror of it — identical content, but one-way and read-only from a +contributor's perspective. Branches, forks, and merges made on the GitHub +side aren't fed back upstream, so they risk being silently overwritten by +the next mirror push. Until two-way sync exists, please fork, branch, and +open issues/PRs from the Gitea repository rather than the GitHub mirror. + +# 16. ATTRIBUTION + +The core of the [Zoxide integration](https://fish.rootiest.fyi/02-path-setup/) in this repository was originally adapted from the [icezyclon/zoxide.fish](https://github.com/icezyclon/zoxide.fish) plugin (MIT Licensed) and has since been heavily customized for performance and Fish 4.x compatibility. + +# 17. LICENSE + +Copyright (C) 2026 Rootiest + +This project is licensed under the **GNU Affero General Public License v3.0 or later** (AGPLv3+). +See the [LICENSE](https://git.rootiest.dev/rootiest/fish-config/src/branch/main/LICENSE) file for the full license text. diff --git a/docs/manual/00-table-of-contents.md b/docs/manual/00-table-of-contents.md index d79409c..df73cab 100644 --- a/docs/manual/00-table-of-contents.md +++ b/docs/manual/00-table-of-contents.md @@ -7,51 +7,6 @@ sidebar: order: 4 --- - 1. Configuration Variables - 2. PATH Setup - 3. Key Bindings - 4. Abbreviations - 4.1 Editors - 4.2 Navigation and Listing - 4.3 Git - 4.4 Terminal Windows, Tabs, and Panes - 4.5 Chezmoi - 4.6 Docker - 4.7 Systemctl - 4.8 AI Assistants - 4.9 History Expansion - 4.10 Miscellaneous - 4.11 Shell Aliases - 5. Functions Reference - 5.1 File and Directory - 5.2 Navigation - 5.3 Editors and Viewers - 5.4 Git and Version Control - 5.5 Package Management - 5.6 Dependency Management - 5.7 System and Monitoring - 5.8 Terminal Management - 5.9 Clipboard - 5.10 Network - 5.11 Pager and Logging - 5.12 AI and Developer Tools - 5.13 Media and Utilities - 5.14 Miscellaneous - 6. Dependency Catalog - 7. Customization - 8. Fisher Plugins - 9. Installation - 10. Personalization - 11. Troubleshooting - 11.1 Uninstalling and Reverting to Backup - 11.2 Fish Version Requirement - 11.3 Enable or Disable Session Logging - 11.4 Change or Disable the Greeting - 11.5 Secrets and Machine-Local Configuration - 11.6 Tool Init Does Nothing (Return Sentinel) - 11.7 Missing Dependencies - 11.8 Vi Mode Keybindings - 11.9 What's with the C1-C6 stuff? - 12. Viewing This Manual + --- diff --git a/docs/manual/14-testing.md b/docs/manual/14-testing.md new file mode 100644 index 0000000..119aeb2 --- /dev/null +++ b/docs/manual/14-testing.md @@ -0,0 +1,13 @@ +--- +title: Testing +manTitle: 14. TESTING +sidebar: + order: 18 +helpKeywords: +- testing +- tests +- test-suite +- run-tests +--- + + diff --git a/docs/manual/15-contributing.md b/docs/manual/15-contributing.md new file mode 100644 index 0000000..e026074 --- /dev/null +++ b/docs/manual/15-contributing.md @@ -0,0 +1,15 @@ +--- +title: Contributing +manTitle: 15. CONTRIBUTING +sidebar: + order: 19 +helpKeywords: +- contributing +- contribute +- pull-request +- fork +- issues +- forge +--- + + diff --git a/docs/manual/16-attribution.md b/docs/manual/16-attribution.md new file mode 100644 index 0000000..34522fd --- /dev/null +++ b/docs/manual/16-attribution.md @@ -0,0 +1,12 @@ +--- +title: Attribution +manTitle: 16. ATTRIBUTION +sidebar: + order: 20 +helpKeywords: +- attribution +- credits +- zoxide +--- + + diff --git a/docs/manual/17-license.md b/docs/manual/17-license.md new file mode 100644 index 0000000..bc9a775 --- /dev/null +++ b/docs/manual/17-license.md @@ -0,0 +1,13 @@ +--- +title: License +manTitle: 17. LICENSE +sidebar: + order: 21 +helpKeywords: +- license +- licensing +- agpl +- copyright +--- + + diff --git a/docs/site/astro.config.mjs b/docs/site/astro.config.mjs index 98f8ded..6e664a5 100644 --- a/docs/site/astro.config.mjs +++ b/docs/site/astro.config.mjs @@ -28,6 +28,11 @@ export default defineConfig({ label: 'Gitea', href: 'https://git.rootiest.dev/rootiest/fish-config', }, + { + icon: 'github', + label: 'GitHub', + href: 'https://github.com/rootiest/fish-config', + }, ], components: { SocialIcons: './src/components/starlight/SocialIcons.astro',