feat(docs): GitHub mirror icon, README-sourced doc sections, auto-generated TOC #129
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -84,6 +86,100 @@ def _with_abbreviations(body: str, abbrs: dict[str, list[dict]]) -> str:
|
||||
return body
|
||||
|
||||
|
||||
TOC_PLACEHOLDER = "<!-- GENERATED: toc -->"
|
||||
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 `<!-- GENERATED: toc -->` 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"<!-- README: (.+?) -->")
|
||||
|
||||
|
||||
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
|
||||
`<!-- README: <Heading> -->` 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 `<!-- README: Heading -->` 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"<LinkButton.*?</LinkButton>\n*", "", body, flags=re.DOTALL)
|
||||
body = re.sub(r"<CardGrid.*?</CardGrid>\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))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
+72
-39
@@ -86,48 +86,50 @@ The configuration uses a structured file tree:
|
||||
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
|
||||
- Editors
|
||||
- Navigation and Listing
|
||||
- Git
|
||||
- Terminal Windows, Tabs, and Panes
|
||||
- Chezmoi
|
||||
- Docker
|
||||
- Systemctl
|
||||
- AI Assistants
|
||||
- History Expansion
|
||||
- Miscellaneous
|
||||
- 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
|
||||
- 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. 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
|
||||
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.
|
||||
|
||||
@@ -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
|
||||
<!-- GENERATED: toc -->
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Testing
|
||||
manTitle: 14. TESTING
|
||||
sidebar:
|
||||
order: 18
|
||||
helpKeywords:
|
||||
- testing
|
||||
- tests
|
||||
- test-suite
|
||||
- run-tests
|
||||
---
|
||||
|
||||
<!-- README: Testing -->
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Contributing
|
||||
manTitle: 15. CONTRIBUTING
|
||||
sidebar:
|
||||
order: 19
|
||||
helpKeywords:
|
||||
- contributing
|
||||
- contribute
|
||||
- pull-request
|
||||
- fork
|
||||
- issues
|
||||
- forge
|
||||
---
|
||||
|
||||
<!-- README: Contributing -->
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Attribution
|
||||
manTitle: 16. ATTRIBUTION
|
||||
sidebar:
|
||||
order: 20
|
||||
helpKeywords:
|
||||
- attribution
|
||||
- credits
|
||||
- zoxide
|
||||
---
|
||||
|
||||
<!-- README: Attribution -->
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: License
|
||||
manTitle: 17. LICENSE
|
||||
sidebar:
|
||||
order: 21
|
||||
helpKeywords:
|
||||
- license
|
||||
- licensing
|
||||
- agpl
|
||||
- copyright
|
||||
---
|
||||
|
||||
<!-- README: License -->
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user