docs: migrate the manual to a Starlight documentation site #72
@@ -5,7 +5,11 @@ on:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "docs/fish-config.md"
|
||||
- "docs/manual/**"
|
||||
- "docs/build-manual.py"
|
||||
- "docs/manualtools.py"
|
||||
- "docs/verify-manual.py"
|
||||
- "docs/site/**"
|
||||
|
||||
jobs:
|
||||
build-docs:
|
||||
@@ -16,8 +20,24 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
- name: Install pandoc
|
||||
run: sudo apt-get update -qq && sudo apt-get install -y pandoc
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y pandoc python3-yaml
|
||||
|
||||
- name: Generate concatenated markdown
|
||||
run: python3 docs/build-manual.py --concat -o docs/fish-config.md
|
||||
|
||||
# Regeneration MUST run before verification: verify-manual.py's
|
||||
# test_concat_roundtrips_original compares a freshly-built concat
|
||||
# against docs/fish-config.md on disk. Before this step ran, that
|
||||
# file was still the stale pre-push copy, so any ordinary edit under
|
||||
# docs/manual/** failed the round-trip check before anything was
|
||||
# regenerated. Do not reorder this back — verification still gates
|
||||
# pandoc and the auto-commit below, it just no longer requires a
|
||||
# contributor to hand-sync the generated file before pushing.
|
||||
- name: Verify manual integrity
|
||||
run: python3 docs/verify-manual.py
|
||||
|
||||
- name: Compile man page
|
||||
run: |
|
||||
@@ -27,22 +47,33 @@ jobs:
|
||||
docs/fish-config.md \
|
||||
-o docs/fish-config.1
|
||||
|
||||
- name: Generate chunked HTML docs
|
||||
run: |
|
||||
rm -rf docs/html/
|
||||
pandoc -f gfm -t chunkedhtml --split-level=1 --toc \
|
||||
--include-in-header docs/html-style.html \
|
||||
docs/fish-config.md \
|
||||
-o docs/html/
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
|
||||
- name: Generate wiki markdown
|
||||
run: python3 docs/split-wiki.py
|
||||
- name: Build documentation site
|
||||
run: |
|
||||
python3 docs/build-manual.py --site
|
||||
cd docs/site
|
||||
npm ci
|
||||
npx astro build
|
||||
|
||||
- name: Deploy to Cloudflare Pages
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
run: |
|
||||
cd docs/site
|
||||
npx --yes wrangler pages deploy dist/ \
|
||||
--project-name=fish-config-docs \
|
||||
--branch=main
|
||||
|
||||
- name: Commit generated docs
|
||||
run: |
|
||||
git config user.name "Gitea Actions"
|
||||
git config user.email "actions@gitea"
|
||||
git add docs/fish-config.1 docs/html/ docs/wiki/
|
||||
git add docs/fish-config.md docs/fish-config.1
|
||||
git diff --cached --quiet && echo "No changes to commit" && exit 0
|
||||
git commit -m "chore(docs): regenerate man page, HTML docs, and wiki"
|
||||
git commit -m "chore(docs): regenerate manual and man page"
|
||||
git push
|
||||
|
||||
@@ -300,3 +300,10 @@ docs/devlogs
|
||||
# ────────────────────────────────────────────────────────
|
||||
/.cache_ggshield
|
||||
user-dots
|
||||
|
||||
# ──────────────────── Generated Docs Site ───────────────────
|
||||
docs/site/node_modules/
|
||||
docs/site/dist/
|
||||
docs/site/.astro/
|
||||
docs/site/src/content/docs/
|
||||
docs/site/src/sidebar.json
|
||||
|
||||
@@ -5,6 +5,8 @@ built around a Catppuccin Mocha aesthetic with a curated set of modern
|
||||
CLI tool integrations, smart shell functions, and a heavily customized
|
||||
abbreviation system for keyboard-driven workflows.
|
||||
|
||||
📖 **[Documentation site](https://fish-config-docs.pages.dev/)**
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
@@ -118,11 +120,16 @@ the watcher inert without uninstalling it.
|
||||
|
||||
## Documentation
|
||||
|
||||
### [📖 Full Documentation Wiki](docs/wiki/index.md)
|
||||
### [📖 Documentation Site](https://fish-config-docs.pages.dev/)
|
||||
|
||||
A multi-page Markdown wiki auto-generated from the single source file `docs/fish-config.md`
|
||||
on every push to `main`. It covers configuration variables, key bindings, abbreviations,
|
||||
all functions, the dependency catalog, customization, and more.
|
||||
A Starlight-powered site generated from `docs/manual/**` — the single source
|
||||
of truth — on every push to `main`. It covers configuration variables, key
|
||||
bindings, abbreviations, all functions, the dependency catalog, customization,
|
||||
and more, with full-text search.
|
||||
|
||||
Contributing to the docs? Edit files under `docs/manual/**`, never the
|
||||
generated `docs/fish-config.md` — it's rebuilt from the manual tree and any
|
||||
hand-edits are discarded.
|
||||
|
||||
To browse the docs from the terminal:
|
||||
|
||||
@@ -130,8 +137,7 @@ To browse the docs from the terminal:
|
||||
|---|---|
|
||||
| `help config` | Open the terminal manual in the best available pager |
|
||||
| `help config <keyword>` | Jump directly to a section matching the keyword |
|
||||
| `help config --html` | Open the pre-built HTML docs in the default browser |
|
||||
| `help config <keyword> --html` | Open HTML docs at the matching section anchor |
|
||||
| `help config --html` | Open the documentation site in the default browser |
|
||||
| `help config --man` | Open the compiled man page via `man -l` |
|
||||
| `help config <keyword> --man` | Open the man page jumping to the nearest match |
|
||||
| `repo-open` | Open this repo's web page in the browser (deep-links to the current branch and sub-directory) |
|
||||
@@ -298,7 +304,7 @@ Command shadows react immediately; bindings, prompt, and abbreviations take effe
|
||||
|
||||
## Attribution
|
||||
|
||||
The core of the [Zoxide integration](docs/wiki/2-path-setup.md) 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.
|
||||
The core of the [Zoxide integration](https://fish-config-docs.pages.dev/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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,376 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Generate publishable artifacts from the docs/manual SSOT.
|
||||
|
||||
--concat one ordered markdown document for pandoc / config-help
|
||||
--site Starlight content tree + sidebar.json
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import manualtools as mt
|
||||
|
||||
DOCS = Path(__file__).parent
|
||||
MANUAL = DOCS / "manual"
|
||||
|
||||
|
||||
def build_concat(root: Path) -> str:
|
||||
"""Concatenate the manual into one ordered markdown document.
|
||||
|
||||
Each file contributes `# {manTitle or title}` at a level matching its
|
||||
depth, and its body headings are demoted by the same amount.
|
||||
|
||||
`root / "_pandoc.yml"` (if present) holds the original document's
|
||||
pandoc metadata block (title/section/header/date/author) as raw text,
|
||||
with no frontmatter fences and no Astro-visible frontmatter key. When
|
||||
present, its contents are re-emitted byte-for-byte as the leading
|
||||
`---`-fenced block, ahead of every heading.
|
||||
"""
|
||||
chunks: list[str] = []
|
||||
pandoc_path = root / "_pandoc.yml"
|
||||
if pandoc_path.exists():
|
||||
raw = pandoc_path.read_text().rstrip("\n")
|
||||
chunks.append(f"---\n{raw}\n---")
|
||||
for path, depth in mt.walk(root):
|
||||
fm, body = mt.parse(path)
|
||||
if not fm.get("man", True):
|
||||
continue
|
||||
heading = fm.get("manTitle") or fm.get("title", path.stem)
|
||||
chunks.append("#" * (depth + 1) + " " + heading)
|
||||
if body:
|
||||
chunks.append(mt.shift_headings(body, depth))
|
||||
return "\n\n".join(chunks) + "\n"
|
||||
|
||||
|
||||
SENTENCE_RE = re.compile(r"^(.+?[.!?])(\s|$)", re.S)
|
||||
PIPELINE_KEYS = ("man", "site", "manTitle", "helpKeywords")
|
||||
JSX_ATTR_ESCAPES = (
|
||||
("&", "&"),
|
||||
('"', """),
|
||||
("<", "<"),
|
||||
("{", "{"),
|
||||
)
|
||||
|
||||
|
||||
def _jsx_attr_escape(value: str) -> str:
|
||||
"""Escape a string for safe use inside a quoted JSX attribute value.
|
||||
|
||||
`&` must go first so escaping later characters doesn't double-escape
|
||||
the ampersands it introduces. `"` closes the attribute early; `<` and
|
||||
`{` are otherwise-live MDX/JSX syntax that must not be interpreted.
|
||||
"""
|
||||
for char, escape in JSX_ATTR_ESCAPES:
|
||||
value = value.replace(char, escape)
|
||||
return value
|
||||
|
||||
|
||||
def _first_sentence(body: str) -> str:
|
||||
"""Extract a one-line description from the start of an entry body.
|
||||
|
||||
`Synopsis:` lines are skipped: they restate the calling convention,
|
||||
which the card already shows as its title, so using one as the card
|
||||
description wastes the line.
|
||||
"""
|
||||
for line in body.split("\n"):
|
||||
line = line.strip()
|
||||
if not line or line.startswith(("#", "```", "|", "-", "*", ">")):
|
||||
continue
|
||||
if line.startswith("Synopsis:"):
|
||||
continue
|
||||
m = SENTENCE_RE.match(line)
|
||||
return (m.group(1) if m else line)[:160]
|
||||
return ""
|
||||
|
||||
|
||||
# Commands common enough in this manual that a block whose every line starts
|
||||
# with one is certainly shell, not prose or a two-column reference table.
|
||||
SHELL_HEADS = frozenset(
|
||||
"""
|
||||
abbr alias apt bg bind brew builtin cargo cat cd chmod code command cp curl
|
||||
dnf echo end env exec export fg fish fisher for funcsave function git help
|
||||
if jobs kitty ls man math mkdir mv nvim npm pacman paru pip pip3 pkg printf
|
||||
python python3 rm set shutdown source string sudo switch systemctl test time
|
||||
tmux touch trash type wget wezterm while yay zellij zypper
|
||||
""".split()
|
||||
)
|
||||
|
||||
SYNOPSIS_PREFIX = "Synopsis:"
|
||||
INDENT = " "
|
||||
|
||||
|
||||
def _is_prose(para: list[str]) -> bool:
|
||||
"""True when a paragraph reads as sentences rather than as code or a table.
|
||||
|
||||
Column-aligned reference tables are the main thing to keep out of a
|
||||
syntax-highlighted fence, and internal runs of two-or-more spaces are
|
||||
what distinguishes them from prose. `<` and `{` are excluded because
|
||||
the emitted paragraph is live markdown, where both would be parsed.
|
||||
"""
|
||||
text = " ".join(para)
|
||||
if "<" in text or "{" in text:
|
||||
return False
|
||||
if not para or para[-1].rstrip()[-1:] not in ".:":
|
||||
return False
|
||||
return all(
|
||||
len(line.split()) >= 3 and " " not in line.strip() for line in para
|
||||
)
|
||||
|
||||
|
||||
def _is_shell(para: list[str], entry_name: str | None) -> bool:
|
||||
"""True when every line of a paragraph looks like a shell command."""
|
||||
name_re = (
|
||||
re.compile(rf"(?<![\w-]){re.escape(entry_name)}(?![\w-])")
|
||||
if entry_name
|
||||
else None
|
||||
)
|
||||
for line in para:
|
||||
stripped = line.strip()
|
||||
if not stripped or stripped.startswith("#"):
|
||||
continue
|
||||
if name_re and name_re.search(stripped):
|
||||
continue
|
||||
if stripped.split()[0].lstrip("$").rstrip(";") not in SHELL_HEADS:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _render_para(para: list[str], entry_name: str | None, deeper: bool) -> str:
|
||||
"""Render one paragraph of a former indented block.
|
||||
|
||||
`deeper` marks paragraphs carrying their own extra indentation — nested
|
||||
option tables, whose alignment only survives inside a code block.
|
||||
"""
|
||||
if not deeper:
|
||||
if _is_prose(para):
|
||||
return "\n".join(line.strip() for line in para)
|
||||
if _is_shell(para, entry_name):
|
||||
body = "\n".join(para)
|
||||
return f"```fish\n{body}\n```"
|
||||
return "\n".join(INDENT + line for line in para)
|
||||
|
||||
|
||||
def _prettify_block(block: list[str], entry_name: str | None) -> str:
|
||||
"""Convert one indented block into fenced code, prose, and tables.
|
||||
|
||||
The manual is authored man-page style: every example, table, and
|
||||
description sits in a single 4-space-indented block, which renders on
|
||||
the site as one unhighlighted grey slab. Splitting a block into its
|
||||
paragraphs recovers the structure the indentation flattened.
|
||||
"""
|
||||
lines = [line[len(INDENT) :] if line.startswith(INDENT) else line for line in block]
|
||||
|
||||
out: list[str] = []
|
||||
if lines and lines[0].startswith(SYNOPSIS_PREFIX):
|
||||
synopsis = lines.pop(0)[len(SYNOPSIS_PREFIX) :].strip()
|
||||
out.append(f"```fish\n{synopsis}\n```")
|
||||
|
||||
para: list[str] = []
|
||||
for line in lines + [""]:
|
||||
if line.strip():
|
||||
para.append(line)
|
||||
continue
|
||||
if para:
|
||||
deeper = any(line.startswith(" ") for line in para)
|
||||
out.append(_render_para(para, entry_name, deeper))
|
||||
para = []
|
||||
return "\n\n".join(chunk for chunk in out if chunk.strip())
|
||||
|
||||
|
||||
def prettify(body: str, entry_name: str | None = None) -> str:
|
||||
"""Rewrite a body's indented code blocks for the website.
|
||||
|
||||
Site-only: the man page and `config-help` keep reading the untouched
|
||||
SSOT, where the indented form is exactly what pandoc wants.
|
||||
"""
|
||||
out: list[str] = []
|
||||
block: list[str] = []
|
||||
in_fence = False
|
||||
|
||||
for line in body.split("\n"):
|
||||
if mt.FENCE_RE.match(line):
|
||||
in_fence = not in_fence
|
||||
if not in_fence and (line.startswith(INDENT) or (not line.strip() and block)):
|
||||
block.append(line)
|
||||
continue
|
||||
if block:
|
||||
while block and not block[-1].strip():
|
||||
block.pop()
|
||||
out.append(_prettify_block(block, entry_name))
|
||||
out.append("")
|
||||
block = []
|
||||
out.append(line)
|
||||
|
||||
if block:
|
||||
while block and not block[-1].strip():
|
||||
block.pop()
|
||||
out.append(_prettify_block(block, entry_name))
|
||||
return "\n".join(out)
|
||||
|
||||
|
||||
def _page_fm(fm: dict) -> dict:
|
||||
"""Strip pipeline-only keys from frontmatter destined for the site."""
|
||||
return {k: v for k, v in fm.items() if k not in PIPELINE_KEYS}
|
||||
|
||||
|
||||
def _split_entries(body: str) -> tuple[str, list[tuple[str, str]]]:
|
||||
"""Split a category body into (intro, [(entry title, entry body)]).
|
||||
|
||||
Fence-aware: an H2-looking line (`## ...`) inside a fenced code block
|
||||
(tracked the same way as `manualtools.shift_headings`) is treated as
|
||||
ordinary body text, not an entry boundary.
|
||||
"""
|
||||
lines = body.split("\n")
|
||||
heading_re = re.compile(r"^## (.+)$")
|
||||
boundaries: list[tuple[int, str]] = []
|
||||
in_fence = False
|
||||
for i, line in enumerate(lines):
|
||||
if mt.FENCE_RE.match(line):
|
||||
in_fence = not in_fence
|
||||
continue
|
||||
if not in_fence:
|
||||
m = heading_re.match(line)
|
||||
if m:
|
||||
boundaries.append((i, m.group(1)))
|
||||
|
||||
if not boundaries:
|
||||
return body.strip(), []
|
||||
|
||||
intro = "\n".join(lines[: boundaries[0][0]]).strip()
|
||||
entries = []
|
||||
for idx, (line_no, title) in enumerate(boundaries):
|
||||
start = line_no + 1
|
||||
end = boundaries[idx + 1][0] if idx + 1 < len(boundaries) else len(lines)
|
||||
# Strip newlines only: a bare .strip() would eat the leading
|
||||
# indentation of the entry's first line, detaching the `Synopsis:`
|
||||
# line from the indented block it opens.
|
||||
entry_body = "\n".join(lines[start:end]).strip("\n")
|
||||
entries.append((title.strip(), entry_body))
|
||||
return intro, entries
|
||||
|
||||
|
||||
def build_site(root: Path, out: Path) -> list[dict]:
|
||||
"""Write the Starlight content tree. Returns the sidebar structure."""
|
||||
if out.exists():
|
||||
shutil.rmtree(out)
|
||||
out.mkdir(parents=True)
|
||||
|
||||
sidebar: list[dict] = []
|
||||
functions_group: dict = {}
|
||||
for path, _depth in mt.walk(root):
|
||||
fm, body = mt.parse(path)
|
||||
if not fm.get("site", True):
|
||||
continue
|
||||
|
||||
rel = path.relative_to(root)
|
||||
is_function_dir = rel.parts and rel.parts[0].endswith("-functions")
|
||||
|
||||
if not is_function_dir:
|
||||
target = out / rel
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
target.write_text(mt.serialize(_page_fm(fm), prettify(body)))
|
||||
if rel.name != "index.md":
|
||||
sidebar.append({"label": fm["title"], "link": "/" + rel.stem + "/"})
|
||||
continue
|
||||
|
||||
# Section 5: category index page keeps its slot; entries explode.
|
||||
slug_dir = "functions"
|
||||
if rel.name == "index.md":
|
||||
target = out / slug_dir / "index.md"
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
target.write_text(mt.serialize(_page_fm(fm), prettify(body)))
|
||||
# Built explicitly rather than by `autogenerate`, which labels
|
||||
# each group with its raw directory slug and republishes this
|
||||
# index as a child of the group it already titles.
|
||||
functions_group = {
|
||||
"label": fm["title"],
|
||||
"collapsed": True,
|
||||
"items": [{"label": "Overview", "link": f"/{slug_dir}/"}],
|
||||
}
|
||||
sidebar.append(functions_group)
|
||||
continue
|
||||
|
||||
category = re.sub(r"^\d+-", "", rel.stem)
|
||||
cat_dir = out / slug_dir / category
|
||||
cat_dir.mkdir(parents=True, exist_ok=True)
|
||||
intro, entries = _split_entries(body)
|
||||
|
||||
cards = []
|
||||
links = []
|
||||
for title, entry_body in entries:
|
||||
entry_slug = re.sub(r"[^\w-]+", "-", title.strip().lower()).strip("-")
|
||||
desc = _first_sentence(entry_body)
|
||||
entry_fm = {"title": title}
|
||||
if desc:
|
||||
entry_fm["description"] = desc
|
||||
(cat_dir / f"{entry_slug}.md").write_text(
|
||||
mt.serialize(entry_fm, prettify(entry_body, title.split()[0]))
|
||||
)
|
||||
href = f"/{slug_dir}/{category}/{entry_slug}/"
|
||||
links.append({"label": title, "link": href})
|
||||
safe_title = _jsx_attr_escape(title)
|
||||
safe_desc = _jsx_attr_escape(desc)
|
||||
cards.append(
|
||||
f' <LinkCard title="{safe_title}" href="{href}"'
|
||||
+ (f' description="{safe_desc}"' if desc else "")
|
||||
+ " />"
|
||||
)
|
||||
|
||||
overview = (
|
||||
"import { CardGrid, LinkCard } from '@astrojs/starlight/components';\n\n"
|
||||
+ (f"{intro}\n\n" if intro else "")
|
||||
+ "<CardGrid>\n"
|
||||
+ "\n".join(cards)
|
||||
+ "\n</CardGrid>\n"
|
||||
)
|
||||
(cat_dir / "index.mdx").write_text(mt.serialize(_page_fm(fm), overview))
|
||||
|
||||
functions_group.setdefault("items", []).append(
|
||||
{
|
||||
"label": fm["title"],
|
||||
"collapsed": True,
|
||||
"items": [
|
||||
{"label": "Overview", "link": f"/{slug_dir}/{category}/"},
|
||||
*links,
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
return sidebar
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser(description=__doc__)
|
||||
ap.add_argument("--concat", action="store_true", help="emit the pandoc document")
|
||||
ap.add_argument("--site", action="store_true", help="emit the Starlight content tree")
|
||||
ap.add_argument("-o", "--output", type=Path, help="write to PATH instead of stdout")
|
||||
args = ap.parse_args()
|
||||
|
||||
if not (args.concat or args.site):
|
||||
ap.error("nothing to do: pass --concat and/or --site")
|
||||
|
||||
if args.site:
|
||||
src = DOCS / "site" / "src"
|
||||
out = src / "content" / "docs"
|
||||
sidebar = build_site(MANUAL, out)
|
||||
(src / "sidebar.json").write_text(json.dumps(sidebar, indent=2) + "\n")
|
||||
print(f"wrote site content to {out} ({len(sidebar)} sidebar entries)")
|
||||
|
||||
if args.concat:
|
||||
text = build_concat(MANUAL)
|
||||
if args.output:
|
||||
args.output.write_text(text)
|
||||
print(f"wrote {args.output}")
|
||||
else:
|
||||
sys.stdout.write(text)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
raise SystemExit(main())
|
||||
@@ -291,10 +291,10 @@ local-config=## local.fish
|
||||
# ── Section 11: Viewing This Manual ──────────────────────────
|
||||
viewing=# 11. VIEWING THIS MANUAL
|
||||
manual=# 11. VIEWING THIS MANUAL
|
||||
ov=## With ov (recommended)
|
||||
ov=## In the terminal
|
||||
man-page=## As a man page
|
||||
manpage=## As a man page
|
||||
jump=## Jumping to a section
|
||||
html=## In the browser (HTML)
|
||||
browser=## In the browser (HTML)
|
||||
wiki=## As a wiki
|
||||
jump=## In the terminal
|
||||
html=## The documentation website
|
||||
browser=## The documentation website
|
||||
site=## The documentation website
|
||||
|
||||
+48
-42
@@ -1328,7 +1328,7 @@ Add -i (interactive confirmation) to destructive commands:
|
||||
### config-help
|
||||
|
||||
Synopsis: config-help [SECTION]
|
||||
config-help [SECTION] --html
|
||||
config-help --html
|
||||
config-help [SECTION] --man
|
||||
config-help -h | --help
|
||||
|
||||
@@ -1338,11 +1338,11 @@ Add -i (interactive confirmation) to destructive commands:
|
||||
keyword (case-insensitive; checks fish-config.index aliases first).
|
||||
|
||||
Flags:
|
||||
--html / -w Open docs/html/index.html in the default browser.
|
||||
If SECTION is given, opens at the matching anchor.
|
||||
Detects the browser via xdg-mime x-scheme-handler/https,
|
||||
then known binaries, then xdg-open as last resort.
|
||||
Respects $fish_help_browser and $BROWSER.
|
||||
--html / -w Open the published documentation website
|
||||
(https://fish-config-docs.pages.dev/) in the default
|
||||
browser via xdg-open. Deep links to a section aren't
|
||||
supported; if SECTION is given, a note points you to the
|
||||
site's search box instead.
|
||||
--man / -m Open docs/fish-config.1 via man -l directly.
|
||||
If SECTION is given, jumps to the nearest match.
|
||||
--help / -h Print usage and navigation key reference.
|
||||
@@ -1350,7 +1350,6 @@ Add -i (interactive confirmation) to destructive commands:
|
||||
config-help keybindings
|
||||
config-help pkg
|
||||
config-help --html
|
||||
config-help pkg --html
|
||||
config-help --man
|
||||
config-help pkg --man
|
||||
|
||||
@@ -1378,7 +1377,7 @@ Add -i (interactive confirmation) to destructive commands:
|
||||
5. xdg-open (last resort)
|
||||
|
||||
open-url https://git.rootiest.dev/rootiest/fish-config
|
||||
open-url "file://$HOME/.config/fish/docs/html/index.html"
|
||||
open-url -v https://fish-config-docs.pages.dev/
|
||||
|
||||
Used internally by config-help --html.
|
||||
|
||||
@@ -2299,25 +2298,17 @@ local.fish in turn sources secrets.fish when it exists.
|
||||
|
||||
# 11. VIEWING THIS MANUAL
|
||||
|
||||
## With ov (recommended)
|
||||
There are four ways to read this manual.
|
||||
|
||||
help config
|
||||
## The documentation website
|
||||
|
||||
ov renders the Markdown with syntax highlighting and section-based
|
||||
navigation.
|
||||
help config --html
|
||||
|
||||
Space next section
|
||||
^ previous section
|
||||
Alt+u toggle section list sidebar
|
||||
/ search forward
|
||||
n / N next / previous search match
|
||||
g go to line number
|
||||
j interactive jump target (line, %, or 'section')
|
||||
q quit
|
||||
|
||||
## With bat
|
||||
|
||||
bat --language=markdown --paging=always ~/.config/fish/docs/fish-config.md
|
||||
Opens https://fish-config-docs.pages.dev/ in the default browser — the
|
||||
Starlight-powered site built from `docs/manual/**` on every push to `main`.
|
||||
It has a section sidebar and full-text search. Deep links to a specific
|
||||
section aren't supported from the command line; once the site opens, use
|
||||
its search box to jump straight to what you need.
|
||||
|
||||
## As a man page
|
||||
|
||||
@@ -2336,29 +2327,36 @@ NOTE: fish-config (hyphen) is this config's man page. fish_config
|
||||
(underscore) is fish's built-in browser-based configuration tool —
|
||||
a completely separate command. Do not mix them up.
|
||||
|
||||
## In the browser (HTML)
|
||||
## In the terminal
|
||||
|
||||
help config --html
|
||||
help config pkg --html
|
||||
help config
|
||||
help config keybindings
|
||||
|
||||
Opens docs/html/index.html in the default web browser. If a section
|
||||
keyword is given, the browser opens directly at the matching anchor
|
||||
(resolved via docs/html/sitemap.json). Browser detection queries the
|
||||
system's x-scheme-handler/https MIME entry (via xdg-mime) to find the
|
||||
real browser binary, then falls back through known browser binaries
|
||||
(firefox, chromium, vivaldi, etc.), and finally xdg-open as a last
|
||||
resort. Set $fish_help_browser or $BROWSER to override.
|
||||
Without a pager available beyond the basics, `help config [SECTION]` opens
|
||||
the Markdown manual in the best available viewer, falling back through:
|
||||
|
||||
## As a wiki
|
||||
1. ov + bat section navigation + syntax highlighting (best)
|
||||
2. ov alone section navigation, raw Markdown
|
||||
3. bat alone syntax highlighting, use / to search
|
||||
4. man -l pre-compiled man page (if available)
|
||||
5. less plain text with line-jump
|
||||
6. cat plain output
|
||||
|
||||
The generated Markdown wiki lives in docs/wiki/. index.md provides the
|
||||
project overview and a full table of contents. Each section page has a
|
||||
navigation bar at the top linking to every other section.
|
||||
With ov, the Markdown renders with syntax highlighting and section-based
|
||||
navigation:
|
||||
|
||||
The wiki is auto-generated from this file by the CI pipeline on every
|
||||
push to main that changes docs/fish-config.md.
|
||||
Space next section
|
||||
^ previous section
|
||||
Alt+u toggle section list sidebar
|
||||
/ search forward
|
||||
n / N next / previous search match
|
||||
g go to line number
|
||||
j interactive jump target (line, %, or 'section')
|
||||
q quit
|
||||
|
||||
## Jumping to a section
|
||||
If SECTION is given, the pager opens at the first heading that matches the
|
||||
keyword (case-insensitive; checks `docs/fish-config.index` aliases first,
|
||||
then falls back to a normalized heading scan):
|
||||
|
||||
help config keybindings
|
||||
help config abbreviations
|
||||
@@ -2366,4 +2364,12 @@ push to main that changes docs/fish-config.md.
|
||||
help config logs
|
||||
help config fish-deps
|
||||
|
||||
The keyword is matched case-insensitively against section headings.
|
||||
## Reading the source directly
|
||||
|
||||
`docs/manual/**` is the single source of truth this manual, the man page,
|
||||
and the website are all generated from. Numbered files and directories
|
||||
correspond to the numbered sections in this manual — browse them in any
|
||||
editor, or from a shell:
|
||||
|
||||
cd ~/.config/fish/docs/manual
|
||||
grep -rn "keybindings" .
|
||||
|
||||
@@ -1,301 +0,0 @@
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -1,495 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>NAME</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="2-synopsis.html" accesskey="n" rel="next">SYNOPSIS</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="index.html" accesskey="p" rel="previous">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="1" id="name">NAME</h1>
|
||||
<p>fish-config - personal fish shell configuration for Fish 4.x with
|
||||
modern CLI tool integration</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,547 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>6. DEPENDENCY CATALOG</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="11-7-customization.html" accesskey="n" rel="next">7. CUSTOMIZATION</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="9-5-functions-reference.html" accesskey="p" rel="previous">5. FUNCTIONS REFERENCE</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="10" id="6-dependency-catalog">6. DEPENDENCY
|
||||
CATALOG</h1>
|
||||
<p>fish-deps manages these tools. Run <code>fish-deps</code> to check
|
||||
status, or <code>fish-deps install</code> to install missing ones.</p>
|
||||
<h2 data-number="10.1" id="required">Required</h2>
|
||||
<pre><code>fish Fish shell >= 4.0
|
||||
fzf Fuzzy finder
|
||||
zoxide Smart cd with frecency</code></pre>
|
||||
<h2 data-number="10.2" id="integrations-1">Integrations</h2>
|
||||
<pre><code>wakatime Developer time tracking
|
||||
tailscale Mesh VPN client</code></pre>
|
||||
<h2 data-number="10.3" id="recommended">Recommended</h2>
|
||||
<pre><code>cargo Rust toolchain (via rustup); used by fish-deps to install
|
||||
Rust-based tools and to build fish from source. All paths
|
||||
are gated on type -q cargo and degrade gracefully.
|
||||
starship Cross-shell prompt; loaded via type -q starship guard.
|
||||
Without it the Catppuccin nim-style fallback prompt activates.
|
||||
uv Python package and project manager (Astral); used by the
|
||||
fish-from-source build path in fish-deps. All consumers
|
||||
degrade gracefully without it.
|
||||
direnv Per-directory environment loading; integration is fully
|
||||
guarded with type -q direnv. Without it the direnv hook
|
||||
is simply not loaded and auto-venv activates normally.
|
||||
paru AUR helper (Arch only; preferred); guarded throughout —
|
||||
non-Arch systems silently skip AUR-specific paths.
|
||||
yay AUR helper (Arch only; fallback to paru); same guards apply.
|
||||
eza Modern ls replacement
|
||||
lsd ls replacement (fallback to eza)
|
||||
bat Syntax-highlighted cat
|
||||
btop Modern resource monitor
|
||||
dust Disk usage tree (Rust)
|
||||
duf Disk usage/free overview
|
||||
prettyping Colorized ping wrapper
|
||||
ov Modern pager (replaces less)
|
||||
ripgrep Fast line search
|
||||
lazygit Terminal git UI
|
||||
lazydocker Terminal docker UI
|
||||
trash Safe delete (trash-cli)
|
||||
kitty GPU-accelerated terminal (primary)
|
||||
wezterm GPU-accelerated terminal (alternative)
|
||||
python3 Standalone interpreter — used by the paru/yay log cleaner.
|
||||
Note: uv does not provide python3 on PATH, and Arch's base
|
||||
does not include it, so it is listed separately. All
|
||||
consumers degrade gracefully without it.
|
||||
yt-dlp Video/media downloader; backs the yt-dlp wrapper function.
|
||||
Optional — the wrapper falls back to the system yt-dlp and
|
||||
the rest of the config works without it.</code></pre>
|
||||
<h2 data-number="10.4" id="install-methods">Install Methods</h2>
|
||||
<p>The install priority for each tool:</p>
|
||||
<pre><code>cargo Rust tools (eza, lsd, bat, dust, ov, ripgrep, trashy, zoxide,
|
||||
starship) — always gets the latest crate version
|
||||
system PM paru / apt / brew / dnf / etc. — for tools without a crate
|
||||
git clone fzf — installed from GitHub to ~/.fzf/
|
||||
curl starship installer, fisher bootstrap, uv installer</code></pre>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,888 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>7. CUSTOMIZATION</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="12-8-fisher-plugins.html" accesskey="n" rel="next">8. FISHER PLUGINS</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="10-6-dependency-catalog.html" accesskey="p" rel="previous">6. DEPENDENCY CATALOG</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="11" id="7-customization">7. CUSTOMIZATION</h1>
|
||||
<h2 data-number="11.1" id="machine-local-configuration">Machine-local
|
||||
Configuration</h2>
|
||||
<p>Place machine-specific settings that should not be committed to git
|
||||
in:</p>
|
||||
<pre><code>$__fish_user_dots_path/local.fish</code></pre>
|
||||
<p><code>__fish_user_dots_path</code> defaults to
|
||||
<code>~/.config/.user-dots/fish</code>. Set a custom location with:</p>
|
||||
<pre><code>set -U __fish_user_dots_path /path/to/your/dots/fish</code></pre>
|
||||
<p>Typical uses: additional PATH entries, local aliases,
|
||||
hostname-specific env vars, work-specific tool configs.</p>
|
||||
<p>For convenience, a git-ignored <code>user-dots</code> symlink in the
|
||||
fish config directory tracks <code>$__fish_user_dots_path</code> so the
|
||||
overlay can be browsed from <code>~/.config/fish/</code>. It is created
|
||||
if missing and repointed if the path changes. Opt out by setting
|
||||
<code>__fish_user_dots_symlink</code> to a falsy value, or toggling
|
||||
"Dots link" off on the config-settings Paths page — this stops
|
||||
generation and removes any existing link. It only ever manages a symlink
|
||||
and never clobbers a real file or directory at that path.</p>
|
||||
<h2 data-number="11.2" id="secrets-and-api-keys">Secrets and API
|
||||
Keys</h2>
|
||||
<pre><code>$__fish_user_dots_path/secrets.fish</code></pre>
|
||||
<p>Store API tokens, GPG keys, private credentials here. This file is
|
||||
never committed. It is sourced by local.fish directly, not by
|
||||
config.fish.</p>
|
||||
<p><code>local.fish</code> is sourced at the end of config.fish on every
|
||||
interactive session, so it and its companion secrets.fish can override
|
||||
anything set earlier.</p>
|
||||
<h2 data-number="11.3"
|
||||
id="overriding-configuration-variables">Overriding Configuration
|
||||
Variables</h2>
|
||||
<p>Any variable set in local.fish after the main config loads takes
|
||||
effect. Example: to increase the scrollback history limit:</p>
|
||||
<pre><code># in local.fish
|
||||
set -gx SCROLLBACK_HISTORY_MAX_FILES 200</code></pre>
|
||||
<h2 data-number="11.4" id="fish-universal-variables">Fish Universal
|
||||
Variables</h2>
|
||||
<p>Some settings (fzf colors, theme) are stored in fish_variables via
|
||||
<code>set -U</code>. These are machine-local and git-ignored. Do not
|
||||
commit fish_variables.</p>
|
||||
<h2 data-number="11.5"
|
||||
id="opinionated-components-minimal-mode">Opinionated Components (Minimal
|
||||
Mode)</h2>
|
||||
<p>Every opinionated piece of this config is active by default but can
|
||||
be switched off through six category opt-out variables, each evaluated
|
||||
via __fish_variable_check. Set a variable to any falsy value (0, false,
|
||||
no, off, n) to disable its category; erase it or set a truthy value (1,
|
||||
true, yes, on, y) to re-enable. Unset means enabled.</p>
|
||||
<p>An explicit per-category truthy value takes precedence over the
|
||||
master switch: setting __fish_config_opinionated=0 disables all unset
|
||||
categories, but a category with an explicit truthy value remains enabled
|
||||
regardless.</p>
|
||||
<pre><code>Variable Disables
|
||||
------------------------------ ------------------------------------
|
||||
__fish_config_op_aliases Command shadows and flag injection:
|
||||
ls->eza, cat->bat, cd->zoxide,
|
||||
rm->trash, less->ov, top->btop,
|
||||
ping->prettyping, ssh->kitten,
|
||||
du->duf/dust, mkdir/bash wrappers,
|
||||
history timestamps, grep/cp/mv/wget
|
||||
flag injection, help intercept, claude
|
||||
AGENTS.md auto-link
|
||||
__fish_config_op_autoexec Startup side-effects: Fisher
|
||||
bootstrap, theme apply, paru/yay
|
||||
wrapper generation, auto venv
|
||||
activation, WakaTime hook
|
||||
__fish_config_op_overrides Key and env overrides: Vi mode,
|
||||
exit->smart_exit, PAGER/MANPAGER,
|
||||
CDPATH, bang-bang system, autopair,
|
||||
puffer, starship prompt, theme
|
||||
colors, FZF_DEFAULT_OPTS, right
|
||||
prompt
|
||||
__fish_config_op_integrations Terminal/tool coupling: Kitty/
|
||||
WezTerm window abbreviations, done
|
||||
notifications, spwin/tab/split,
|
||||
hist, logs, upgrade, WakaTime
|
||||
__fish_config_op_logging Logging & capture: scrollback
|
||||
capture on exit, paru/yay AUR log
|
||||
wrappers, Kitty watcher capture;
|
||||
sentinel file coordinates
|
||||
cross-process state
|
||||
__fish_config_op_greeting Greeting & first-run UI: per-session
|
||||
fish_greeting override (defines empty
|
||||
function late in config.fish to
|
||||
suppress distro greetings such as
|
||||
CachyOS fastfetch); first-run welcome
|
||||
banner in conf.d/first_run.fish</code></pre>
|
||||
<p>Examples:</p>
|
||||
<pre><code># Disable command shadows only (rm becomes plain rm again):
|
||||
set -U __fish_config_op_aliases off
|
||||
|
||||
# Full minimal mode — disable all six categories at once:
|
||||
set -U __fish_config_opinionated 0
|
||||
|
||||
# Re-enable everything:
|
||||
set -Ue __fish_config_opinionated
|
||||
|
||||
# Minimal mode but keep the greeting:
|
||||
set -U __fish_config_opinionated 0
|
||||
set -U __fish_config_op_greeting 1
|
||||
# (erase both to go back to full-flavor defaults)</code></pre>
|
||||
<p>For an interactive alternative to setting these variables by hand,
|
||||
run config-settings — a full-screen TUI that flips any category
|
||||
(including C5 logging) on or off, per session or universally. See its
|
||||
entry in Section 5.</p>
|
||||
<p>Notes:</p>
|
||||
<ul>
|
||||
<li>Command shadows (rm, cat, ls, ...) react immediately; conf.d-level
|
||||
components (bindings, prompt, abbreviations, hooks) take effect in new
|
||||
shells.</li>
|
||||
<li>With aliases disabled, rm falls back to bare <code>command rm</code>
|
||||
— files are deleted permanently, not trashed.</li>
|
||||
<li>Disabled integration commands (spwin, tab, split, hist, logs,
|
||||
upgrade) print an error naming the variable that disabled them.</li>
|
||||
<li>On CachyOS, the distro fish config's own aliases, history override,
|
||||
and bang-bang bindings are stripped per category as well.</li>
|
||||
</ul>
|
||||
<h3 data-number="11.5.1" id="component-reference">Component
|
||||
Reference</h3>
|
||||
<p>The following tables detail every component in each category. Use
|
||||
this reference to understand exactly which behaviors change when you
|
||||
toggle a category variable.</p>
|
||||
<h4 data-number="11.5.1.1" id="c1--command-shadows">C1 — Command
|
||||
Shadows</h4>
|
||||
<p>Disabling __fish_config_op_aliases restores standard system behavior
|
||||
for all of these commands.</p>
|
||||
<pre><code>Command / Alias Active behavior Disabled fallback
|
||||
───────────────────────────────────────────────────────────────────────────
|
||||
ls eza -l -a --icons --hyperlink system ls
|
||||
cat bat syntax-highlighted; dirs → ls /usr/bin/cat
|
||||
cd zoxide frecency-based navigation fish builtin cd
|
||||
rm moves files to trash (recoverable) command rm (permanent)
|
||||
less $PAGER → ov → less → more → cat system less
|
||||
du duf (disk overview) or dust (dir tree) system du
|
||||
top btop resource monitor system top
|
||||
ping prettyping --nolegend animation system ping
|
||||
ssh kitten ssh in Kitty terminal system ssh
|
||||
rg rg --hyperlink-format=kitty system rg
|
||||
mkdir verbose path-tree display on creation mkdir -p silently
|
||||
bash XDG bashrc + $SHELL reset on exit system bash
|
||||
history timestamps prepended to every entry fish builtin history
|
||||
cp / mv forced -i confirmation prompt cp / mv unmodified
|
||||
wget forced --continue (resume downloads) system wget
|
||||
grep/fgrep/egrep forced --color=auto system grep variants
|
||||
dir / vdir forced --color=auto system dir / vdir
|
||||
help config intercepts "help config" → config-help fish builtin help
|
||||
claude auto-links AGENTS.md as CLAUDE.md before launch command claude
|
||||
edit multi-editor launcher (GUI/term + fallbacks) $EDITOR/nvim/nano/vi</code></pre>
|
||||
<p>When C1 is disabled, <code>rm</code> uses bare
|
||||
<code>command rm</code> with no wrapper — files are permanently deleted,
|
||||
not trashed. There is no intermediate safety net.</p>
|
||||
<h4 data-number="11.5.1.2" id="c2--startup-side-effects">C2 — Startup
|
||||
Side-Effects</h4>
|
||||
<p>These run automatically without any user action. Disabling
|
||||
__fish_config_op_autoexec prevents all of them.</p>
|
||||
<pre><code>Component Trigger What it does
|
||||
───────────────────────────────────────────────────────────────────────────
|
||||
Fisher bootstrap First shell only Downloads and installs fisher
|
||||
Fisher update After bootstrap Installs all fish_plugins entries
|
||||
Catppuccin Mocha theme First shell only Applies theme via fish_config
|
||||
paru wrapper Every startup Writes ~/.local/bin/paru wrapper
|
||||
yay wrapper Every startup Writes ~/.local/bin/yay wrapper
|
||||
Python venv activation On every cd Sources .venv/bin/activate.fish
|
||||
WakaTime command hook On every command Reports to WakaTime API
|
||||
Auto-pull fast-forward On entering a repo Background ff-only git pull
|
||||
user-dots symlink Every startup Links $__fish_config_dir/user-dots
|
||||
to $__fish_user_dots_path</code></pre>
|
||||
<p>When C2 is disabled: no Fisher install, no theme application, no
|
||||
paru/yay wrapper generation, no automatic venv activation, no WakaTime
|
||||
reporting, no auto-pull (the PWD handler is never registered), and the
|
||||
user-dots convenience symlink is not created. The symlink is git-ignored
|
||||
and only ever managed as a symlink — a real file or directory at that
|
||||
path is left untouched. The symlink has its own opt-out independent of
|
||||
C2: set __fish_user_dots_symlink to a falsy value (or toggle "Dots link"
|
||||
off on the config-settings Paths page) to stop generating it and remove
|
||||
any existing link — honoured even when C2 is enabled. Managed by the
|
||||
__fish_user_dots_link helper. The first-run completion marker
|
||||
(__fish_config_first_run_complete) is still set so the init does not
|
||||
re-run on subsequent shells.</p>
|
||||
<p>Python venv activation fires on every directory change. If a
|
||||
directory uses direnv (.envrc present), direnv takes priority and
|
||||
auto-venv is skipped for that directory.</p>
|
||||
<p>Auto-pull fast-forwards opted-in repositories in the background when
|
||||
you cd into them. The fish-config repo is always covered; other repos
|
||||
are added with the <code>auto-pull</code> command (see its entry in the
|
||||
functions reference). It only ever fast-forwards a clean repo whose
|
||||
branch has an upstream — never rebases, merges, or overwrites work — so
|
||||
it is a no-op on dirty trees, divergent branches, or repos without a
|
||||
remote. The handler fires once per repo entry (not on every
|
||||
sub-directory cd). The registry is machine-local at
|
||||
<code>$__fish_user_dots_path/auto-pull.list</code> (defaults to
|
||||
<code>~/.config/.user-dots/fish/auto-pull.list</code>) and is never
|
||||
committed.</p>
|
||||
<h4 data-number="11.5.1.3" id="c3--key-and-environment-overrides">C3 —
|
||||
Key and Environment Overrides</h4>
|
||||
<p>These change fundamental shell behavior: how keys work, which pager
|
||||
opens, and what the prompt looks like. Disabling
|
||||
__fish_config_op_overrides removes all of them.</p>
|
||||
<pre><code>Override What it replaces or sets
|
||||
───────────────────────────────────────────────────────────────────────────
|
||||
Vi mode fish_vi_key_bindings replaces default Emacs mode
|
||||
exit → smart_exit exit wrapper that captures scrollback before closing
|
||||
PAGER=ov ov used by git, man, and all $PAGER-aware tools
|
||||
MANPAGER=bat pipeline man pages rendered with syntax highlighting
|
||||
CDPATH=. ~/projects ~ bare dir names resolve against ~/projects and ~
|
||||
Bang-bang system ! and $ keys expand history; !^, !*, !-N, !?str?,
|
||||
^old^new abbreviations; six expand_bang_* helpers
|
||||
Autopair ( [ { " ' auto-close to (), [], {}, "", ''
|
||||
Puffer key intercepts . ! $ * keys intercepted for smart expansion
|
||||
Starship prompt fish_prompt replaced by Starship + OSC 133 markers
|
||||
Catppuccin colors 30+ fish_color_* variables set to Mocha palette
|
||||
FZF_DEFAULT_OPTS FZF themed to Catppuccin Mocha colors
|
||||
Right prompt fish_right_prompt: exit code (on failure) + dim timestamp; always rendered; Docker context added when starship+C3 active</code></pre>
|
||||
<p>The bang-bang system spans key_bindings.fish, abbr.fish, puffer.fish,
|
||||
and six expand_bang_*.fish functions. All are gated together — disabling
|
||||
C3 removes the entire bang-expansion system at once.</p>
|
||||
<p>When C3 is disabled, <code>exit</code> falls back to
|
||||
<code>builtin exit</code> with no scrollback capture, no Kitty IPC, and
|
||||
no file I/O on exit. The scrollback capture block is independently
|
||||
controlled by C5 (see below).</p>
|
||||
<h4 data-number="11.5.1.4" id="c4--terminal-and-tool-integration">C4 —
|
||||
Terminal and Tool Integration</h4>
|
||||
<p>These features couple the shell to specific external tools. Disabling
|
||||
__fish_config_op_integrations disables all of them.</p>
|
||||
<pre><code>Component Requires
|
||||
───────────────────────────────────────────────────────────────────────────
|
||||
~60 Kitty/WezTerm abbrs Active Kitty or WezTerm session
|
||||
(:w, :wv, :wh, :t, etc.)
|
||||
Done desktop notifications Graphical desktop with a notification daemon
|
||||
spwin Kitty or WezTerm
|
||||
tab Kitty, WezTerm, or Konsole
|
||||
split Kitty or WezTerm
|
||||
hist fzf + wl-copy (Wayland clipboard)
|
||||
logs fzf + ov; reads from ~/.terminal_history/
|
||||
upgrade paru or yay (Arch Linux only)
|
||||
WakaTime hook wakatime CLI and a configured API key</code></pre>
|
||||
<p>Disabled integration commands (spwin, tab, split, hist, logs,
|
||||
upgrade) print a colored error to stderr naming the variable that
|
||||
disabled them rather than silently failing.</p>
|
||||
<h4 data-number="11.5.1.5" id="c5--logging-and-capture">C5 — Logging and
|
||||
Capture</h4>
|
||||
<p>Five components capture shell output to disk. Disabling
|
||||
__fish_config_op_logging skips all capture and removes the logging
|
||||
wrappers.</p>
|
||||
<pre><code>Component What it captures
|
||||
───────────────────────────────────────────────────────────────────────────
|
||||
Scrollback capture Terminal session output saved to:
|
||||
~/.terminal_history/scrollback_YYYY-MM-DD_HH-MM-SS.log
|
||||
tmux pane capture Continuous pane stream via pipe-pane, saved to:
|
||||
~/.terminal_history/tmux_<session>-w<win>-p<pane>_YYYY-MM-DD_HH-MM-SS.log
|
||||
zellij pane capture Pane scrollback snapshot on shell exit, saved to:
|
||||
~/.terminal_history/zellij_<session>-p<pane>_YYYY-MM-DD_HH-MM-SS.log
|
||||
paru wrapper All paru/AUR output captured to:
|
||||
~/.terminal_history/paru_YYYY-MM-DD_HH-MM-SS.log
|
||||
yay wrapper All yay/AUR output captured to:
|
||||
~/.terminal_history/yay_YYYY-MM-DD_HH-MM-SS.log
|
||||
Kitty watcher watcher.py captures scrollback when Kitty closes</code></pre>
|
||||
<p>The tmux capture starts automatically when fish launches inside any
|
||||
tmux pane ($TMUX is set). It uses tmux's native pipe-pane to stream all
|
||||
pane output directly to disk without an intermediate process. Each fish
|
||||
shell session gets its own log file; a new log is created on each shell
|
||||
start (including exec fish and new splits). Before each new log, the
|
||||
oldest tmux_*.log files are pruned (by modification time) to keep the
|
||||
total within SCROLLBACK_HISTORY_MAX_FILES, matching the paru/yay wrapper
|
||||
behaviour.</p>
|
||||
<p>The zellij capture works differently: Zellij has no live
|
||||
output-streaming facility like pipe-pane, so the log is taken as a
|
||||
one-shot snapshot when the shell exits, via
|
||||
<code>zellij action dump-screen --full --ansi</code> (the --ansi flag
|
||||
preserves color). The dump is captured on the fish process's stdout and
|
||||
written to the log file by fish itself (not via <code>--path</code>,
|
||||
which would make the zellij server write the file). A fish_exit handler
|
||||
(registered whenever $ZELLIJ is set) writes the pane's full scrollback
|
||||
and then prunes old zellij_*.log files the same way. Because the capture
|
||||
happens at exit, toggling __fish_config_op_logging takes effect on the
|
||||
next exit with no restart or sentinel coordination needed — the C5 guard
|
||||
is re-checked when the handler fires.</p>
|
||||
<p>LIMITATION — zellij capture only fires on a clean shell exit (typing
|
||||
<code>exit</code>, Ctrl-D, or a logout), because that is when the
|
||||
fish_exit handler runs. It does NOT capture when you close a pane or
|
||||
quit zellij through zellij itself:</p>
|
||||
<ul>
|
||||
<li>Closing a pane signals the shell and tears the pane down
|
||||
concurrently, so even if the handler runs, <code>dump-screen</code> may
|
||||
find the pane buffer already gone.</li>
|
||||
<li>Quitting zellij kills the zellij server, and
|
||||
<code>dump-screen</code> needs a live server to read from — there is
|
||||
nothing left to snapshot.</li>
|
||||
</ul>
|
||||
<p>This is a structural difference from tmux, NOT a bug. tmux streams
|
||||
pane output to disk continuously via pipe-pane, so whatever was printed
|
||||
is already saved no matter how the pane dies. Zellij can only snapshot,
|
||||
and the only reliable snapshot point from the shell is a clean exit. To
|
||||
guarantee a zellij pane is logged, end the session with
|
||||
<code>exit</code> or Ctrl-D rather than zellij's close-pane or quit
|
||||
actions.</p>
|
||||
<p>The Kitty watcher is managed by the kitty-logging command: it
|
||||
symlinks the watcher (fish-config-watcher.py) into the Kitty config
|
||||
directory and wires it into kitty.conf via a managed block. Inside
|
||||
Kitty, a non-blocking per-session reminder points first-time users at
|
||||
<code>kitty-logging install</code> until they install or run
|
||||
<code>kitty-logging dismiss</code>. Install affects new Kitty windows
|
||||
only; runtime disable is still handled by the .logging_disabled
|
||||
sentinel.</p>
|
||||
<p>Logging coordination via sentinel file</p>
|
||||
<p>C5 uses a sentinel file to synchronize state between the shell and
|
||||
out-of-process components (the Kitty watcher and all running
|
||||
shells):</p>
|
||||
<pre><code>~/.config/fish/.logging_disabled</code></pre>
|
||||
<p>Disabling __fish_config_op_logging:</p>
|
||||
<ol type="1">
|
||||
<li>Creates the sentinel immediately in every open shell.</li>
|
||||
<li>Removes ~/.local/bin/paru and ~/.local/bin/yay logging wrappers;
|
||||
bare /usr/bin/paru and /usr/bin/yay are used instead.</li>
|
||||
<li>Kitty's watcher.py reads the sentinel on each save attempt and skips
|
||||
capture — no Kitty restart required.</li>
|
||||
<li>smart_exit stops saving scrollback logs.</li>
|
||||
<li>Stops tmux pipe-pane capture in every open fish shell inside
|
||||
tmux.</li>
|
||||
</ol>
|
||||
<p>Re-enabling __fish_config_op_logging:</p>
|
||||
<ol type="1">
|
||||
<li>Removes the sentinel in every open shell.</li>
|
||||
<li>Regenerates paru/yay logging wrappers in ~/.local/bin/.</li>
|
||||
<li>Kitty watcher resumes capture on the next session exit.</li>
|
||||
<li>Restarts tmux pipe-pane capture in every open fish shell inside
|
||||
tmux.</li>
|
||||
</ol>
|
||||
<p>Changes propagate to all running shells through an event handler that
|
||||
fires whenever __fish_config_op_logging changes — no shell restart
|
||||
needed.</p>
|
||||
<p>Note: C3 and C5 compose independently. C3 controls whether the
|
||||
smart_exit wrapper is active at all; C5 controls only the
|
||||
scrollback-capture block inside it. With C3 disabled, exit is plain
|
||||
builtin exit regardless of C5.</p>
|
||||
<h4 data-number="11.5.1.6" id="c6--greeting-and-first-run-ui">C6 —
|
||||
Greeting and First-Run UI</h4>
|
||||
<pre><code>Component What it shows
|
||||
───────────────────────────────────────────────────────────────────────────
|
||||
First-run welcome banner One-time message on first interactive session
|
||||
fish_greeting override Empty function defined late in config.fish to
|
||||
suppress distro greetings (e.g. CachyOS sets
|
||||
fish_greeting to fastfetch by default)</code></pre>
|
||||
<p>When C6 is disabled, no greeting is printed by this config. Any
|
||||
greeting set by the distro or other configs runs normally — this config
|
||||
simply does not override it.</p>
|
||||
<h2 data-number="11.6" id="prompt-and-theme">Prompt and Theme</h2>
|
||||
<h3 data-number="11.6.1" id="starship">Starship</h3>
|
||||
<p>The primary prompt is Starship, initialized by conf.d/starship.fish.
|
||||
Configure it via ~/.config/starship.toml.</p>
|
||||
<p>conf.d/starship.fish defines a fish_prompt wrapper that only
|
||||
activates when starship is in PATH. It emits OSC 133;A (prompt start)
|
||||
immediately before Starship renders and OSC 133;B (input start)
|
||||
immediately after, placing both markers on the prompt line itself. This
|
||||
allows ov to use them as sticky section headers when browsing scrollback
|
||||
logs. Without Starship, fish's built-in prompt handles these markers
|
||||
automatically.</p>
|
||||
<h3 data-number="11.6.2" id="catppuccin-fallback-prompt">Catppuccin
|
||||
Fallback Prompt</h3>
|
||||
<p>When Starship is absent or C3 overrides are disabled, a built-in
|
||||
nim-style two-line prompt activates from functions/fish_prompt.fish. No
|
||||
external dependencies — fish builtins only.</p>
|
||||
<p>Layout:</p>
|
||||
<pre><code>┬─[user@host:~/path] (main)
|
||||
╰─>$</code></pre>
|
||||
<p>Elements:</p>
|
||||
<pre><code>user Yellow (Catppuccin Yellow); red if root
|
||||
@host Blue (local) or Teal (SSH)
|
||||
~/path prompt_pwd abbreviation (Catppuccin Text)
|
||||
(main) Current git branch in Catppuccin Pink; omitted outside repos
|
||||
─[V:name] Active Python venv basename; omitted when none
|
||||
─[N/I/R/V] Vi-mode indicator when vi bindings are active
|
||||
┬─ / ╰─> Connector lines: Catppuccin Green on success, Red on failure</code></pre>
|
||||
<p>The right prompt (fish_right_prompt.fish) always renders, regardless
|
||||
of C3 state. On failure it shows a red ✘ and the exit code; on success
|
||||
it shows only the dim timestamp. When starship is installed and C3 is
|
||||
enabled, the active Docker context is also shown (if non-default):</p>
|
||||
<pre><code>✘ 1 myctx Fri Jun 12 00:51:21 2026 ← failed, starship+C3 active
|
||||
✘ 1 Fri Jun 12 00:51:21 2026 ← failed, fallback prompt
|
||||
Fri Jun 12 00:51:21 2026 ← success (no ✘)</code></pre>
|
||||
<h3 data-number="11.6.3" id="fzf">FZF</h3>
|
||||
<p>FZF is themed to Catppuccin Mocha via FZF_DEFAULT_OPTS set in
|
||||
integrations/fzf.fish. The colors applied:</p>
|
||||
<pre><code>Background: #1E1E2E (base) #313244 (surface0)
|
||||
Foreground: #CDD6F4 (text)
|
||||
Highlights: #F38BA8 (red) #CBA6F7 (mauve) #B4BEFE (lavender)</code></pre>
|
||||
<p>To customize, override FZF_DEFAULT_OPTS in local.fish.</p>
|
||||
<h3 data-number="11.6.4"
|
||||
id="catppuccin-mocha-syntax-highlighting">Catppuccin Mocha Syntax
|
||||
Highlighting</h3>
|
||||
<p>The Catppuccin Mocha theme ships with this config in themes/ and is
|
||||
applied on first run via <code>conf.d/first_run.fish</code>. Colors are
|
||||
stored in fish_variables (universal). To switch variants, install a
|
||||
different theme from themes/:</p>
|
||||
<pre><code>fish_config theme save "Catppuccin Latte"</code></pre>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,573 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>8. FISHER PLUGINS</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="13-9-installation.html" accesskey="n" rel="next">9. INSTALLATION</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="11-7-customization.html" accesskey="p" rel="previous">7. CUSTOMIZATION</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="12" id="8-fisher-plugins">8. FISHER PLUGINS</h1>
|
||||
<p>Fisher is bootstrapped automatically on the <strong>first interactive
|
||||
session</strong> via <code>conf.d/first_run.fish</code>. This also
|
||||
applies the Catppuccin Mocha theme and prints a one-time welcome message
|
||||
(gated by __fish_config_op_greeting; set it to 0 to suppress).
|
||||
Subsequent sessions skip all first-run logic with zero overhead.</p>
|
||||
<p>To re-trigger first-run initialization (e.g., after a fresh install
|
||||
or for testing), run:</p>
|
||||
<pre><code>set -Ue __fish_config_first_run_complete</code></pre>
|
||||
<p>Then open a new shell.</p>
|
||||
<h2 data-number="12.1" id="fisher-managed-plugins">Fisher-Managed
|
||||
Plugins</h2>
|
||||
<p>The following plugins are fully managed by Fisher. Their files are
|
||||
installed into the repo directory by Fisher and are listed in
|
||||
<code>.gitignore</code> — do not commit them. Fisher installs and
|
||||
updates them automatically.</p>
|
||||
<pre><code>jorgebucaran/fisher Plugin manager itself
|
||||
meaningful-ooo/sponge Remove failed commands from history</code></pre>
|
||||
<h2 data-number="12.2" id="sponge-history-filtering">Sponge History
|
||||
Filtering</h2>
|
||||
<p>Sponge removes failed commands from history and, via
|
||||
conf.d/sponge_privacy.fish, also filters privacy-sensitive commands
|
||||
through three layers:</p>
|
||||
<p>Layer 1 — Static patterns (universal, persistent across sessions):
|
||||
Commands matching any of these structural signatures are never
|
||||
recorded:</p>
|
||||
<pre><code>--password / --token / --passphrase / --api-key flags with values
|
||||
Inline env assignments: GITHUB_TOKEN=xxx, MY_API_KEY=abc
|
||||
Fish set with sensitive names: set -gx GITHUB_TOKEN xxx
|
||||
URLs with embedded credentials: https://user:pass@host
|
||||
HTTP Authorization headers: curl -H "Authorization: ..."
|
||||
Basic auth flags: curl -u user:pass
|
||||
sshpass, docker login -p, openssl -passin/-passout</code></pre>
|
||||
<p>Layer 2 — Dynamic secret values (session globals, refreshed each
|
||||
login): On the first prompt, after secrets.fish has loaded, the literal
|
||||
values of all exported variables whose names suggest credentials (TOKEN,
|
||||
PASSWORD, SECRET, API_KEY, etc.) are collected, regex-escaped, and added
|
||||
as a session-scoped overlay. Because globals shadow universals in Fish,
|
||||
the combined list is what sponge sees. Rotating a token takes effect on
|
||||
the next login automatically.</p>
|
||||
<p>Layer 3 — Per-command filter (sponge_filter_secrets): Catches
|
||||
credentials in variables exported after login, such as tokens sourced
|
||||
from a project .env file mid-session.</p>
|
||||
<p>To add your own persistent patterns:</p>
|
||||
<pre><code>set -U -a sponge_regex_patterns 'your-regex-here'</code></pre>
|
||||
<p>To mark additional variable NAMES as credential-bearing (so Layer 2
|
||||
scrubs their values), add name tokens — via <code>config-settings</code>
|
||||
→ Sponge, or directly:</p>
|
||||
<pre><code>set -U -a __fish_sponge_extra_sensitive ACME_API VAULT_PW</code></pre>
|
||||
<p>Tokens are folded into the Layer 2 name match case-insensitively as
|
||||
substrings, so ACME_API also covers ACME_API_KEY. (The match uses
|
||||
<code>--entire</code> to return the full variable name, so partial-name
|
||||
tokens dereference the right value.)</p>
|
||||
<p>The <code>config-settings</code> Sponge page also surfaces sponge's
|
||||
own tuning variables — sponge_delay, sponge_successful_exit_codes,
|
||||
sponge_purge_only_on_exit, and sponge_allow_previously_successful — so
|
||||
they can be changed without typing variable names.</p>
|
||||
<h2 data-number="12.3" id="bundled-plugin-functionality">Bundled Plugin
|
||||
Functionality</h2>
|
||||
<p>The remaining plugin functionality is bundled directly with this
|
||||
config rather than managed through Fisher. The bundled versions include
|
||||
customizations for Fish 4.x compatibility and improved behavior that
|
||||
differ from their upstream releases. Installing them through Fisher
|
||||
would overwrite these customizations.</p>
|
||||
<p>Bundled components and their upstream origins:</p>
|
||||
<pre><code>catppuccin/fish → themes/ + conf.d/theme.fish
|
||||
PatrickF1/fzf.fish → functions/_fzf_*.fish + conf.d/fzf.fish
|
||||
franciscolourenco/done → conf.d/done.fish
|
||||
jorgebucaran/autopair.fish → functions/_autopair_*.fish + conf.d/autopair.fish
|
||||
nickeb96/puffer-fish → functions/_puffer_fish_*.fish + conf.d/puffer.fish</code></pre>
|
||||
<p>Do not run <code>fisher install</code> for these — it will overwrite
|
||||
the customized versions. To update their behavior, edit the relevant
|
||||
bundled files directly.</p>
|
||||
<h2 data-number="12.4" id="fish_plugins-manifest">fish_plugins
|
||||
Manifest</h2>
|
||||
<p>The <code>fish_plugins</code> file at the config root:</p>
|
||||
<pre><code>jorgebucaran/fisher Plugin manager itself
|
||||
meaningful-ooo/sponge Remove failed commands from history</code></pre>
|
||||
<p>To update all Fisher-managed plugins, run <code>fisher update</code>
|
||||
or <code>fish-deps update</code> which calls it as its first step.</p>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,521 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>9. INSTALLATION</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="14-10-personalization.html" accesskey="n" rel="next">10. PERSONALIZATION</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="12-8-fisher-plugins.html" accesskey="p" rel="previous">8. FISHER PLUGINS</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="13" id="9-installation">9. INSTALLATION</h1>
|
||||
<p>This configuration is managed as a git repository. To deploy on a new
|
||||
machine:</p>
|
||||
<pre><code>mv ~/.config/fish ~/.config/fish.bak # back up any existing config
|
||||
git clone https://git.rootiest.dev/rootiest/fish-config.git ~/.config/fish</code></pre>
|
||||
<p>Then open a new Fish shell. Fisher installs automatically on first
|
||||
launch and the Catppuccin Mocha theme is applied. All other plugin
|
||||
functionality is bundled directly with this config and requires no
|
||||
additional installation.</p>
|
||||
<h2 data-number="13.1" id="return-sentinel">Return Sentinel</h2>
|
||||
<p>config.fish ends with a return sentinel guard. Any lines appended
|
||||
after it by a tool's setup command (starship init fish | source, zoxide
|
||||
init fish | source, etc.) will have no effect. All integrations are
|
||||
managed via conf.d/ files.</p>
|
||||
<p>If a new tool's shell integration appears to do nothing, check
|
||||
whether its setup command appended an init line below the sentinel and
|
||||
create a dedicated conf.d/<tool>.fish instead.</p>
|
||||
<h2 data-number="13.2" id="updating">Updating</h2>
|
||||
<p>Pull the latest changes from the upstream repository without needing
|
||||
a configured git remote:</p>
|
||||
<pre><code>config-update Fetch and apply the latest commits from upstream
|
||||
config-update --dry-run Preview available changes without applying them
|
||||
config-update --force Stash local changes, pull, then restore the stash</code></pre>
|
||||
<p>The remote URL (<a
|
||||
href="https://git.rootiest.dev/rootiest/fish-config.git">https://git.rootiest.dev/rootiest/fish-config.git</a>)
|
||||
is hard-coded, so this works on a fresh clone with no origin configured.
|
||||
All git output is suppressed. Run exec fish after a successful update to
|
||||
reload.</p>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,540 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>10. PERSONALIZATION</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="15-11-viewing-this-manual.html" accesskey="n" rel="next">11. VIEWING THIS MANUAL</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="13-9-installation.html" accesskey="p" rel="previous">9. INSTALLATION</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="14" id="10-personalization">10. PERSONALIZATION</h1>
|
||||
<p>Sensitive credentials and machine-specific settings are kept out of
|
||||
version control in a private directory. The path defaults to
|
||||
<code>~/.config/.user-dots/fish/</code> but can be overridden:</p>
|
||||
<pre><code>set -U __fish_user_dots_path /path/to/your/dots/fish</code></pre>
|
||||
<p>Or use the interactive TUI — run <code>config-settings</code> and
|
||||
navigate to the "Dots Path" row (last row). Press Enter to type a new
|
||||
path, or ← / h to reset to the default.</p>
|
||||
<p>config.fish sources local.fish from that directory on every
|
||||
interactive session. local.fish is responsible for sourcing its own
|
||||
secrets.fish:</p>
|
||||
<pre><code>$__fish_user_dots_path/
|
||||
├── secrets.fish API keys, tokens, passwords, personal identifiers
|
||||
└── local.fish Machine-specific paths, env vars, and sourcing secrets</code></pre>
|
||||
<p>fish_variables (auto-managed by fish) is excluded from this repo via
|
||||
.gitignore. Do not commit it.</p>
|
||||
<h2 data-number="14.1" id="secretsfish">secrets.fish</h2>
|
||||
<p>Store anything you would not commit to a public repo: API keys, auth
|
||||
tokens, passwords, and personal identifiers.</p>
|
||||
<pre><code>set -gx MY_NAME "Your Name"
|
||||
set -gx MY_EMAIL "you@example.com"
|
||||
set -gx GPG_RECIPIENT "you@example.com"
|
||||
set -gx GITHUB_TOKEN ghp_yourTokenHere
|
||||
set -gx OPENAI_API_KEY sk-proj-yourKeyHere
|
||||
set -gx GITEA_TOKEN yourGiteaTokenHere
|
||||
set -gx GITEA_CHOSEN_LOGIN your.gitea.instance
|
||||
set -gx KOPIA_PASSWORD yourKopiaPassword</code></pre>
|
||||
<h2 data-number="14.2" id="localfish">local.fish</h2>
|
||||
<p>Store paths and variables specific to one machine — things that would
|
||||
be wrong on any other system.</p>
|
||||
<pre><code># CDPATH — directories searched by cd
|
||||
set -gx CDPATH . /home/youruser/projects /home/youruser
|
||||
|
||||
# Path to your shared .gitignore boilerplate
|
||||
set -gx GITIGNORE_BOILERPLATE ~/.config/git/gitignore_boilerplate
|
||||
|
||||
# SSH shortcuts
|
||||
abbr -a sshr 'ssh you@your-server.local'
|
||||
abbr -a sshw 'ssh you@work-server.example.com'
|
||||
|
||||
# Docker context shortcuts
|
||||
abbr -a dcr 'docker context use my-remote-server'
|
||||
abbr -a dcw 'docker context use work-server'</code></pre>
|
||||
<p>local.fish is sourced at the end of config.fish with an existence
|
||||
check so the public config works cleanly on any machine without the
|
||||
private repo. local.fish in turn sources secrets.fish when it
|
||||
exists.</p>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,546 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>11. VIEWING THIS MANUAL</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="14-10-personalization.html" accesskey="p" rel="previous">10. PERSONALIZATION</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="15" id="11-viewing-this-manual">11. VIEWING THIS
|
||||
MANUAL</h1>
|
||||
<h2 data-number="15.1" id="with-ov-recommended">With ov
|
||||
(recommended)</h2>
|
||||
<pre><code>help config</code></pre>
|
||||
<p>ov renders the Markdown with syntax highlighting and section-based
|
||||
navigation.</p>
|
||||
<pre><code>Space next section
|
||||
^ previous section
|
||||
Alt+u toggle section list sidebar
|
||||
/ search forward
|
||||
n / N next / previous search match
|
||||
g go to line number
|
||||
j interactive jump target (line, %, or 'section')
|
||||
q quit</code></pre>
|
||||
<h2 data-number="15.2" id="with-bat">With bat</h2>
|
||||
<pre><code>bat --language=markdown --paging=always ~/.config/fish/docs/fish-config.md</code></pre>
|
||||
<h2 data-number="15.3" id="as-a-man-page">As a man page</h2>
|
||||
<pre><code>help config --man
|
||||
help config pkg --man</code></pre>
|
||||
<p>Opens the compiled docs/fish-config.1 directly via man -l, bypassing
|
||||
the pager fallback chain. If a section keyword is given, the pager opens
|
||||
at the nearest matching heading. The symlink is created once on first
|
||||
run (like an install step) and MANPATH is set each session, enabling the
|
||||
standard invocation:</p>
|
||||
<pre><code>man fish-config</code></pre>
|
||||
<p>NOTE: fish-config (hyphen) is this config's man page. fish_config
|
||||
(underscore) is fish's built-in browser-based configuration tool — a
|
||||
completely separate command. Do not mix them up.</p>
|
||||
<h2 data-number="15.4" id="in-the-browser-html">In the browser
|
||||
(HTML)</h2>
|
||||
<pre><code>help config --html
|
||||
help config pkg --html</code></pre>
|
||||
<p>Opens docs/html/index.html in the default web browser. If a section
|
||||
keyword is given, the browser opens directly at the matching anchor
|
||||
(resolved via docs/html/sitemap.json). Browser detection queries the
|
||||
system's x-scheme-handler/https MIME entry (via xdg-mime) to find the
|
||||
real browser binary, then falls back through known browser binaries
|
||||
(firefox, chromium, vivaldi, etc.), and finally xdg-open as a last
|
||||
resort. Set $fish_help_browser or $BROWSER to override.</p>
|
||||
<h2 data-number="15.5" id="as-a-wiki">As a wiki</h2>
|
||||
<p>The generated Markdown wiki lives in docs/wiki/. index.md provides
|
||||
the project overview and a full table of contents. Each section page has
|
||||
a navigation bar at the top linking to every other section.</p>
|
||||
<p>The wiki is auto-generated from this file by the CI pipeline on every
|
||||
push to main that changes docs/fish-config.md.</p>
|
||||
<h2 data-number="15.6" id="jumping-to-a-section">Jumping to a
|
||||
section</h2>
|
||||
<pre><code>help config keybindings
|
||||
help config abbreviations
|
||||
help config pkg
|
||||
help config logs
|
||||
help config fish-deps</code></pre>
|
||||
<p>The keyword is matched case-insensitively against section
|
||||
headings.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,503 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>SYNOPSIS</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="3-description.html" accesskey="n" rel="next">DESCRIPTION</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="1-name.html" accesskey="p" rel="previous">NAME</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="2" id="synopsis">SYNOPSIS</h1>
|
||||
<pre><code>help config [SECTION]</code></pre>
|
||||
<p>Open this manual in the best available pager. Optionally jump to a
|
||||
section by keyword:</p>
|
||||
<pre><code>help config keybindings
|
||||
help config pkg
|
||||
help config abbreviations
|
||||
help config logs</code></pre>
|
||||
<p>The <code>help config</code> syntax integrates with fish's built-in
|
||||
help command. The underlying <code>config-help</code> function is also
|
||||
available directly.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,562 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>DESCRIPTION</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="4-table-of-contents.html" accesskey="n" rel="next">TABLE OF CONTENTS</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="2-synopsis.html" accesskey="p" rel="previous">SYNOPSIS</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="3" id="description">DESCRIPTION</h1>
|
||||
<p>A production-grade Fish shell configuration targeting Fish 4.x. It
|
||||
provides:</p>
|
||||
<ul>
|
||||
<li>Drop-in replacements for common Unix tools (ls, cat, rm, du, ping,
|
||||
less)</li>
|
||||
<li>Deep Kitty and WezTerm terminal integration: tab/window/pane
|
||||
management from the command line</li>
|
||||
<li>Automatic session logging: terminal scrollback, tmux/zellij panes,
|
||||
and paru/yay output captured to ~/.terminal_history (on by default; see
|
||||
below)</li>
|
||||
<li>Automatic Python virtualenv activation on directory change</li>
|
||||
<li>Cross-platform package management via pkg and fish-deps</li>
|
||||
<li>AI session helpers for Claude Code and Antigravity</li>
|
||||
<li>Catppuccin Mocha color theme throughout</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p><strong>CAUTION - SESSION LOGGING IS ON BY DEFAULT</strong></p>
|
||||
<p>This configuration silently records terminal output to
|
||||
<code>~/.terminal_history</code>: Kitty scrollback on window close, live
|
||||
tmux pane streams, zellij pane snapshots on exit, and full paru/yay
|
||||
output. These logs can contain command output, file contents, and
|
||||
secrets printed to the terminal. Nothing leaves your machine, but the
|
||||
files persist locally.</p>
|
||||
<ul>
|
||||
<li>Disable all logging with:
|
||||
<code>set -U __fish_config_op_logging off</code></li>
|
||||
<li>Prefer a menu? Run the interactive picker:
|
||||
<code>config-settings</code></li>
|
||||
<li>See Section 7 (C5 - Logging and Capture) for the full
|
||||
breakdown.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>The configuration is split across:</p>
|
||||
<pre><code>config.fish Main entry point; sets env vars and PATH
|
||||
conf.d/
|
||||
abbr.fish All abbreviations
|
||||
autopair.fish Auto-pair brackets and quotes (bundled from jorgebucaran/autopair.fish)
|
||||
cheat.fish cheat.sh tab completions
|
||||
done.fish Desktop notifications for long commands
|
||||
first_run.fish One-time init: Fisher bootstrap, theme, welcome
|
||||
key_bindings.fish Custom key bindings and Vi mode
|
||||
logging-events.fish C5 --on-variable event handlers; syncs logging state at startup
|
||||
kitty-watcher-reminder.fish C5 per-session reminder to set up the Kitty watcher
|
||||
paru-wrapper.fish Auto-generates ~/.local/bin/paru logging wrapper
|
||||
puffer.fish !! / !$ / ./ expansion (bundled from nickeb96/puffer-fish)
|
||||
tmux-logging.fish C5 starts tmux pipe-pane capture when fish runs inside tmux
|
||||
zellij-logging.fish C5 fish_exit handler dumping zellij pane scrollback on exit
|
||||
sponge_privacy.fish Sponge privacy patterns; filters credentials from history
|
||||
starship.fish fish_prompt with OSC 133 shell-integration markers
|
||||
tailscale.fish Tailscale CLI tab completions
|
||||
theme.fish Catppuccin syntax highlight colors
|
||||
tricks.fish PATH, bang-bang helpers, bat man pages, aliases
|
||||
wakatime.fish WakaTime shell hook
|
||||
yay-wrapper.fish Auto-generates ~/.local/bin/yay logging wrapper
|
||||
zoxide.fish Zoxide z/zi integration; overrides cd
|
||||
functions/ Custom functions, one per file, autoloaded
|
||||
completions/ Tab completion scripts
|
||||
integrations/
|
||||
fzf.fish FZF Catppuccin theme and key binding config
|
||||
scripts/
|
||||
clean_progress_log.py Strips paru/yay typescript animations to clean static logs
|
||||
agents-tools/ AGENTS.md version-bump script and git hooks (wired via core.hooksPath)
|
||||
docs/ Offline documentation and compiled man page
|
||||
fish-config.md Primary source manual (terminal-readable)
|
||||
fish-config.1 Compiled man page (auto-generated by CI)
|
||||
fish-config.index Section index for help config navigation
|
||||
html/ Chunked HTML docs (auto-generated by CI)
|
||||
wiki/ Markdown wiki (auto-generated by CI)</code></pre>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,530 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>TABLE OF CONTENTS</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="5-1-configuration-variables.html" accesskey="n" rel="next">1. CONFIGURATION VARIABLES</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="3-description.html" accesskey="p" rel="previous">DESCRIPTION</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="4" id="table-of-contents">TABLE OF CONTENTS</h1>
|
||||
<pre><code>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. Viewing This Manual</code></pre>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,602 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>1. CONFIGURATION VARIABLES</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="6-2-path-setup.html" accesskey="n" rel="next">2. PATH SETUP</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="4-table-of-contents.html" accesskey="p" rel="previous">TABLE OF CONTENTS</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="5" id="1-configuration-variables">1. CONFIGURATION
|
||||
VARIABLES</h1>
|
||||
<p>These variables are exported from config.fish on every interactive
|
||||
session. Override them in local.fish (see Section 10,
|
||||
Personalization).</p>
|
||||
<h2 data-number="5.1" id="environment-directories-xdg">Environment
|
||||
Directories (XDG)</h2>
|
||||
<pre><code>XDG_CONFIG_HOME ~/.config
|
||||
XDG_CACHE_HOME ~/.cache
|
||||
XDG_DATA_HOME ~/.local/share
|
||||
XDG_STATE_HOME ~/.local/state</code></pre>
|
||||
<p>Tools that respect XDG are directed to these paths rather than
|
||||
polluting $HOME.</p>
|
||||
<h2 data-number="5.2" id="tool-homes-xdg-compliant">Tool Homes
|
||||
(XDG-compliant)</h2>
|
||||
<pre><code>CARGO_HOME $XDG_DATA_HOME/cargo
|
||||
RUSTUP_HOME $XDG_DATA_HOME/rustup
|
||||
GOPATH $XDG_DATA_HOME/go
|
||||
BUN_INSTALL $XDG_DATA_HOME/bun
|
||||
NPM_CONFIG_PREFIX $XDG_DATA_HOME/npm-global
|
||||
GNUPGHOME $XDG_CONFIG_HOME/gnupg
|
||||
WAKATIME_HOME $XDG_CONFIG_HOME/wakatime</code></pre>
|
||||
<h2 data-number="5.3" id="editor-and-pager">Editor and Pager</h2>
|
||||
<pre><code>EDITOR nvim (falls back to vi if nvim is absent)
|
||||
VISUAL unset by default; set a GUI editor via local.fish (the edit
|
||||
function falls back to a GUI chain when VISUAL is empty)
|
||||
SUDO_EDITOR same as EDITOR
|
||||
PAGER ov (falls back to less)</code></pre>
|
||||
<h2 data-number="5.4" id="scrollback-history">Scrollback History</h2>
|
||||
<pre><code>__fish_scrollback_history_dir (unset → ~/.terminal_history)
|
||||
__fish_scrollback_history_max_files (unset → 100)
|
||||
SCROLLBACK_HISTORY_DIR ~/.terminal_history (exported mirror)
|
||||
SCROLLBACK_HISTORY_MAX_FILES 100 (exported mirror)</code></pre>
|
||||
<p>The <em><em>fish_scrollback_history</em>* universal variables are the
|
||||
fish-style source of truth — set them via <code>config-settings</code> →
|
||||
Paths, or <code>set -U</code> directly. config.fish exports the
|
||||
SCROLLBACK_HISTORY</em>* mirrors from them, because the POSIX wrapper
|
||||
scripts (paru/yay/tmux/zellij logging and _prune_terminal_logs) read the
|
||||
exported names from the environment. When the _<em>fish</em> vars are
|
||||
unset, the documented defaults are exported. config.fish deliberately
|
||||
does not create a global source var, which would shadow the universal
|
||||
and stop live edits from taking effect.</p>
|
||||
<p>Scrollback logs accumulate in SCROLLBACK_HISTORY_DIR as timestamped
|
||||
files. When the count exceeds SCROLLBACK_HISTORY_MAX_FILES the oldest
|
||||
are pruned automatically on exit. Use <code>logs</code> to browse them
|
||||
interactively.</p>
|
||||
<h2 data-number="5.5" id="other">Other</h2>
|
||||
<pre><code>GPG_TTY $(tty) — ensures GPG passphrase prompts work
|
||||
CLAUDE_CODE_NO_FLICKER 1 — suppress terminal flicker in Claude Code
|
||||
CDPATH . ~/projects ~</code></pre>
|
||||
<p>Opinionated defaults (CDPATH, PAGER/MANPAGER, Vi mode, command
|
||||
shadows, terminal integrations) can be switched off per category with
|
||||
universal variables — see Section 7, "Opinionated Components (Minimal
|
||||
Mode)".</p>
|
||||
<h2 data-number="5.6" id="pager-hierarchy">Pager Hierarchy</h2>
|
||||
<p>$PAGER is set to ov when available, falling back to less. The less
|
||||
wrapper function extends this into a full chain so anything that calls
|
||||
less directly also benefits:</p>
|
||||
<pre><code>$PAGER → ov → less → more → cat</code></pre>
|
||||
<p>When bat is installed, man pages are rendered with syntax
|
||||
highlighting:</p>
|
||||
<pre><code>MANROFFOPT -c
|
||||
MANPAGER sh -c 'col -bx | bat -l man -p'</code></pre>
|
||||
<h2 data-number="5.7" id="integrations">Integrations</h2>
|
||||
<h3 data-number="5.7.1" id="zoxide">Zoxide</h3>
|
||||
<p>cd, z, and cdi/zi are all mapped to zoxide-backed navigation. Tab
|
||||
completions for cd and z blend standard directory entries (CWD and
|
||||
CDPATH) with frecency results so both familiar and frequently-visited
|
||||
paths appear in one list.</p>
|
||||
<h3 data-number="5.7.2" id="direnv">DirEnv</h3>
|
||||
<p>Automatically loads .envrc files on directory change. Takes priority
|
||||
over the auto-venv logic — if a directory is managed by direnv, the
|
||||
auto-venv activation is skipped entirely.</p>
|
||||
<h3 data-number="5.7.3" id="auto-python-venv">Auto Python Venv</h3>
|
||||
<p>When entering a directory that contains a .venv/, the virtualenv is
|
||||
activated automatically and deactivated when you leave the project
|
||||
tree.</p>
|
||||
<h3 data-number="5.7.4" id="wakatime">WakaTime</h3>
|
||||
<p>Every shell command is reported to WakaTime for time-tracking. Set
|
||||
FISH_WAKATIME_DISABLED=1 to disable without removing the plugin.</p>
|
||||
<h3 data-number="5.7.5" id="tailscale">Tailscale</h3>
|
||||
<p>Full tab completion for the tailscale CLI is provided via
|
||||
conf.d/tailscale.fish.</p>
|
||||
<h3 data-number="5.7.6" id="done-notifications">Done Notifications</h3>
|
||||
<p>Desktop notifications fire when a command takes longer than 10
|
||||
seconds and the terminal window is not focused. Configured via fish
|
||||
universal variables:</p>
|
||||
<pre><code>__done_min_cmd_duration 10000 ms
|
||||
__done_notification_urgency_level low</code></pre>
|
||||
<h3 data-number="5.7.7" id="scrollback-history-1">Scrollback
|
||||
History</h3>
|
||||
<p>When running inside Kitty, closing a shell session via exit saves a
|
||||
timestamped scrollback snapshot to SCROLLBACK_HISTORY_DIR. Files are
|
||||
named:</p>
|
||||
<pre><code>scrollback_YYYY-MM-DD_HH-MM-SS.log</code></pre>
|
||||
<p>The paru and yay wrappers (auto-generated in ~/.local/bin/) run the
|
||||
command inside a PTY via script(1) so download progress bars are
|
||||
preserved on screen, then render the captured terminal animation down to
|
||||
a clean static log via scripts/clean_progress_log.py (a small
|
||||
terminal-screen emulator that replays cursor movements, collapses
|
||||
repainted progress frames to their final state, and preserves ANSI
|
||||
color). If python3 is unavailable the wrapper falls back to dropping
|
||||
only the script(1) header/footer. Output is saved to:</p>
|
||||
<pre><code>paru_YYYY-MM-DD_HH-MM-SS.log
|
||||
yay_YYYY-MM-DD_HH-MM-SS.log</code></pre>
|
||||
<p>Before pruning, _scrollback_prune_junk silently removes empty files,
|
||||
files with only a single meaningful line (e.g. bare [exited] captures),
|
||||
and Kitty tab-rename prompt captures. Use exit --no-log (or exit -n) to
|
||||
skip capture.</p>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,506 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>2. PATH SETUP</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="7-3-key-bindings.html" accesskey="n" rel="next">3. KEY BINDINGS</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="5-1-configuration-variables.html" accesskey="p" rel="previous">1. CONFIGURATION VARIABLES</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="6" id="2-path-setup">2. PATH SETUP</h1>
|
||||
<p>Directories prepended to PATH in this order (first wins):</p>
|
||||
<pre><code>~/.local/bin Standard user-local executables
|
||||
~/Applications User-installed standalone apps
|
||||
~/scripts Personal shell scripts
|
||||
~/bin Cargo binaries (appended — lowest priority)
|
||||
$BUN_INSTALL/bin Bun runtime and global packages
|
||||
$NPM_CONFIG_PREFIX/bin Global npm packages
|
||||
~/.lmstudio/bin LM Studio CLI
|
||||
~/.resend/bin Resend CLI
|
||||
~/.fzf/bin fzf binary (git-installed)</code></pre>
|
||||
<p>Cargo binaries are intentionally appended (lowest priority) to avoid
|
||||
shadowing system-installed Rust tools.</p>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,538 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>3. KEY BINDINGS</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="8-4-abbreviations.html" accesskey="n" rel="next">4. ABBREVIATIONS</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="6-2-path-setup.html" accesskey="p" rel="previous">2. PATH SETUP</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="7" id="3-key-bindings">3. KEY BINDINGS</h1>
|
||||
<p>The shell uses Vi key bindings (fish_vi_key_bindings). All custom
|
||||
bindings are active in Insert, Normal, and Visual modes unless
|
||||
noted.</p>
|
||||
<pre><code>Binding Action
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Ctrl+G Insert the head of the previous command's last path
|
||||
argument. Equivalent to !$:h in Bash.
|
||||
Example: previous = "cd /usr/local/bin"
|
||||
Ctrl+G inserts "/usr/local"
|
||||
|
||||
Ctrl+F Interactive history substitution. Type old/new then
|
||||
press Ctrl+F to apply s/old/new/ to the previous
|
||||
command. Equivalent to !!:s/old/new/ in Bash.
|
||||
Example: previous = "echo this is a test"
|
||||
type "this is/that was", press Ctrl+F
|
||||
result = "echo that was a test"
|
||||
|
||||
Ctrl+Alt+U Strip the first token of the current command line,
|
||||
leaving arguments in place with the cursor at the
|
||||
start. Useful for quickly retyping the command.
|
||||
Example: "mkdir new_folder" -> " new_folder"
|
||||
|
||||
Ctrl+Alt+= Evaluate the current command line buffer with
|
||||
Qalculate! (qalc) and print the result inline.
|
||||
Requires qalc to be installed.
|
||||
Example: type "150 * 1.08", press Ctrl+Alt+=
|
||||
prints 162
|
||||
|
||||
Ctrl+Enter Smart execute: runs commands instantly without
|
||||
pressing Enter a second time for certain fast-path
|
||||
commands (speedtest-fast, etc.).
|
||||
|
||||
@@ FZF inline picker. Type @@ anywhere on the command
|
||||
line to open an fzf picker and insert a selection
|
||||
at the cursor position.</code></pre>
|
||||
<h2 data-number="7.1"
|
||||
id="fzf-bindings-bundled-from-patrickf1fzffish">FZF Bindings (bundled
|
||||
from PatrickF1/fzf.fish)</h2>
|
||||
<pre><code>Ctrl+R Search command history
|
||||
Ctrl+Alt+F Search git-tracked files
|
||||
Ctrl+Alt+L Search git log
|
||||
Ctrl+Alt+S Search git status
|
||||
Ctrl+V Search shell variables
|
||||
Ctrl+Alt+P Search running processes</code></pre>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,641 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>4. ABBREVIATIONS</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up">FISH-CONFIG</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">FISH-CONFIG</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="9-5-functions-reference.html" accesskey="n" rel="next">5. FUNCTIONS REFERENCE</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Previous:</span> <a href="7-3-key-bindings.html" accesskey="p" rel="previous">3. KEY BINDINGS</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<h1 data-number="8" id="4-abbreviations">4. ABBREVIATIONS</h1>
|
||||
<p>Abbreviations expand when you press Space or Enter. They are
|
||||
terminal-aware: some expand differently in Kitty vs WezTerm vs other
|
||||
terminals.</p>
|
||||
<h2 data-number="8.1" id="41-editors">4.1 Editors</h2>
|
||||
<pre><code>n / nv / neovim nvim
|
||||
e edit
|
||||
se sudoedit
|
||||
k kate
|
||||
editt Open new tab with nvim (terminal-aware)
|
||||
cdnv cd ~/.config/nvim
|
||||
cdnvn cd ~/.config/nvim; nvim</code></pre>
|
||||
<h2 data-number="8.2" id="42-navigation-and-listing">4.2 Navigation and
|
||||
Listing</h2>
|
||||
<pre><code>l ls
|
||||
lS lss (sort by size)
|
||||
lsR lsr (sort by time, oldest first)
|
||||
lX lx (sort by extension)
|
||||
lT lt (tree, depth 2)
|
||||
lsT lstree (full recursive tree)
|
||||
lzd ld (lazydocker)
|
||||
cdi zi (interactive zoxide picker)</code></pre>
|
||||
<h2 data-number="8.3" id="43-git">4.3 Git</h2>
|
||||
<pre><code>g git
|
||||
lg lazygit
|
||||
gitig / git-ignore gi (generate .gitignore)</code></pre>
|
||||
<h2 data-number="8.4" id="44-terminal-windows-tabs-and-panes">4.4
|
||||
Terminal Windows, Tabs, and Panes</h2>
|
||||
<p>These abbreviations control the terminal emulator. Each has a Kitty
|
||||
variant and a WezTerm variant; the correct one is inserted based on
|
||||
$TERM or $TERM_PROGRAM.</p>
|
||||
<pre><code>:w New OS window
|
||||
:wv Split pane horizontally (new pane below)
|
||||
:wh Split pane vertically (new pane to the right)
|
||||
:wo Detach current window to its own OS window
|
||||
:wot Move current pane to a new tab
|
||||
:t New tab
|
||||
:tl Set tab title
|
||||
:tw Set window title
|
||||
:twk Rename workspace (WezTerm only)
|
||||
:tp Focus previous tab
|
||||
:tn Focus next tab
|
||||
:q Close current pane/window
|
||||
:Q Close current tab
|
||||
:sw spwin (spawn new OS window)</code></pre>
|
||||
<p>Quick-navigate shortcuts open windows/tabs/panes with preset working
|
||||
dirs:</p>
|
||||
<pre><code>:tgk New tab at ~/.config/kitty
|
||||
:tgn New tab at ~/.config/nvim
|
||||
:tgf New tab at ~/.config/fish
|
||||
:tgh New tab at ~
|
||||
:tgcz New tab at chezmoi source dir
|
||||
:tgcm New tab at chezmoi source dir
|
||||
:tgp New tab at ~/projects
|
||||
:tgr New tab at / (root)</code></pre>
|
||||
<p>Prefixes :wg* and :wvg* / :whg* open OS windows or splits to the same
|
||||
set of dirs, respectively.</p>
|
||||
<p>Prefixes :cd* open tabs with a quick cd shortcut:</p>
|
||||
<pre><code>:cdn cd ~/.config/nvim
|
||||
:cdf cd ~/.config/fish
|
||||
:cdh cd ~
|
||||
:cdcz cd to chezmoi source
|
||||
:cdp cd ~/projects</code></pre>
|
||||
<p>Appending n to any :cd* abbreviation also runs nvim after changing
|
||||
dir.</p>
|
||||
<h2 data-number="8.5" id="45-chezmoi">4.5 Chezmoi</h2>
|
||||
<pre><code>cm / cme / cmi / cmap / cmad / cmrm / cmcd /
|
||||
cz / cze / czi / czap / czad / czrm / czcd
|
||||
|
||||
cm / cz chezmoi
|
||||
cmcd / czcd chezmoi cd
|
||||
cme / cze chezmoi edit
|
||||
cmad / czad chezmoi add
|
||||
cmap / czap chezmoi apply
|
||||
cmrm / cmf / czrm / czf chezmoi forget
|
||||
cmi / czi chezmoi init</code></pre>
|
||||
<h2 data-number="8.6" id="46-docker">4.6 Docker</h2>
|
||||
<pre><code>dcl docker context use default
|
||||
dcls docker context ls
|
||||
lzd ld (lazydocker)</code></pre>
|
||||
<h2 data-number="8.7" id="47-systemctl">4.7 Systemctl</h2>
|
||||
<pre><code>sc systemctl
|
||||
ssc sudo systemctl
|
||||
scu systemctl --user
|
||||
st systemctl status
|
||||
scs sudo systemctl start
|
||||
scr sudo systemctl restart
|
||||
ssct sudo systemctl start
|
||||
sscs sudo systemctl stop
|
||||
sscr sudo systemctl restart</code></pre>
|
||||
<h2 data-number="8.8" id="48-ai-assistants">4.8 AI Assistants</h2>
|
||||
<pre><code>ag agy
|
||||
ag. agy .
|
||||
v antigravity-ide
|
||||
s wezterm ssh (WezTerm only)</code></pre>
|
||||
<h2 data-number="8.9" id="49-history-expansion">4.9 History
|
||||
Expansion</h2>
|
||||
<p>These are implemented as keybinding helpers, but can also be
|
||||
typed:</p>
|
||||
<pre><code>!^ Expand to first argument of previous command
|
||||
!* Expand to all arguments of previous command
|
||||
typo_sub Interactive typo substitution (Ctrl+F)
|
||||
bang_string !string expansion
|
||||
bang_search !?string search
|
||||
bang_minus_n !-n (nth-previous command)</code></pre>
|
||||
<h2 data-number="8.10" id="410-miscellaneous">4.10 Miscellaneous</h2>
|
||||
<pre><code>/exit exit
|
||||
:q Close pane (alias for terminal close)
|
||||
:Q Close tab
|
||||
sudu sudo -s
|
||||
kt kitty (Kitty only)
|
||||
c cat
|
||||
speedtest-fast fast-cli
|
||||
bl bd list
|
||||
bs bd sync
|
||||
bC bd create --title
|
||||
bsh bd show
|
||||
lb lazybeads</code></pre>
|
||||
<h2 data-number="8.11" id="411-shell-aliases">4.11 Shell Aliases</h2>
|
||||
<p>These aliases are defined in conf.d/tricks.fish via alias (which
|
||||
creates Fish functions). They are active in all interactive
|
||||
sessions.</p>
|
||||
<h3 data-number="8.11.1" id="navigation">Navigation</h3>
|
||||
<pre><code>.. cd ..
|
||||
... cd ../..
|
||||
.... cd ../../..
|
||||
..... cd ../../../..
|
||||
...... cd ../../../../..</code></pre>
|
||||
<h3 data-number="8.11.2" id="color-overrides">Color Overrides</h3>
|
||||
<p>Force color output for common tools:</p>
|
||||
<pre><code>grep grep --color=auto
|
||||
fgrep fgrep --color=auto
|
||||
egrep egrep --color=auto
|
||||
dir dir --color=auto
|
||||
vdir vdir --color=auto</code></pre>
|
||||
<h3 data-number="8.11.3" id="safety-wrappers">Safety Wrappers</h3>
|
||||
<p>Add -i (interactive confirmation) to destructive commands:</p>
|
||||
<pre><code>cp cp -i
|
||||
mv mv -i</code></pre>
|
||||
<h3 data-number="8.11.4" id="archives-and-networking">Archives and
|
||||
Networking</h3>
|
||||
<pre><code>tarnow tar -acf Create compressed archive (auto-detects format)
|
||||
untar tar -zxvf Extract a gzip-compressed archive
|
||||
wget wget -c Resume interrupted downloads by default
|
||||
tb nc termbin.com 9999 Pipe content to termbin.com for quick sharing</code></pre>
|
||||
<h3 data-number="8.11.5" id="system-logs">System Logs</h3>
|
||||
<pre><code>jctl journalctl -p 3 -xb Show priority-3 (error) journal entries
|
||||
from the current boot</code></pre>
|
||||
<hr />
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,903 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<meta name="author" content="Rootiest" />
|
||||
<title>FISH-CONFIG</title>
|
||||
<style>
|
||||
div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }
|
||||
span.navlink { flex: 1; }
|
||||
span.navlink-label { display: inline-block; min-width: 4em; }
|
||||
html {
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
overflow-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 12px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
html {
|
||||
background-color: white;
|
||||
}
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
hyphens: manual;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC ul {
|
||||
padding-left: 1.3em;
|
||||
}
|
||||
#TOC > ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
/* The extra [class] is a hack that increases specificity enough to
|
||||
override a similar rule in reveal.js */
|
||||
ul.task-list[class]{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
font-size: inherit;
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<style>
|
||||
/* ── Catppuccin Latte (light) / Mocha (dark) ─────────────────── */
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--bg: #eff1f5;
|
||||
--surface: #e6e9ef;
|
||||
--overlay: #ccd0da;
|
||||
--text: #4c4f69;
|
||||
--sub1: #6c6f85;
|
||||
--sub0: #8c8fa1;
|
||||
--blue: #1e66f5;
|
||||
--lavender: #7287fd;
|
||||
--sapphire: #209fb5;
|
||||
--green: #40a02b;
|
||||
--yellow: #df8e1d;
|
||||
--peach: #fe640b;
|
||||
--mauve: #8839ef;
|
||||
--code-bg: #dce0e8;
|
||||
--border: #bcc0cc;
|
||||
--glow1: rgba(30, 102, 245, 0.05);
|
||||
--glow2: rgba(136, 57, 239, 0.04);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #1e1e2e;
|
||||
--surface: #313244;
|
||||
--overlay: #45475a;
|
||||
--text: #cdd6f4;
|
||||
--sub1: #bac2de;
|
||||
--sub0: #a6adc8;
|
||||
--blue: #89b4fa;
|
||||
--lavender: #b4befe;
|
||||
--sapphire: #74c7ec;
|
||||
--green: #a6e3a1;
|
||||
--yellow: #f9e2af;
|
||||
--peach: #fab387;
|
||||
--mauve: #cba6f7;
|
||||
--code-bg: #181825;
|
||||
--border: #45475a;
|
||||
--glow1: rgba(137, 180, 250, 0.06);
|
||||
--glow2: rgba(203, 166, 247, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse 55% 40% at 10% 5%, var(--glow1) 0%, transparent 100%),
|
||||
radial-gradient(ellipse 45% 45% at 90% 95%, var(--glow2) 0%, transparent 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 2.5rem 5rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────── */
|
||||
a { color: var(--blue); text-decoration: none; }
|
||||
a:hover { color: var(--lavender); text-decoration: underline; }
|
||||
a:visited { color: var(--lavender); }
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────── */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
color: var(--lavender);
|
||||
line-height: 1.3;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.9rem;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.4em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.35rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
h3 { font-size: 1.1rem; color: var(--sapphire); }
|
||||
h4 { font-size: 0.95rem; color: var(--sub1); }
|
||||
|
||||
p { margin: 0.8em 0; }
|
||||
|
||||
/* ── Title block (pandoc-generated cover) ──────────────────── */
|
||||
#title-block-header {
|
||||
text-align: center;
|
||||
padding: 2.5rem 0 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
#title-block-header .title {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 2.6rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--lavender);
|
||||
border: none;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
#title-block-header .author,
|
||||
#title-block-header .date {
|
||||
color: var(--sub0);
|
||||
font-size: 0.875rem;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────── */
|
||||
code {
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
background: var(--code-bg);
|
||||
color: var(--peach);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
/* ── Code blocks ───────────────────────────────────────────── */
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--sapphire);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.1em 1.4em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.55;
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
color: var(--text);
|
||||
padding: 0;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* ── Blockquotes ───────────────────────────────────────────── */
|
||||
blockquote {
|
||||
border-left: 3px solid var(--yellow);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.75em 1.25em;
|
||||
background: var(--surface);
|
||||
color: var(--sub1);
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
blockquote p { margin: 0.3em 0; }
|
||||
|
||||
/* ── Tables ────────────────────────────────────────────────── */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1.4em 0;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.55em 0.9em;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: var(--surface);
|
||||
color: var(--lavender);
|
||||
font-weight: 600;
|
||||
font-family: "JetBrains Mono", "Fira Code", ui-monospace, monospace;
|
||||
font-size: 0.82em;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
tr:nth-child(even) { background: var(--surface); }
|
||||
tr:hover { background: var(--overlay); }
|
||||
|
||||
/* ── HR ────────────────────────────────────────────────────── */
|
||||
hr { border: none; border-top: 1px solid var(--border); margin: 2.5em 0; }
|
||||
|
||||
/* ── Lists ─────────────────────────────────────────────────── */
|
||||
ul, ol { padding-left: 1.6em; }
|
||||
li { margin: 0.35em 0; }
|
||||
|
||||
/* ── Chunk navigation bar (prev / up / next) ───────────────── */
|
||||
nav:not(#TOC):not([role="doc-toc"]) {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
margin: 1.5em 0;
|
||||
font-size: 0.875em;
|
||||
overflow: hidden;
|
||||
}
|
||||
nav:not(#TOC):not([role="doc-toc"]) p {
|
||||
margin: 0;
|
||||
padding: 0.65em 1.2em;
|
||||
display: flex;
|
||||
gap: 0.4em 1.75em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
/* JS wraps each "Label: <a>" pair in .nav-item so they flex as a unit */
|
||||
.nav-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-item a { color: var(--blue); }
|
||||
.nav-item a:hover { color: var(--lavender); }
|
||||
|
||||
/* ── Table of contents panel ───────────────────────────────── */
|
||||
nav#TOC, nav[role="doc-toc"] {
|
||||
display: block;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--lavender);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.2em 1.5em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
nav#TOC > h2,
|
||||
nav[role="doc-toc"] > h2 {
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sub0);
|
||||
border: none;
|
||||
margin: 0 0 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
nav#TOC ul, nav[role="doc-toc"] ul {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
nav#TOC > ul, nav[role="doc-toc"] > ul { padding-left: 0; }
|
||||
nav#TOC li, nav[role="doc-toc"] li {
|
||||
margin: 0.3em 0;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid transparent;
|
||||
transition: border-color 0.12s;
|
||||
}
|
||||
nav#TOC li:hover, nav[role="doc-toc"] li:hover {
|
||||
border-left-color: var(--lavender);
|
||||
}
|
||||
nav#TOC a, nav[role="doc-toc"] a {
|
||||
color: var(--sub1);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
nav#TOC a:hover, nav[role="doc-toc"] a:hover {
|
||||
color: var(--lavender);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* ── Hide ToC on every page except index.html ───────────── */
|
||||
var path = location.pathname;
|
||||
var onIndex = path === '/' || path === '' || /\/index\.html(\?.*)?$/.test(path);
|
||||
if (!onIndex) {
|
||||
var toc = document.getElementById('TOC') ||
|
||||
document.querySelector('[role="doc-toc"]');
|
||||
if (toc) toc.remove();
|
||||
}
|
||||
|
||||
/* ── Wrap each "Label: <a>" pair in a .nav-item span ───────
|
||||
Pandoc emits label text nodes and anchors as siblings;
|
||||
flex sees them as separate items, causing labels to split
|
||||
from their links when wrapping. Grouping them in a span
|
||||
keeps each label+link as a single flex unit. */
|
||||
document.querySelectorAll('nav:not(#TOC):not([role="doc-toc"])').forEach(function (nav) {
|
||||
var p = nav.querySelector('p');
|
||||
if (!p) return;
|
||||
var children = Array.from(p.childNodes);
|
||||
var pairs = [];
|
||||
for (var i = 0; i + 1 < children.length; i++) {
|
||||
var cur = children[i];
|
||||
var nxt = children[i + 1];
|
||||
if (cur.nodeType === Node.TEXT_NODE &&
|
||||
/[A-Z][a-z]*:\s*/.test(cur.textContent) &&
|
||||
nxt.nodeType === Node.ELEMENT_NODE &&
|
||||
nxt.tagName === 'A') {
|
||||
pairs.push([cur, nxt]);
|
||||
i++; // skip the anchor on the next iteration
|
||||
}
|
||||
}
|
||||
pairs.forEach(function (pair) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'nav-item';
|
||||
p.insertBefore(span, pair[0]);
|
||||
span.appendChild(pair[0]);
|
||||
span.appendChild(pair[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav id="sitenav">
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
</span>
|
||||
<span class="navlink">
|
||||
</span>
|
||||
</div>
|
||||
<div class="sitenav">
|
||||
<span class="navlink">
|
||||
<span class="navlink-label">Next:</span> <a href="1-name.html" accesskey="n" rel="next">NAME</a>
|
||||
</span>
|
||||
<span class="navlink">
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
<header id="title-block-header">
|
||||
<h1 class="title">FISH-CONFIG</h1>
|
||||
<p class="author">Rootiest</p>
|
||||
<p class="date">June 2026</p>
|
||||
</header>
|
||||
<nav id="TOC" role="doc-toc">
|
||||
<ul>
|
||||
<li><a href="1-name.html" id="toc-name">NAME</a></li>
|
||||
<li><a href="2-synopsis.html" id="toc-synopsis">SYNOPSIS</a></li>
|
||||
<li><a href="3-description.html"
|
||||
id="toc-description">DESCRIPTION</a></li>
|
||||
<li><a href="4-table-of-contents.html" id="toc-table-of-contents">TABLE
|
||||
OF CONTENTS</a></li>
|
||||
<li><a href="5-1-configuration-variables.html"
|
||||
id="toc-1-configuration-variables">1. CONFIGURATION VARIABLES</a>
|
||||
<ul>
|
||||
<li><a
|
||||
href="5-1-configuration-variables.html#environment-directories-xdg"
|
||||
id="toc-environment-directories-xdg">Environment Directories
|
||||
(XDG)</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#tool-homes-xdg-compliant"
|
||||
id="toc-tool-homes-xdg-compliant">Tool Homes (XDG-compliant)</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#editor-and-pager"
|
||||
id="toc-editor-and-pager">Editor and Pager</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#scrollback-history"
|
||||
id="toc-scrollback-history">Scrollback History</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#other"
|
||||
id="toc-other">Other</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#pager-hierarchy"
|
||||
id="toc-pager-hierarchy">Pager Hierarchy</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#integrations"
|
||||
id="toc-integrations">Integrations</a>
|
||||
<ul>
|
||||
<li><a href="5-1-configuration-variables.html#zoxide"
|
||||
id="toc-zoxide">Zoxide</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#direnv"
|
||||
id="toc-direnv">DirEnv</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#auto-python-venv"
|
||||
id="toc-auto-python-venv">Auto Python Venv</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#wakatime"
|
||||
id="toc-wakatime">WakaTime</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#tailscale"
|
||||
id="toc-tailscale">Tailscale</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#done-notifications"
|
||||
id="toc-done-notifications">Done Notifications</a></li>
|
||||
<li><a href="5-1-configuration-variables.html#scrollback-history-1"
|
||||
id="toc-scrollback-history-1">Scrollback History</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
<li><a href="6-2-path-setup.html" id="toc-2-path-setup">2. PATH
|
||||
SETUP</a></li>
|
||||
<li><a href="7-3-key-bindings.html" id="toc-3-key-bindings">3. KEY
|
||||
BINDINGS</a>
|
||||
<ul>
|
||||
<li><a
|
||||
href="7-3-key-bindings.html#fzf-bindings-bundled-from-patrickf1fzffish"
|
||||
id="toc-fzf-bindings-bundled-from-patrickf1fzffish">FZF Bindings
|
||||
(bundled from PatrickF1/fzf.fish)</a></li>
|
||||
</ul></li>
|
||||
<li><a href="8-4-abbreviations.html" id="toc-4-abbreviations">4.
|
||||
ABBREVIATIONS</a>
|
||||
<ul>
|
||||
<li><a href="8-4-abbreviations.html#41-editors" id="toc-41-editors">4.1
|
||||
Editors</a></li>
|
||||
<li><a href="8-4-abbreviations.html#42-navigation-and-listing"
|
||||
id="toc-42-navigation-and-listing">4.2 Navigation and Listing</a></li>
|
||||
<li><a href="8-4-abbreviations.html#43-git" id="toc-43-git">4.3
|
||||
Git</a></li>
|
||||
<li><a href="8-4-abbreviations.html#44-terminal-windows-tabs-and-panes"
|
||||
id="toc-44-terminal-windows-tabs-and-panes">4.4 Terminal Windows, Tabs,
|
||||
and Panes</a></li>
|
||||
<li><a href="8-4-abbreviations.html#45-chezmoi" id="toc-45-chezmoi">4.5
|
||||
Chezmoi</a></li>
|
||||
<li><a href="8-4-abbreviations.html#46-docker" id="toc-46-docker">4.6
|
||||
Docker</a></li>
|
||||
<li><a href="8-4-abbreviations.html#47-systemctl"
|
||||
id="toc-47-systemctl">4.7 Systemctl</a></li>
|
||||
<li><a href="8-4-abbreviations.html#48-ai-assistants"
|
||||
id="toc-48-ai-assistants">4.8 AI Assistants</a></li>
|
||||
<li><a href="8-4-abbreviations.html#49-history-expansion"
|
||||
id="toc-49-history-expansion">4.9 History Expansion</a></li>
|
||||
<li><a href="8-4-abbreviations.html#410-miscellaneous"
|
||||
id="toc-410-miscellaneous">4.10 Miscellaneous</a></li>
|
||||
<li><a href="8-4-abbreviations.html#411-shell-aliases"
|
||||
id="toc-411-shell-aliases">4.11 Shell Aliases</a>
|
||||
<ul>
|
||||
<li><a href="8-4-abbreviations.html#navigation"
|
||||
id="toc-navigation">Navigation</a></li>
|
||||
<li><a href="8-4-abbreviations.html#color-overrides"
|
||||
id="toc-color-overrides">Color Overrides</a></li>
|
||||
<li><a href="8-4-abbreviations.html#safety-wrappers"
|
||||
id="toc-safety-wrappers">Safety Wrappers</a></li>
|
||||
<li><a href="8-4-abbreviations.html#archives-and-networking"
|
||||
id="toc-archives-and-networking">Archives and Networking</a></li>
|
||||
<li><a href="8-4-abbreviations.html#system-logs"
|
||||
id="toc-system-logs">System Logs</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html"
|
||||
id="toc-5-functions-reference">5. FUNCTIONS REFERENCE</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#51-file-and-directory"
|
||||
id="toc-51-file-and-directory">5.1 File and Directory</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#cat" id="toc-cat">cat</a></li>
|
||||
<li><a href="9-5-functions-reference.html#copy"
|
||||
id="toc-copy">copy</a></li>
|
||||
<li><a href="9-5-functions-reference.html#du" id="toc-du">du</a></li>
|
||||
<li><a href="9-5-functions-reference.html#dusize"
|
||||
id="toc-dusize">dusize</a></li>
|
||||
<li><a href="9-5-functions-reference.html#ld" id="toc-ld">lD</a></li>
|
||||
<li><a href="9-5-functions-reference.html#ls" id="toc-ls">ls</a></li>
|
||||
<li><a href="9-5-functions-reference.html#lsr" id="toc-lsr">lsr</a></li>
|
||||
<li><a href="9-5-functions-reference.html#lss" id="toc-lss">lss</a></li>
|
||||
<li><a href="9-5-functions-reference.html#lstree"
|
||||
id="toc-lstree">lstree</a></li>
|
||||
<li><a href="9-5-functions-reference.html#lt" id="toc-lt">lt</a></li>
|
||||
<li><a href="9-5-functions-reference.html#ltr" id="toc-ltr">ltr</a></li>
|
||||
<li><a href="9-5-functions-reference.html#lx" id="toc-lx">lx</a></li>
|
||||
<li><a href="9-5-functions-reference.html#mkdir"
|
||||
id="toc-mkdir">mkdir</a></li>
|
||||
<li><a href="9-5-functions-reference.html#mkcd"
|
||||
id="toc-mkcd">mkcd</a></li>
|
||||
<li><a href="9-5-functions-reference.html#poke"
|
||||
id="toc-poke">poke</a></li>
|
||||
<li><a href="9-5-functions-reference.html#rm" id="toc-rm">rm</a></li>
|
||||
<li><a href="9-5-functions-reference.html#rg" id="toc-rg">rg</a></li>
|
||||
<li><a href="9-5-functions-reference.html#scrub"
|
||||
id="toc-scrub">scrub</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#52-navigation"
|
||||
id="toc-52-navigation">5.2 Navigation</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#cdi" id="toc-cdi">cdi</a></li>
|
||||
<li><a href="9-5-functions-reference.html#clone"
|
||||
id="toc-clone">clone</a></li>
|
||||
<li><a href="9-5-functions-reference.html#clonet"
|
||||
id="toc-clonet">clonet</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#53-editors-and-viewers"
|
||||
id="toc-53-editors-and-viewers">5.3 Editors and Viewers</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#edit"
|
||||
id="toc-edit">edit</a></li>
|
||||
<li><a href="9-5-functions-reference.html#fc" id="toc-fc">fc</a></li>
|
||||
<li><a href="9-5-functions-reference.html#less"
|
||||
id="toc-less">less</a></li>
|
||||
<li><a href="9-5-functions-reference.html#rawfish"
|
||||
id="toc-rawfish">rawfish</a></li>
|
||||
<li><a href="9-5-functions-reference.html#view"
|
||||
id="toc-view">view</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#54-git-and-version-control"
|
||||
id="toc-54-git-and-version-control">5.4 Git and Version Control</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#auto-pull"
|
||||
id="toc-auto-pull">auto-pull</a></li>
|
||||
<li><a href="9-5-functions-reference.html#branch"
|
||||
id="toc-branch">branch</a></li>
|
||||
<li><a href="9-5-functions-reference.html#gi" id="toc-gi">gi</a></li>
|
||||
<li><a href="9-5-functions-reference.html#git-clean"
|
||||
id="toc-git-clean">git-clean</a></li>
|
||||
<li><a href="9-5-functions-reference.html#gitup"
|
||||
id="toc-gitup">gitup</a></li>
|
||||
<li><a href="9-5-functions-reference.html#gitui"
|
||||
id="toc-gitui">gitui</a></li>
|
||||
<li><a href="9-5-functions-reference.html#hist"
|
||||
id="toc-hist">hist</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#55-package-management"
|
||||
id="toc-55-package-management">5.5 Package Management</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#pkg" id="toc-pkg">pkg</a></li>
|
||||
<li><a href="9-5-functions-reference.html#search"
|
||||
id="toc-search">search</a></li>
|
||||
<li><a href="9-5-functions-reference.html#upgrade"
|
||||
id="toc-upgrade">upgrade</a></li>
|
||||
<li><a href="9-5-functions-reference.html#cleanup"
|
||||
id="toc-cleanup">cleanup</a></li>
|
||||
<li><a href="9-5-functions-reference.html#parur"
|
||||
id="toc-parur">parur</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#56-dependency-management"
|
||||
id="toc-56-dependency-management">5.6 Dependency Management</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#fish-deps"
|
||||
id="toc-fish-deps">fish-deps</a></li>
|
||||
<li><a href="9-5-functions-reference.html#check_fish_deps"
|
||||
id="toc-check_fish_deps">check_fish_deps</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#57-system-and-monitoring"
|
||||
id="toc-57-system-and-monitoring">5.7 System and Monitoring</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#top" id="toc-top">top</a></li>
|
||||
<li><a href="9-5-functions-reference.html#swapstat"
|
||||
id="toc-swapstat">swapstat</a></li>
|
||||
<li><a href="9-5-functions-reference.html#sbver"
|
||||
id="toc-sbver">sbver</a></li>
|
||||
<li><a href="9-5-functions-reference.html#ports"
|
||||
id="toc-ports">ports</a></li>
|
||||
<li><a href="9-5-functions-reference.html#screensleep"
|
||||
id="toc-screensleep">screensleep</a></li>
|
||||
<li><a href="9-5-functions-reference.html#lock"
|
||||
id="toc-lock">lock</a></li>
|
||||
<li><a href="9-5-functions-reference.html#sudo-toggle"
|
||||
id="toc-sudo-toggle">sudo-toggle</a></li>
|
||||
<li><a href="9-5-functions-reference.html#limine-edit"
|
||||
id="toc-limine-edit">limine-edit</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#58-terminal-management"
|
||||
id="toc-58-terminal-management">5.8 Terminal Management</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#tab" id="toc-tab">tab</a></li>
|
||||
<li><a href="9-5-functions-reference.html#split"
|
||||
id="toc-split">split</a></li>
|
||||
<li><a href="9-5-functions-reference.html#spwin"
|
||||
id="toc-spwin">spwin</a></li>
|
||||
<li><a href="9-5-functions-reference.html#detach"
|
||||
id="toc-detach">detach</a></li>
|
||||
<li><a href="9-5-functions-reference.html#bkg" id="toc-bkg">bkg</a></li>
|
||||
<li><a href="9-5-functions-reference.html#ssh" id="toc-ssh">ssh</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#59-clipboard"
|
||||
id="toc-59-clipboard">5.9 Clipboard</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#y" id="toc-y">y</a></li>
|
||||
<li><a href="9-5-functions-reference.html#p" id="toc-p">p</a></li>
|
||||
<li><a href="9-5-functions-reference.html#paste"
|
||||
id="toc-paste">paste</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#510-network"
|
||||
id="toc-510-network">5.10 Network</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#gip" id="toc-gip">gip</a></li>
|
||||
<li><a href="9-5-functions-reference.html#gip4"
|
||||
id="toc-gip4">gip4</a></li>
|
||||
<li><a href="9-5-functions-reference.html#gip6"
|
||||
id="toc-gip6">gip6</a></li>
|
||||
<li><a href="9-5-functions-reference.html#ping"
|
||||
id="toc-ping">ping</a></li>
|
||||
<li><a href="9-5-functions-reference.html#qr" id="toc-qr">qr</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#511-pager-and-logging"
|
||||
id="toc-511-pager-and-logging">5.11 Pager and Logging</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#logs"
|
||||
id="toc-logs">logs</a></li>
|
||||
<li><a href="9-5-functions-reference.html#smart_exit"
|
||||
id="toc-smart_exit">smart_exit</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#512-ai-and-developer-tools"
|
||||
id="toc-512-ai-and-developer-tools">5.12 AI and Developer Tools</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#agy" id="toc-agy">agy</a></li>
|
||||
<li><a href="9-5-functions-reference.html#antigravity-ide"
|
||||
id="toc-antigravity-ide">antigravity-ide</a></li>
|
||||
<li><a href="9-5-functions-reference.html#agents-init"
|
||||
id="toc-agents-init">agents-init</a></li>
|
||||
<li><a href="9-5-functions-reference.html#claude"
|
||||
id="toc-claude">claude</a></li>
|
||||
<li><a href="9-5-functions-reference.html#claude-docs"
|
||||
id="toc-claude-docs">claude-docs</a></li>
|
||||
<li><a href="9-5-functions-reference.html#claude-pr"
|
||||
id="toc-claude-pr">claude-pr</a></li>
|
||||
<li><a href="9-5-functions-reference.html#qc" id="toc-qc">qc</a></li>
|
||||
<li><a href="9-5-functions-reference.html#superpowers"
|
||||
id="toc-superpowers">superpowers</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#513-media-and-utilities"
|
||||
id="toc-513-media-and-utilities">5.13 Media and Utilities</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#dng2avif"
|
||||
id="toc-dng2avif">dng2avif</a></li>
|
||||
<li><a href="9-5-functions-reference.html#steam-dl"
|
||||
id="toc-steam-dl">steam-dl</a></li>
|
||||
<li><a href="9-5-functions-reference.html#spark"
|
||||
id="toc-spark">spark</a></li>
|
||||
<li><a href="9-5-functions-reference.html#yt-dlp"
|
||||
id="toc-yt-dlp">yt-dlp</a></li>
|
||||
</ul></li>
|
||||
<li><a href="9-5-functions-reference.html#514-miscellaneous"
|
||||
id="toc-514-miscellaneous">5.14 Miscellaneous</a>
|
||||
<ul>
|
||||
<li><a href="9-5-functions-reference.html#config-help"
|
||||
id="toc-config-help">config-help</a></li>
|
||||
<li><a href="9-5-functions-reference.html#open-url"
|
||||
id="toc-open-url">open-url</a></li>
|
||||
<li><a href="9-5-functions-reference.html#repo-open"
|
||||
id="toc-repo-open">repo-open</a></li>
|
||||
<li><a href="9-5-functions-reference.html#config-update"
|
||||
id="toc-config-update">config-update</a></li>
|
||||
<li><a href="9-5-functions-reference.html#config-settings"
|
||||
id="toc-config-settings">config-settings</a></li>
|
||||
<li><a href="9-5-functions-reference.html#config-toggle-deprecated"
|
||||
id="toc-config-toggle-deprecated">config-toggle (deprecated)</a></li>
|
||||
<li><a href="9-5-functions-reference.html#bash"
|
||||
id="toc-bash">bash</a></li>
|
||||
<li><a href="9-5-functions-reference.html#bd-pull"
|
||||
id="toc-bd-pull">bd-pull</a></li>
|
||||
<li><a href="9-5-functions-reference.html#cheat"
|
||||
id="toc-cheat">cheat</a></li>
|
||||
<li><a href="9-5-functions-reference.html#cffetch--ffetch"
|
||||
id="toc-cffetch--ffetch">cffetch / ffetch</a></li>
|
||||
<li><a href="9-5-functions-reference.html#dockup"
|
||||
id="toc-dockup">dockup</a></li>
|
||||
<li><a href="9-5-functions-reference.html#joplin"
|
||||
id="toc-joplin">joplin</a></li>
|
||||
<li><a href="9-5-functions-reference.html#ld-1"
|
||||
id="toc-ld-1">ld</a></li>
|
||||
<li><a href="9-5-functions-reference.html#replay"
|
||||
id="toc-replay">replay</a></li>
|
||||
<li><a href="9-5-functions-reference.html#kitty-logging"
|
||||
id="toc-kitty-logging">kitty-logging</a></li>
|
||||
<li><a href="9-5-functions-reference.html#tmux-clean"
|
||||
id="toc-tmux-clean">tmux-clean</a></li>
|
||||
<li><a href="9-5-functions-reference.html#wake-lock"
|
||||
id="toc-wake-lock">wake-lock</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
<li><a href="10-6-dependency-catalog.html"
|
||||
id="toc-6-dependency-catalog">6. DEPENDENCY CATALOG</a>
|
||||
<ul>
|
||||
<li><a href="10-6-dependency-catalog.html#required"
|
||||
id="toc-required">Required</a></li>
|
||||
<li><a href="10-6-dependency-catalog.html#integrations-1"
|
||||
id="toc-integrations-1">Integrations</a></li>
|
||||
<li><a href="10-6-dependency-catalog.html#recommended"
|
||||
id="toc-recommended">Recommended</a></li>
|
||||
<li><a href="10-6-dependency-catalog.html#install-methods"
|
||||
id="toc-install-methods">Install Methods</a></li>
|
||||
</ul></li>
|
||||
<li><a href="11-7-customization.html" id="toc-7-customization">7.
|
||||
CUSTOMIZATION</a>
|
||||
<ul>
|
||||
<li><a href="11-7-customization.html#machine-local-configuration"
|
||||
id="toc-machine-local-configuration">Machine-local
|
||||
Configuration</a></li>
|
||||
<li><a href="11-7-customization.html#secrets-and-api-keys"
|
||||
id="toc-secrets-and-api-keys">Secrets and API Keys</a></li>
|
||||
<li><a href="11-7-customization.html#overriding-configuration-variables"
|
||||
id="toc-overriding-configuration-variables">Overriding Configuration
|
||||
Variables</a></li>
|
||||
<li><a href="11-7-customization.html#fish-universal-variables"
|
||||
id="toc-fish-universal-variables">Fish Universal Variables</a></li>
|
||||
<li><a
|
||||
href="11-7-customization.html#opinionated-components-minimal-mode"
|
||||
id="toc-opinionated-components-minimal-mode">Opinionated Components
|
||||
(Minimal Mode)</a>
|
||||
<ul>
|
||||
<li><a href="11-7-customization.html#component-reference"
|
||||
id="toc-component-reference">Component Reference</a></li>
|
||||
</ul></li>
|
||||
<li><a href="11-7-customization.html#prompt-and-theme"
|
||||
id="toc-prompt-and-theme">Prompt and Theme</a>
|
||||
<ul>
|
||||
<li><a href="11-7-customization.html#starship"
|
||||
id="toc-starship">Starship</a></li>
|
||||
<li><a href="11-7-customization.html#catppuccin-fallback-prompt"
|
||||
id="toc-catppuccin-fallback-prompt">Catppuccin Fallback Prompt</a></li>
|
||||
<li><a href="11-7-customization.html#fzf" id="toc-fzf">FZF</a></li>
|
||||
<li><a
|
||||
href="11-7-customization.html#catppuccin-mocha-syntax-highlighting"
|
||||
id="toc-catppuccin-mocha-syntax-highlighting">Catppuccin Mocha Syntax
|
||||
Highlighting</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
<li><a href="12-8-fisher-plugins.html" id="toc-8-fisher-plugins">8.
|
||||
FISHER PLUGINS</a>
|
||||
<ul>
|
||||
<li><a href="12-8-fisher-plugins.html#fisher-managed-plugins"
|
||||
id="toc-fisher-managed-plugins">Fisher-Managed Plugins</a></li>
|
||||
<li><a href="12-8-fisher-plugins.html#sponge-history-filtering"
|
||||
id="toc-sponge-history-filtering">Sponge History Filtering</a></li>
|
||||
<li><a href="12-8-fisher-plugins.html#bundled-plugin-functionality"
|
||||
id="toc-bundled-plugin-functionality">Bundled Plugin
|
||||
Functionality</a></li>
|
||||
<li><a href="12-8-fisher-plugins.html#fish_plugins-manifest"
|
||||
id="toc-fish_plugins-manifest">fish_plugins Manifest</a></li>
|
||||
</ul></li>
|
||||
<li><a href="13-9-installation.html" id="toc-9-installation">9.
|
||||
INSTALLATION</a>
|
||||
<ul>
|
||||
<li><a href="13-9-installation.html#return-sentinel"
|
||||
id="toc-return-sentinel">Return Sentinel</a></li>
|
||||
<li><a href="13-9-installation.html#updating"
|
||||
id="toc-updating">Updating</a></li>
|
||||
</ul></li>
|
||||
<li><a href="14-10-personalization.html" id="toc-10-personalization">10.
|
||||
PERSONALIZATION</a>
|
||||
<ul>
|
||||
<li><a href="14-10-personalization.html#secretsfish"
|
||||
id="toc-secretsfish">secrets.fish</a></li>
|
||||
<li><a href="14-10-personalization.html#localfish"
|
||||
id="toc-localfish">local.fish</a></li>
|
||||
</ul></li>
|
||||
<li><a href="15-11-viewing-this-manual.html"
|
||||
id="toc-11-viewing-this-manual">11. VIEWING THIS MANUAL</a>
|
||||
<ul>
|
||||
<li><a href="15-11-viewing-this-manual.html#with-ov-recommended"
|
||||
id="toc-with-ov-recommended">With ov (recommended)</a></li>
|
||||
<li><a href="15-11-viewing-this-manual.html#with-bat"
|
||||
id="toc-with-bat">With bat</a></li>
|
||||
<li><a href="15-11-viewing-this-manual.html#as-a-man-page"
|
||||
id="toc-as-a-man-page">As a man page</a></li>
|
||||
<li><a href="15-11-viewing-this-manual.html#in-the-browser-html"
|
||||
id="toc-in-the-browser-html">In the browser (HTML)</a></li>
|
||||
<li><a href="15-11-viewing-this-manual.html#as-a-wiki"
|
||||
id="toc-as-a-wiki">As a wiki</a></li>
|
||||
<li><a href="15-11-viewing-this-manual.html#jumping-to-a-section"
|
||||
id="toc-jumping-to-a-section">Jumping to a section</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: Name
|
||||
manTitle: NAME
|
||||
man: true
|
||||
site: false
|
||||
sidebar:
|
||||
order: 1
|
||||
---
|
||||
|
||||
fish-config - personal fish shell configuration for Fish 4.x with modern CLI tool integration
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
title: Synopsis
|
||||
manTitle: SYNOPSIS
|
||||
man: true
|
||||
site: false
|
||||
sidebar:
|
||||
order: 2
|
||||
---
|
||||
|
||||
help config [SECTION]
|
||||
|
||||
Open this manual in the best available pager. Optionally jump to a section
|
||||
by keyword:
|
||||
|
||||
help config keybindings
|
||||
help config pkg
|
||||
help config abbreviations
|
||||
help config logs
|
||||
|
||||
The `help config` syntax integrates with fish's built-in help command.
|
||||
The underlying `config-help` function is also available directly.
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Table Of Contents
|
||||
manTitle: TABLE OF CONTENTS
|
||||
man: true
|
||||
site: false
|
||||
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. Viewing This Manual
|
||||
|
||||
---
|
||||
@@ -1,7 +1,11 @@
|
||||
# 1. CONFIGURATION VARIABLES
|
||||
|
||||
**Sections:** [Index](index.md) | **1. Configuration Variables** | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
|
||||
---
|
||||
title: Configuration Variables
|
||||
manTitle: 1. CONFIGURATION VARIABLES
|
||||
sidebar:
|
||||
order: 5
|
||||
helpKeywords:
|
||||
- variables
|
||||
- config
|
||||
---
|
||||
|
||||
These variables are exported from config.fish on every interactive session.
|
||||
@@ -1,7 +1,10 @@
|
||||
# 2. PATH SETUP
|
||||
|
||||
**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | **2. Path Setup** | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
|
||||
---
|
||||
title: Path Setup
|
||||
manTitle: 2. PATH SETUP
|
||||
sidebar:
|
||||
order: 6
|
||||
helpKeywords:
|
||||
- path
|
||||
---
|
||||
|
||||
Directories prepended to PATH in this order (first wins):
|
||||
@@ -1,7 +1,13 @@
|
||||
# 3. KEY BINDINGS
|
||||
|
||||
**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | **3. Key Bindings** | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
|
||||
---
|
||||
title: Key Bindings
|
||||
manTitle: 3. KEY BINDINGS
|
||||
sidebar:
|
||||
order: 7
|
||||
helpKeywords:
|
||||
- keybindings
|
||||
- bindings
|
||||
- key-bindings
|
||||
- keys
|
||||
---
|
||||
|
||||
The shell uses Vi key bindings (fish_vi_key_bindings). All custom bindings
|
||||
@@ -1,7 +1,12 @@
|
||||
# 4. ABBREVIATIONS
|
||||
|
||||
**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | **4. Abbreviations** | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
|
||||
---
|
||||
title: Abbreviations
|
||||
manTitle: 4. ABBREVIATIONS
|
||||
sidebar:
|
||||
order: 8
|
||||
helpKeywords:
|
||||
- abbreviations
|
||||
- abbr
|
||||
- abbrs
|
||||
---
|
||||
|
||||
Abbreviations expand when you press Space or Enter. They are terminal-aware:
|
||||
@@ -0,0 +1,164 @@
|
||||
---
|
||||
title: File and Directory
|
||||
manTitle: 5.1 File and Directory
|
||||
sidebar:
|
||||
order: 1
|
||||
helpKeywords:
|
||||
- files
|
||||
---
|
||||
|
||||
## cat
|
||||
|
||||
Synopsis: cat [args...]
|
||||
Wraps bat for files with syntax highlighting and line numbers.
|
||||
Passes directories to ls. Falls back to /usr/bin/cat.
|
||||
|
||||
cat README.md
|
||||
cat ~/projects/myapp
|
||||
|
||||
## copy
|
||||
|
||||
Synopsis: copy <source> <dest>
|
||||
Wraps cp, stripping trailing slashes from source directories to
|
||||
prevent unintended nesting inside the destination.
|
||||
|
||||
copy ./mydir/ ~/backup # copies mydir INTO backup, not backup/mydir/
|
||||
|
||||
## du
|
||||
|
||||
Synopsis: du [--disk|--dir|--dua] [args...]
|
||||
Smart disk-usage dispatcher:
|
||||
--disk force duf (disk-level free/used overview)
|
||||
--dir force dust (per-directory tree breakdown)
|
||||
--dua force dua (fast space analyzer)
|
||||
Without flags, routes to the most appropriate tool by context.
|
||||
|
||||
du ~/Downloads
|
||||
du --disk
|
||||
|
||||
## dusize
|
||||
|
||||
Synopsis: dusize [dir]
|
||||
Human-readable disk usage for a directory via du -sh. Defaults to cwd.
|
||||
|
||||
dusize ~/Videos
|
||||
|
||||
## lD
|
||||
|
||||
Synopsis: lD [args...]
|
||||
Lists directories only in long format with icons. Uses eza, falls back
|
||||
to lsd, then system ls.
|
||||
|
||||
lD ~/projects
|
||||
|
||||
## ls
|
||||
|
||||
Synopsis: ls [args...]
|
||||
Lists files in long format with icons and hyperlinks. Uses eza, falls
|
||||
back to lsd, then system ls.
|
||||
|
||||
ls
|
||||
ls -a ~/projects
|
||||
|
||||
## lsr
|
||||
|
||||
Synopsis: lsr [args...]
|
||||
Lists files sorted by modification time, oldest first. Uses eza.
|
||||
|
||||
## lss
|
||||
|
||||
Synopsis: lss [args...]
|
||||
Lists files sorted by size with gradient color scaling. Uses eza.
|
||||
|
||||
## lstree
|
||||
|
||||
Synopsis: lstree [args...]
|
||||
Full recursive tree view with icons. Uses eza.
|
||||
|
||||
lstree ~/projects/myapp
|
||||
|
||||
## lt
|
||||
|
||||
Synopsis: lt [args...]
|
||||
Tree view limited to depth 2 with icons. Uses eza.
|
||||
|
||||
lt ~/projects
|
||||
|
||||
## ltr
|
||||
|
||||
Synopsis: ltr [args...]
|
||||
Lists files sorted by modification time, oldest first, long format with
|
||||
age-based gradient scaling. Uses eza.
|
||||
|
||||
## lx
|
||||
|
||||
Synopsis: lx [args...]
|
||||
Lists files sorted by extension, long format. Uses eza.
|
||||
|
||||
## mkdir
|
||||
|
||||
Synopsis: mkdir [args...]
|
||||
Interactive mkdir that prints a tree of created directories.
|
||||
Falls back to mkdir -p silently.
|
||||
|
||||
mkdir ~/projects/myapp/src
|
||||
|
||||
## mkcd
|
||||
|
||||
Synopsis: mkcd [-s] <dir>
|
||||
Creates a directory (including parents) and cd into it. Prints a tree
|
||||
of created dirs by default; -s/--silent suppresses output.
|
||||
|
||||
mkcd ~/projects/newapp/src
|
||||
|
||||
## poke
|
||||
|
||||
Synopsis: poke <file> [file...]
|
||||
Creates files via touch, automatically creating any missing parent
|
||||
directories first.
|
||||
|
||||
poke ~/projects/new/src/main.fish
|
||||
|
||||
## rm
|
||||
|
||||
Synopsis: rm [-e [opts] | -S | args...]
|
||||
Safe rm wrapper routing to trash:
|
||||
|
||||
(no args) List current trash contents
|
||||
-e/--empty Empty the trash (pass options to trash-empty)
|
||||
-S/--secure Permanently delete via rm -rf + fstrim (irreversible)
|
||||
-r/-R/--recursive Move to trash
|
||||
<paths> Move to trash (safe delete)
|
||||
|
||||
Falls back to /usr/bin/rm when trash is unavailable.
|
||||
|
||||
rm file.txt # moves to trash
|
||||
rm -e # empty trash
|
||||
rm -S sensitive.pem # permanent delete
|
||||
|
||||
## rg
|
||||
|
||||
Synopsis: rg [args...]
|
||||
In Kitty, wraps ripgrep with --hyperlink-format=kitty so search
|
||||
results are clickable file links in the terminal. Falls back to
|
||||
system rg in any other terminal. All other arguments pass through
|
||||
unchanged.
|
||||
|
||||
rg "fish_greeting" ~/.config/fish/
|
||||
rg -l "TODO" ~/projects/myapp
|
||||
|
||||
## scrub
|
||||
|
||||
Synopsis: scrub [-a] [-d] [-h]
|
||||
Recursively removes OS metadata, editor artifacts, compiler output,
|
||||
and dev caches using fd.
|
||||
|
||||
-a/--aggressive Also removes node_modules, logs, .cache, IDE dirs,
|
||||
AI session artifacts
|
||||
-d/--dry-run Print what would be removed without deleting
|
||||
|
||||
scrub
|
||||
scrub -a
|
||||
scrub -d
|
||||
|
||||
---
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Navigation
|
||||
manTitle: 5.2 Navigation
|
||||
sidebar:
|
||||
order: 2
|
||||
helpKeywords:
|
||||
- nav-fns
|
||||
---
|
||||
|
||||
## cdi
|
||||
|
||||
Synopsis: cdi [query]
|
||||
Interactive directory picker combining zoxide frecency with fzf.
|
||||
Equivalent to zi.
|
||||
|
||||
cdi myproject
|
||||
|
||||
## clone
|
||||
|
||||
Synopsis: clone [args...]
|
||||
Clone a git repository into a new Kitty window. Kitty-only.
|
||||
|
||||
clone https://github.com/user/repo.git
|
||||
|
||||
## clonet
|
||||
|
||||
Synopsis: clonet [args...]
|
||||
Clone a git repository into a new Kitty tab. Kitty-only.
|
||||
|
||||
clonet https://github.com/user/repo.git
|
||||
|
||||
---
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Editors and Viewers
|
||||
manTitle: 5.3 Editors and Viewers
|
||||
sidebar:
|
||||
order: 3
|
||||
helpKeywords:
|
||||
- editors
|
||||
---
|
||||
|
||||
## edit
|
||||
|
||||
Synopsis: edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...]
|
||||
|
||||
Opens files in a text editor, choosing a terminal or GUI editor and
|
||||
resolving a rich chain of fallbacks. With no --visual/--terminal flag the
|
||||
mode is auto-detected: interactive terminals use the terminal editor
|
||||
($EDITOR), while detached invocations (e.g. desktop shortcuts) use the GUI
|
||||
editor ($VISUAL). Clipboard contents and literal strings can be opened as
|
||||
throwaway temp files. Editor output is suppressed unless --verbose.
|
||||
|
||||
GUI fallback chain: zed → antigravity-ide → code → kate → kwrite →
|
||||
gnome-text-editor → gedit
|
||||
Terminal fallback chain: nvim → vim → micro → nano → vi
|
||||
|
||||
Options:
|
||||
-V, --visual Force the GUI editor ($VISUAL or fallbacks)
|
||||
-t, --terminal Force the terminal editor ($EDITOR or fallbacks)
|
||||
-e, --editor=X Use a specific editor binary X
|
||||
-c, --clipboard Open the clipboard contents (as a temp file)
|
||||
-x, --text=STR Open STR as the contents of a new temp file
|
||||
-n, --new Force a new window/instance (best-effort)
|
||||
-v, --verbose Print the launch command and editor output
|
||||
-s, --silent Suppress all output, including the editor's
|
||||
-h, --help Show this help message
|
||||
|
||||
edit ~/.config/fish/config.fish
|
||||
edit --visual notes.txt
|
||||
edit --terminal --new todo.md
|
||||
edit --editor=code --clipboard
|
||||
edit --text="hello world"
|
||||
|
||||
## fc
|
||||
|
||||
Synopsis: fc [command_prefix]
|
||||
Edit the last shell command (or one matching a prefix) in $EDITOR,
|
||||
then execute the result. Bash-style fc behaviour.
|
||||
|
||||
fc
|
||||
fc git
|
||||
|
||||
## less
|
||||
|
||||
Synopsis: less [args...]
|
||||
Pager wrapper with fallback chain: $PAGER -> ov -> less -> more -> cat.
|
||||
|
||||
less /var/log/syslog
|
||||
|
||||
## rawfish
|
||||
|
||||
Synopsis: rawfish [args...]
|
||||
Launches Fish with NO_TMUX=1, bypassing any tmux auto-attach logic.
|
||||
Useful when you need a clean shell without session management.
|
||||
|
||||
## view
|
||||
|
||||
Synopsis: view [args...]
|
||||
Opens files in nvim read-only mode (-R). Falls back to less.
|
||||
|
||||
view /etc/fstab
|
||||
|
||||
---
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Git and Version Control
|
||||
manTitle: 5.4 Git and Version Control
|
||||
sidebar:
|
||||
order: 4
|
||||
helpKeywords:
|
||||
- git
|
||||
---
|
||||
|
||||
## auto-pull
|
||||
|
||||
Synopsis: auto-pull [list]
|
||||
auto-pull add [PATH]
|
||||
auto-pull remove <NAME|PATH>
|
||||
auto-pull status
|
||||
|
||||
Manages the registry of repositories that are background fast-forwarded
|
||||
when you enter them (see "Auto-pull fast-forward" under the C2 component
|
||||
reference). The fish-config repo is always covered as a baseline. The
|
||||
registry is machine-local at `$__fish_user_dots_path/auto-pull.list` (defaults
|
||||
to `~/.config/.user-dots/fish/auto-pull.list`), one absolute path per line,
|
||||
and is never committed. Registry management works
|
||||
even when C2 auto-execution is disabled; only the background sync is gated.
|
||||
|
||||
list Show registered repos (default)
|
||||
add [PATH] Register PATH's git root (default: current repo)
|
||||
remove <NAME|PATH> Unregister by basename or exact path
|
||||
status Show enabled/disabled state, repo count, list path
|
||||
|
||||
cd ~/src/qmk_firmware; and auto-pull add
|
||||
auto-pull add ~/work/api
|
||||
auto-pull list
|
||||
auto-pull remove qmk_firmware
|
||||
|
||||
## branch
|
||||
|
||||
Synopsis: branch <branch_name>
|
||||
Switches to a local branch, or creates it if it does not exist.
|
||||
|
||||
branch feature/new-ui
|
||||
|
||||
## gi
|
||||
|
||||
Synopsis: gi [-h] [-b] [-p] [-s] [-l] [targets...]
|
||||
Generates .gitignore content from the gitignore.io API with MD5-based
|
||||
deduplication (patterns already present are not re-appended).
|
||||
|
||||
-b/--boilerplate Append generic boilerplate first
|
||||
-p/--prompt Prompt interactively for targets
|
||||
-s/--stdout Print to stdout instead of appending to .gitignore
|
||||
-l/--list List all available targets
|
||||
targets Comma-separated or space-separated target names
|
||||
|
||||
gi python,venv
|
||||
gi -b -p
|
||||
gi -s node > .gitignore
|
||||
|
||||
## git-clean
|
||||
|
||||
Synopsis: git-clean [-f]
|
||||
Fetches and prunes the remote, fast-forwards the current branch, then
|
||||
deletes local branches whose remote tracking branch has been deleted.
|
||||
Switches to main/master automatically if the current branch is orphaned.
|
||||
|
||||
-f/--force Force-delete unmerged branches too
|
||||
|
||||
git-clean
|
||||
git-clean --force
|
||||
|
||||
## gitup
|
||||
|
||||
Synopsis: gitup [args...]
|
||||
Fetches updates from the remote and shows git status. Extra args are
|
||||
forwarded to git fetch.
|
||||
|
||||
gitup
|
||||
gitup --all
|
||||
|
||||
## gitui
|
||||
|
||||
Synopsis: gitui [args...]
|
||||
Launches gitui with the Catppuccin Frappe theme pre-applied.
|
||||
|
||||
## hist
|
||||
|
||||
Synopsis: hist
|
||||
Searches shell history with fzf, inserts the selection into the command
|
||||
line, and copies it to the clipboard via wl-copy.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: Package Management
|
||||
manTitle: 5.5 Package Management
|
||||
sidebar:
|
||||
order: 5
|
||||
helpKeywords:
|
||||
- package-manager
|
||||
- packages
|
||||
---
|
||||
|
||||
## pkg
|
||||
|
||||
Synopsis: pkg [-h] [-i|-u] <package> [package...]
|
||||
Installs or removes packages using the detected system package manager.
|
||||
Supports: paru, yay, pacman, apt, dnf, zypper, yum, brew, pkg.
|
||||
|
||||
(no flag) Auto mode: installs missing packages, removes installed ones
|
||||
-i/--install Force install
|
||||
-u/--uninstall Force uninstall
|
||||
|
||||
pkg firefox # auto: install if missing, remove if present
|
||||
pkg -i ripgrep fd # force install
|
||||
pkg -u cowsay # force uninstall
|
||||
|
||||
The package-installed check uses the correct query for each PM:
|
||||
pacman/paru/yay pacman -Qi
|
||||
apt dpkg -s
|
||||
dnf/zypper/yum rpm -q
|
||||
brew brew list
|
||||
pkg pkg info
|
||||
|
||||
## search
|
||||
|
||||
Synopsis: search [args...]
|
||||
Interactive AUR package search and install via paru or yay.
|
||||
Arch Linux only.
|
||||
|
||||
search neovim
|
||||
|
||||
## upgrade
|
||||
|
||||
Synopsis: upgrade
|
||||
Full system upgrade via paru -Syu --noconfirm or yay -Syu --noconfirm.
|
||||
Arch Linux only.
|
||||
|
||||
## cleanup
|
||||
|
||||
Synopsis: cleanup
|
||||
Lists and removes orphan packages via pacman, logging their names to
|
||||
~/.removed_orphans. Arch Linux only.
|
||||
|
||||
## parur
|
||||
|
||||
Synopsis: parur
|
||||
Opens an fzf picker of all installed packages (with pacman -Qi previews),
|
||||
then removes the selected packages via paru or yay. Arch Linux only.
|
||||
|
||||
parur
|
||||
|
||||
---
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Dependency Management
|
||||
manTitle: 5.6 Dependency Management
|
||||
sidebar:
|
||||
order: 6
|
||||
helpKeywords:
|
||||
- deps
|
||||
---
|
||||
|
||||
## fish-deps
|
||||
|
||||
Synopsis: fish-deps [status|install|update|sync]
|
||||
Unified command for managing all tools this configuration depends on.
|
||||
|
||||
status (default) Show installed/missing status grouped by tier
|
||||
install Interactively install each missing dependency
|
||||
update Update all installed dependencies
|
||||
sync Install missing deps, then update all
|
||||
|
||||
Install method priority (highest to lowest):
|
||||
1. git+cargo source build (fish shell itself)
|
||||
2. cargo (Rust tools — gets latest crate version)
|
||||
3. system PM (paru/apt/brew/etc.)
|
||||
4. git clone (fzf)
|
||||
5. curl installer (starship, fisher, uv)
|
||||
|
||||
When multiple methods are available you are prompted to choose.
|
||||
|
||||
Dependencies are grouped into three tiers:
|
||||
|
||||
Required fish, fzf, zoxide
|
||||
Integrations wakatime, tailscale
|
||||
Recommended cargo, starship, uv, direnv, paru, yay, eza, lsd, bat,
|
||||
btop, dust, duf, prettyping, ov, ripgrep, lazygit,
|
||||
lazydocker, trash, kitty, wezterm, python3, yt-dlp
|
||||
|
||||
fish-deps
|
||||
fish-deps install
|
||||
fish-deps update
|
||||
fish-deps sync
|
||||
|
||||
## check_fish_deps
|
||||
|
||||
Synopsis: check_fish_deps
|
||||
Backwards-compatibility alias for `fish-deps status`.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: System and Monitoring
|
||||
manTitle: 5.7 System and Monitoring
|
||||
sidebar:
|
||||
order: 7
|
||||
helpKeywords:
|
||||
- system
|
||||
---
|
||||
|
||||
## top
|
||||
|
||||
Synopsis: top [args...]
|
||||
Launches btop as a modern resource monitor. Falls back to system top.
|
||||
|
||||
## swapstat
|
||||
|
||||
Synopsis: swapstat
|
||||
Displays a colorized memory report: kernel swappiness, zRAM compression
|
||||
ratio, zRAM device details, and active swap priorities.
|
||||
|
||||
## sbver
|
||||
|
||||
Synopsis: sbver [--brief]
|
||||
Verifies Secure Boot signatures on all EFI binaries tracked by sbctl.
|
||||
Color-codes results: green checkmark (verified), red X (unsigned).
|
||||
Prints a pass/fail summary.
|
||||
|
||||
--brief Suppress per-file output, show only the summary
|
||||
|
||||
sbver
|
||||
sbver --brief
|
||||
|
||||
## ports
|
||||
|
||||
Synopsis: ports
|
||||
Lists active TCP listeners with lsof, showing port/address without
|
||||
hostname resolution.
|
||||
|
||||
## screensleep
|
||||
|
||||
Synopsis: screensleep
|
||||
Turns off the display via KDE PowerDevil's "Turn Off Screen" action,
|
||||
invoked through busctl.
|
||||
|
||||
## lock
|
||||
|
||||
Synopsis: lock
|
||||
Locks the current desktop session using loginctl lock-session.
|
||||
|
||||
## sudo-toggle
|
||||
|
||||
Synopsis: sudo-toggle
|
||||
Toggles the sudo NOPASSWD rule on/off via /etc/sudoers.d/nofail-toggle.
|
||||
Useful for automated tasks that would otherwise require password entry.
|
||||
|
||||
## limine-edit
|
||||
|
||||
Synopsis: limine-edit
|
||||
Opens /boot/limine.conf in sudoedit, then automatically re-enrolls the
|
||||
config hash, runs CachyOS boot hooks, and re-signs Secure Boot files.
|
||||
Combines the edit and sign steps into a single command.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: Terminal Management
|
||||
manTitle: 5.8 Terminal Management
|
||||
sidebar:
|
||||
order: 8
|
||||
helpKeywords:
|
||||
- terminal-mgmt
|
||||
---
|
||||
|
||||
## tab
|
||||
|
||||
Synopsis: tab [args...]
|
||||
Opens a new tab in Kitty (kitty @ launch --type=tab), WezTerm
|
||||
(wezterm cli spawn), or Konsole. Uses current working directory,
|
||||
or $cdto if set.
|
||||
|
||||
tab
|
||||
|
||||
## split
|
||||
|
||||
Synopsis: split [-h|-v] [command...]
|
||||
Opens a new pane in Kitty or WezTerm, optionally running a command.
|
||||
|
||||
-h/--horizontal (default) Split below
|
||||
-v/--vertical Split to the right
|
||||
|
||||
split
|
||||
split -v nvim README.md
|
||||
|
||||
## spwin
|
||||
|
||||
Synopsis: spwin [args...]
|
||||
Spawns a new terminal OS window in Kitty (via spawn-window.sh or
|
||||
kitty @ launch --type=os-window) or WezTerm (wezterm cli spawn --new-window).
|
||||
|
||||
## detach
|
||||
|
||||
Synopsis: detach [-h] [--version] <command> [args...]
|
||||
Runs a command fully detached via nohup with stdout/stderr discarded.
|
||||
The command survives the current session.
|
||||
|
||||
detach rsync -a ./data remote:/backup/
|
||||
|
||||
## bkg
|
||||
|
||||
Synopsis: bkg <command> [args...]
|
||||
Launches a command in the background via nohup with output discarded.
|
||||
Simpler than detach; no version flag.
|
||||
|
||||
bkg firefox
|
||||
|
||||
## ssh
|
||||
|
||||
Synopsis: ssh [args...]
|
||||
In Kitty, wraps ssh with kitten ssh for better terminal integration
|
||||
(multiplexing, copy/paste support). Falls back to system ssh elsewhere.
|
||||
|
||||
ssh user@host
|
||||
|
||||
---
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Clipboard
|
||||
manTitle: 5.9 Clipboard
|
||||
sidebar:
|
||||
order: 9
|
||||
helpKeywords:
|
||||
- clipboard
|
||||
---
|
||||
|
||||
## y
|
||||
|
||||
Synopsis: y [text...]
|
||||
Copies text to the clipboard via wl-copy (Wayland) or xclip (X11).
|
||||
Reads from stdin if no arguments given.
|
||||
|
||||
y "hello world"
|
||||
ls | y
|
||||
cat file.txt | y
|
||||
|
||||
## p
|
||||
|
||||
Synopsis: p [args...]
|
||||
Outputs clipboard contents to stdout.
|
||||
|
||||
p | grep foo
|
||||
p > file.txt
|
||||
|
||||
## paste
|
||||
|
||||
Alias for p. Identical behaviour.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Network
|
||||
manTitle: 5.10 Network
|
||||
sidebar:
|
||||
order: 10
|
||||
helpKeywords:
|
||||
- network
|
||||
---
|
||||
|
||||
## gip
|
||||
|
||||
Synopsis: gip
|
||||
Fetches and prints both the public IPv4 and IPv6 address via
|
||||
icanhazip.com.
|
||||
|
||||
## gip4
|
||||
|
||||
Synopsis: gip4
|
||||
Fetches and prints the public IPv4 address.
|
||||
|
||||
## gip6
|
||||
|
||||
Synopsis: gip6
|
||||
Fetches and prints the public IPv6 address. Returns 1 if IPv6 is
|
||||
unavailable.
|
||||
|
||||
## ping
|
||||
|
||||
Synopsis: ping [args...]
|
||||
Wraps prettyping with --nolegend. Pass --legend to show the legend.
|
||||
Falls back to system ping.
|
||||
|
||||
ping google.com
|
||||
|
||||
## qr
|
||||
|
||||
Synopsis: qr [text...]
|
||||
Generates a UTF-8 QR code from text or stdin. Uses qrencode locally;
|
||||
falls back to the qrenco.de API.
|
||||
|
||||
qr "https://example.com"
|
||||
echo "https://example.com" | qr
|
||||
|
||||
---
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Pager and Logging
|
||||
manTitle: 5.11 Pager and Logging
|
||||
sidebar:
|
||||
order: 11
|
||||
helpKeywords:
|
||||
- logging
|
||||
---
|
||||
|
||||
## logs
|
||||
|
||||
Synopsis: logs [-c <category>]
|
||||
Interactively browses terminal log files sorted newest-first using fzf.
|
||||
|
||||
-c/--category Filter to: scrollback, paru, or yay
|
||||
|
||||
Keybindings inside the fzf browser:
|
||||
Enter Open in $PAGER
|
||||
Ctrl+E Open in $EDITOR
|
||||
Ctrl+D Delete (with confirmation)
|
||||
? Toggle keybind help overlay
|
||||
|
||||
Paru and yay logs open in ov with syntax highlighting and sticky section
|
||||
headers. Scrollback logs open in ov with per-command sticky prompt headers
|
||||
based on OSC 133 markers.
|
||||
|
||||
logs
|
||||
logs -c paru
|
||||
logs -c scrollback
|
||||
|
||||
## smart_exit
|
||||
|
||||
Synopsis: smart_exit [-n]
|
||||
Closes the shell session. In Kitty, captures the terminal scrollback to
|
||||
a timestamped log file in $SCROLLBACK_HISTORY_DIR before exiting.
|
||||
Automatically prunes the oldest logs when the count exceeds
|
||||
$SCROLLBACK_HISTORY_MAX_FILES.
|
||||
|
||||
-n/--no-log Exit without saving a scrollback log
|
||||
|
||||
The exit builtin is wired to smart_exit for interactive sessions.
|
||||
Typing exit or Ctrl+D behaves identically to smart_exit.
|
||||
|
||||
smart_exit
|
||||
smart_exit --no-log
|
||||
|
||||
---
|
||||
@@ -0,0 +1,116 @@
|
||||
---
|
||||
title: AI and Developer Tools
|
||||
manTitle: 5.12 AI and Developer Tools
|
||||
sidebar:
|
||||
order: 12
|
||||
helpKeywords:
|
||||
- ai
|
||||
---
|
||||
|
||||
## agy
|
||||
|
||||
Synopsis: agy [args...]
|
||||
Wrapper for the agy Antigravity AI CLI. Before launching, delegates to
|
||||
agents-init --agents to ensure AGENTS/ is scaffolded and CLAUDE.md is
|
||||
symlinked to AGENTS/AGENTS.md in the current project, then forwards all
|
||||
arguments verbatim to the real agy binary. Command shadow (C1): when
|
||||
__fish_config_op_aliases (or the master) is disabled, the call is
|
||||
passed through to the real agy binary unchanged.
|
||||
|
||||
agy chat
|
||||
agy resume
|
||||
|
||||
## antigravity-ide
|
||||
|
||||
Synopsis: antigravity-ide [args...]
|
||||
Runs the antigravity-ide editor with warnings filtered.
|
||||
|
||||
## agents-init
|
||||
|
||||
Synopsis: agents-init [--agents | --plugins]
|
||||
Scaffold an AGENTS/ sub-repository for tracking agent specs, plans, specs,
|
||||
and dev logs. Creates AGENTS/ as a standalone git repo, moves any existing
|
||||
AGENTS.md into it, and replaces it with a relative symlink (plus
|
||||
CLAUDE.md -> AGENTS/AGENTS.md so Claude Code picks up the shared agent
|
||||
instructions). Consolidates plans/ and specs/ directly under AGENTS/
|
||||
(merging any legacy docs/plans, docs/superpowers/plans, or old
|
||||
AGENTS/plugins/ locations into the canonical AGENTS/<tgt>), creates
|
||||
AGENTS/devlogs/, and wires docs/superpowers/{plans,specs} symlinks back to
|
||||
them. Adds managed paths to .gitignore and auto-commits every change inside
|
||||
the AGENTS/ sub-repo; pulls first when the sub-repo has an upstream.
|
||||
Fully idempotent: a second run produces no output and no new commits.
|
||||
Flags: --agents re-runs only the AGENTS.md / symlink step; --plugins
|
||||
re-runs only the plans/specs/devlogs wiring step. Called automatically by
|
||||
the claude and agy wrappers on every invocation.
|
||||
|
||||
Structure versioning: each AGENTS/ repo carries a self-contained version
|
||||
bumper. AGENTS/.version holds MAJOR.MINOR.PATCH (seeded 1.0.0). Committed
|
||||
git hooks under AGENTS/.agents-tools/ (wired via core.hooksPath) bump it on
|
||||
every commit: MINOR (resetting PATCH) when the tracked directory set
|
||||
changes, PATCH otherwise; MAJOR is manual-only. A prepare-commit-msg hook
|
||||
appends "(vX.Y.Z)" to the commit subject. Downstream tooling can read
|
||||
AGENTS/.version - a changed MINOR field signals a structure change. Because
|
||||
core.hooksPath is a single setting, the local override would otherwise
|
||||
shadow your global hooks; after bumping the version, each shim chains
|
||||
(execs) to the global/system core.hooksPath hook of the same name so global
|
||||
pre-commit / prepare-commit-msg hooks (e.g. ggshield, Git LFS) still run.
|
||||
The script and hooks are shipped from scripts/agents-tools/ and refreshed
|
||||
when their version marker is stale.
|
||||
|
||||
agents-init
|
||||
agents-init --agents
|
||||
agents-init --plugins
|
||||
|
||||
## claude
|
||||
|
||||
Synopsis: claude [args...]
|
||||
Wrapper for the claude CLI. Before launching, delegates to agents-init
|
||||
--agents to ensure AGENTS/ is scaffolded and CLAUDE.md is symlinked to
|
||||
AGENTS/AGENTS.md in the current project, then forwards all arguments
|
||||
verbatim to the real claude binary. Command shadow (C1): when
|
||||
__fish_config_op_aliases (or the master) is disabled, the call is
|
||||
passed through to the real claude binary unchanged.
|
||||
|
||||
claude
|
||||
claude --resume
|
||||
|
||||
## claude-docs
|
||||
|
||||
Synopsis: claude-docs
|
||||
Invokes Claude Code to analyze recent repository changes and update
|
||||
README.md, ensuring all documented features and examples are accurate.
|
||||
|
||||
## claude-pr
|
||||
|
||||
Synopsis: claude-pr
|
||||
Invokes Claude Code to run the full PR workflow: create branch,
|
||||
conventional commit, verification, push, and open a PR with a manual
|
||||
verification checklist.
|
||||
|
||||
## qc
|
||||
|
||||
Synopsis: qc [prompt...]
|
||||
Quick-chat wrapper around the aichat LLM CLI that defaults to the "cli"
|
||||
role - a system prompt tuned for concise, terminal-friendly output. On
|
||||
first use it installs the bundled role by symlinking
|
||||
scripts/cli-agent.md to $XDG_CONFIG_HOME/aichat/roles/cli.md (creating
|
||||
the directory if needed). Inherits every aichat flag and tab completion
|
||||
(--wraps aichat); passing --role/-r overrides the default role, so qc
|
||||
forwards to aichat unchanged. The function is only defined when aichat
|
||||
is installed. Run qc --help for aichat's full flag reference with the
|
||||
command name rewritten to qc.
|
||||
|
||||
qc "how do I list open ports on linux?"
|
||||
qc -m ollama:llama3 "explain this error"
|
||||
qc --role coder "refactor this function"
|
||||
|
||||
## superpowers
|
||||
|
||||
Synopsis: superpowers [on|off] [-g]
|
||||
Enables or disables the Superpowers plugin for Antigravity and Claude
|
||||
Code at workspace/project scope (default) or user scope (-g/--global).
|
||||
|
||||
superpowers on
|
||||
superpowers off -g
|
||||
|
||||
---
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Media and Utilities
|
||||
manTitle: 5.13 Media and Utilities
|
||||
sidebar:
|
||||
order: 13
|
||||
helpKeywords:
|
||||
- media
|
||||
---
|
||||
|
||||
## dng2avif
|
||||
|
||||
Synopsis: dng2avif [-i <file>] [-o <file>] [-q <n>] [-s <n>] [input.dng]
|
||||
Converts a DNG raw image to a 10-bit HDR AVIF using an ImageMagick,
|
||||
ffmpeg, avifenc pipeline with metadata sync via exiftool.
|
||||
|
||||
-i/--input Input file (or positional arg)
|
||||
-o/--output Output file (default: same name, .avif extension)
|
||||
-q/--quality Quality 0-100 (default 92)
|
||||
-s/--speed Encoding speed 0-10 (default 3)
|
||||
|
||||
dng2avif photo.dng
|
||||
dng2avif -q 85 -s 5 -i shot.dng -o out.avif
|
||||
|
||||
## steam-dl
|
||||
|
||||
Synopsis: steam-dl
|
||||
Launches Steam under systemd-inhibit, preventing the system from going
|
||||
idle or sleeping while a download is in progress.
|
||||
|
||||
## spark
|
||||
|
||||
Synopsis: spark [--min=<n>] [--max=<n>] [numbers...]
|
||||
Renders a Unicode sparkline bar chart for a sequence of numbers.
|
||||
Reads from stdin if no numbers are given.
|
||||
|
||||
spark 1 1 2 5 14 42
|
||||
echo "3 7 2 9 1" | spark
|
||||
|
||||
## yt-dlp
|
||||
|
||||
Synopsis: yt-dlp [args...] URL [URL...]
|
||||
Wraps yt-dlp, prepending sane defaults: --sponsorblock-remove all,
|
||||
--embed-subs, --embed-metadata, and --embed-thumbnail. Each default
|
||||
is suppressed when you already pass that flag, its alias, or its
|
||||
negation (e.g. --no-embed-thumbnail drops the thumbnail default;
|
||||
--no-sponsorblock or your own --sponsorblock-remove drops ours). All
|
||||
other arguments pass through unchanged, and --help falls through to
|
||||
real yt-dlp. Opinionated component (C1 aliases); when disabled it
|
||||
passes straight through to the system yt-dlp.
|
||||
|
||||
yt-dlp dQw4w9WgXcQ
|
||||
yt-dlp --no-embed-thumbnail dQw4w9WgXcQ
|
||||
|
||||
---
|
||||
@@ -0,0 +1,285 @@
|
||||
---
|
||||
title: Miscellaneous
|
||||
manTitle: 5.14 Miscellaneous
|
||||
sidebar:
|
||||
order: 14
|
||||
helpKeywords:
|
||||
- miscfns
|
||||
---
|
||||
|
||||
## config-help
|
||||
|
||||
Synopsis: config-help [SECTION]
|
||||
config-help --html
|
||||
config-help [SECTION] --man
|
||||
config-help -h | --help
|
||||
|
||||
Opens the offline fish shell configuration manual. Without flags, opens
|
||||
the Markdown source in the best available pager (ov > bat > man > less >
|
||||
cat). If SECTION is given, jumps to the first heading matching that
|
||||
keyword (case-insensitive; checks fish-config.index aliases first).
|
||||
|
||||
Flags:
|
||||
--html / -w Open the published documentation website
|
||||
(https://fish-config-docs.pages.dev/) in the default
|
||||
browser via xdg-open. Deep links to a section aren't
|
||||
supported; if SECTION is given, a note points you to the
|
||||
site's search box instead.
|
||||
--man / -m Open docs/fish-config.1 via man -l directly.
|
||||
If SECTION is given, jumps to the nearest match.
|
||||
--help / -h Print usage and navigation key reference.
|
||||
|
||||
config-help keybindings
|
||||
config-help pkg
|
||||
config-help --html
|
||||
config-help --man
|
||||
config-help pkg --man
|
||||
|
||||
Also available as: help config [SECTION] [FLAGS]
|
||||
|
||||
## open-url
|
||||
|
||||
Synopsis: open-url [-s|--silent] [-v|--verbose] <url>
|
||||
open-url -h | --help
|
||||
|
||||
Opens a URL or file:// URI in the best available graphical web browser,
|
||||
backgrounded so it never blocks the terminal. Resolves a real browser
|
||||
binary rather than deferring to xdg-open, whose MIME dispatch can hand
|
||||
local text/html files to non-browser apps (e.g. ebook readers).
|
||||
|
||||
Silent by default: prints nothing on success (errors always go to
|
||||
stderr). Pass --verbose / -v to report which browser is launched;
|
||||
--silent / -s is accepted for explicitness.
|
||||
|
||||
Resolution order:
|
||||
1. $fish_help_browser (explicit override)
|
||||
2. $BROWSER (validated; errors if not a command)
|
||||
3. xdg-mime default handler for x-scheme-handler/https
|
||||
4. First known browser binary found in a built-in list
|
||||
5. xdg-open (last resort)
|
||||
|
||||
open-url https://git.rootiest.dev/rootiest/fish-config
|
||||
open-url -v https://fish-config-docs.pages.dev/
|
||||
|
||||
Used internally by config-help --html.
|
||||
|
||||
Typo abbreviation: url-open (expands to open-url on space/enter).
|
||||
|
||||
## repo-open
|
||||
|
||||
Synopsis: repo-open [-p|--print] [-r|--root]
|
||||
repo-open -h | --help
|
||||
|
||||
Opens the web page for the current repository's `origin` remote in a
|
||||
browser (via open-url). Deep-links to the current branch when it exists
|
||||
on the remote — falling back to the remote's default branch (main/master)
|
||||
otherwise — and to the current sub-directory when run below the repo root.
|
||||
|
||||
The remote URL is normalized from HTTPS and SSH/scp forms
|
||||
(git@host:owner/repo.git, ssh://…, https://…). The web path layout is
|
||||
provider-specific; the provider is resolved in order:
|
||||
|
||||
1. git config browse.provider (per-repo or --global override)
|
||||
2. Hostname heuristic (github / gitlab / gitea / bitbucket;
|
||||
codeberg → gitea)
|
||||
3. Default: github-style layout
|
||||
|
||||
Self-hosted hosts the heuristic can't classify (a Gitea/GitLab instance
|
||||
on a custom domain) need a one-time override:
|
||||
|
||||
git config browse.provider gitea
|
||||
|
||||
Flags:
|
||||
--print / -p Print the resolved URL instead of opening it.
|
||||
--root / -r Ignore the current sub-directory; link to the repo root.
|
||||
--help / -h Show usage.
|
||||
|
||||
repo-open
|
||||
repo-open --print
|
||||
repo-open --root
|
||||
|
||||
Typo abbreviation: open-repo (expands to repo-open on space/enter).
|
||||
|
||||
## config-update
|
||||
|
||||
Synopsis: config-update [-h] [-n] [-f]
|
||||
|
||||
Pulls the latest fish configuration from the upstream repository
|
||||
(https://git.rootiest.dev/rootiest/fish-config.git) into ~/.config/fish.
|
||||
The remote URL is hard-coded, so this works on fresh clones with no git
|
||||
remote configured. All git output is suppressed; colored messages report
|
||||
fetch and merge status. After a successful pull, run `exec fish` to
|
||||
reload.
|
||||
|
||||
Flags:
|
||||
--dry-run / -n Fetch and show available commits without applying them.
|
||||
--force / -f Stash local changes, pull, then restore the stash.
|
||||
--help / -h Show usage.
|
||||
|
||||
config-update
|
||||
config-update --dry-run
|
||||
config-update --force
|
||||
|
||||
## config-settings
|
||||
|
||||
Synopsis: config-settings [-h]
|
||||
|
||||
Opens an interactive TUI for managing fish configuration settings across
|
||||
four pages, without having to type or remember variable names. Tab cycles
|
||||
forward through the pages; Shift-Tab cycles backward.
|
||||
|
||||
Universal — opinionated category toggles (C1–C6) + master, persistent (set -U)
|
||||
Session — the same toggles, current shell only (set -g)
|
||||
Sponge — sponge history-scrubbing settings: delay, successful exit
|
||||
codes, purge-only-on-exit, allow-previously-successful, and
|
||||
extra sensitive variable-name tokens
|
||||
Paths — scrollback log directory, scrollback max files, the
|
||||
user-dots path, and the user-dots convenience symlink toggle
|
||||
(Dots link)
|
||||
|
||||
Toggle rows use ← → (or h/l) along an OFF ← DEFAULT → ON scale; DEFAULT
|
||||
erases the variable so the master switch / built-in default applies. Value
|
||||
rows (the path/int/list settings on the Sponge and Paths pages) use Enter to
|
||||
edit inline; ← / h clears the value back to its default. List rows (e.g.
|
||||
Extra secret, OK codes) accept values separated by commas and/or whitespace
|
||||
— "A, B", "A,B" and "A B" all yield the same two entries. Changes apply
|
||||
immediately. Always available regardless of the __fish_config_opinionated
|
||||
master state.
|
||||
|
||||
The Sponge and Paths pages always write universal variables — these are
|
||||
persistent, set-and-forget settings with no per-session scope. Editing a
|
||||
scrollback row updates both the __fish_scrollback_history_* source-of-truth
|
||||
variables and the exported SCROLLBACK_HISTORY_* mirrors, so the AUR/tmux/
|
||||
zellij log wrappers (which read the exported names) see the change in the
|
||||
running session.
|
||||
|
||||
The panel adapts to the terminal width automatically, selecting from
|
||||
four layout tiers (with a 6-column buffer on each side before stepping
|
||||
up to the next tier) and horizontally centering the box. The panel
|
||||
redraws within ~0.3 s of a terminal resize with no keypress required.
|
||||
|
||||
COLUMNS >= 90 → 78-wide panel (most detail)
|
||||
COLUMNS >= 86 → 74-wide panel
|
||||
COLUMNS >= 82 → 70-wide panel
|
||||
COLUMNS < 82 → 52-wide panel (default)
|
||||
|
||||
Navigation:
|
||||
↑ ↓ / k j Move cursor
|
||||
← → / h l Toggle rows: OFF ← DEFAULT → ON
|
||||
← / h Value rows: clear to default
|
||||
Enter Value rows: edit inline (Sponge / Paths pages)
|
||||
Tab / S-Tab Next / previous page
|
||||
q / Escape Exit
|
||||
|
||||
Flags:
|
||||
--help / -h Show usage.
|
||||
|
||||
config-settings
|
||||
|
||||
## config-toggle (deprecated)
|
||||
|
||||
Deprecated alias for config-settings. Prints a deprecation notice to
|
||||
stderr, then delegates all arguments to config-settings.
|
||||
|
||||
config-toggle
|
||||
|
||||
## bash
|
||||
|
||||
Synopsis: bash [args...]
|
||||
Switches to bash, with XDG config applied. On exit, $SHELL is reset
|
||||
back to fish.
|
||||
|
||||
## bd-pull
|
||||
|
||||
Synopsis: bd-pull <owner/repo>
|
||||
Fetches unlinked Gitea issues and creates local Beads entries, updating
|
||||
issue titles with the assigned Beads IDs.
|
||||
Requires $GITEA_TOKEN and $GITEA_URL to be set.
|
||||
|
||||
bd-pull rootiest/fish-config
|
||||
|
||||
## cheat
|
||||
|
||||
Synopsis: cheat <topic> [args...]
|
||||
Displays a colorized cheatsheet using cheat -c, falls back to tldr,
|
||||
then man.
|
||||
|
||||
cheat tar
|
||||
cheat git
|
||||
|
||||
## cffetch / ffetch
|
||||
|
||||
Synopsis: cffetch [args...] / ffetch [args...]
|
||||
Clears the screen and displays system information via fastfetch with
|
||||
the custom config at ~/.fastfetch.jsonc. Falls back to neofetch.
|
||||
|
||||
## dockup
|
||||
|
||||
Synopsis: dockup [-h] [directory]
|
||||
Pulls latest Docker images, restarts services in the given Docker
|
||||
Compose project, and prunes dangling images.
|
||||
|
||||
dockup ~/myapp
|
||||
|
||||
## joplin
|
||||
|
||||
Synopsis: joplin [args...]
|
||||
Runs the Joplin CLI with Node.js deprecation warnings suppressed.
|
||||
|
||||
joplin ls
|
||||
|
||||
## ld
|
||||
|
||||
Synopsis: ld
|
||||
Launches lazydocker targeting the currently active Docker context,
|
||||
detected via docker context inspect.
|
||||
|
||||
## replay
|
||||
|
||||
Synopsis: replay <commands>
|
||||
Runs Bash commands and replays any resulting changes to environment
|
||||
variables, aliases, and the working directory back into the current
|
||||
Fish session. Useful for sourcing Bash scripts.
|
||||
|
||||
replay "source ~/.bashrc"
|
||||
replay "export FOO=bar"
|
||||
|
||||
## kitty-logging
|
||||
|
||||
Synopsis: kitty-logging [install|uninstall|status|dismiss] [-h]
|
||||
|
||||
Manages the Kitty scrollback watcher that powers C5 logging. Ships a
|
||||
canonical watcher and symlinks it into the Kitty config directory (so it
|
||||
always tracks the source), wiring it into kitty.conf through a
|
||||
sentinel-marked managed block. Commenting out any conflicting watcher line
|
||||
avoids double-capture.
|
||||
|
||||
Commands:
|
||||
install Symlink the watcher and add the managed block
|
||||
uninstall Remove the managed block and the watcher symlink
|
||||
status Show wiring, installed watcher version, and C5 state
|
||||
dismiss Stop the per-session setup reminder
|
||||
|
||||
Runtime capture stays governed by the C5 .logging_disabled sentinel, so
|
||||
disabling __fish_config_op_logging makes the watcher inert without
|
||||
uninstalling. Install affects new Kitty windows only.
|
||||
|
||||
Example:
|
||||
kitty-logging install
|
||||
kitty-logging status
|
||||
|
||||
## tmux-clean
|
||||
|
||||
Synopsis: tmux-clean
|
||||
Kills all detached (unattached) tmux sessions, leaving attached ones
|
||||
running.
|
||||
|
||||
## wake-lock
|
||||
|
||||
Synopsis: wake-lock <command> [args...]
|
||||
Runs a command under systemd-inhibit, preventing the system from going
|
||||
idle or sleeping until the command completes.
|
||||
|
||||
wake-lock rsync -avz src/ dest/
|
||||
|
||||
---
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: Functions Reference
|
||||
manTitle: 5. FUNCTIONS REFERENCE
|
||||
sidebar:
|
||||
order: 9
|
||||
helpKeywords:
|
||||
- functions
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# 6. DEPENDENCY CATALOG
|
||||
|
||||
**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | **6. Dependency Catalog** | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
|
||||
---
|
||||
title: Dependency Catalog
|
||||
manTitle: 6. DEPENDENCY CATALOG
|
||||
sidebar:
|
||||
order: 10
|
||||
helpKeywords:
|
||||
- catalog
|
||||
- deps-catalog
|
||||
---
|
||||
|
||||
fish-deps manages these tools. Run `fish-deps` to check status, or
|
||||
@@ -1,7 +1,11 @@
|
||||
# 7. CUSTOMIZATION
|
||||
|
||||
**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | **7. Customization** | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
|
||||
---
|
||||
title: Customization
|
||||
manTitle: 7. CUSTOMIZATION
|
||||
sidebar:
|
||||
order: 11
|
||||
helpKeywords:
|
||||
- customization
|
||||
- customize
|
||||
---
|
||||
|
||||
## Machine-local Configuration
|
||||
@@ -1,7 +1,11 @@
|
||||
# 8. FISHER PLUGINS
|
||||
|
||||
**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | **8. Fisher Plugins** | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
|
||||
---
|
||||
title: Fisher Plugins
|
||||
manTitle: 8. FISHER PLUGINS
|
||||
sidebar:
|
||||
order: 12
|
||||
helpKeywords:
|
||||
- plugins
|
||||
- fisher
|
||||
---
|
||||
|
||||
Fisher is bootstrapped automatically on the **first interactive session** via
|
||||
@@ -1,7 +1,11 @@
|
||||
# 9. INSTALLATION
|
||||
|
||||
**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | **9. Installation** | [10. Personalization](10-personalization.md) | [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
|
||||
---
|
||||
title: Installation
|
||||
manTitle: 9. INSTALLATION
|
||||
sidebar:
|
||||
order: 13
|
||||
helpKeywords:
|
||||
- installation
|
||||
- install
|
||||
---
|
||||
|
||||
This configuration is managed as a git repository. To deploy on a new machine:
|
||||
@@ -1,7 +1,11 @@
|
||||
# 10. PERSONALIZATION
|
||||
|
||||
**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | **10. Personalization** | [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
|
||||
---
|
||||
title: Personalization
|
||||
manTitle: 10. PERSONALIZATION
|
||||
sidebar:
|
||||
order: 14
|
||||
helpKeywords:
|
||||
- personalization
|
||||
- personalize
|
||||
---
|
||||
|
||||
Sensitive credentials and machine-specific settings are kept out of version
|
||||
@@ -0,0 +1,85 @@
|
||||
---
|
||||
title: Viewing This Manual
|
||||
manTitle: 11. VIEWING THIS MANUAL
|
||||
sidebar:
|
||||
order: 15
|
||||
helpKeywords:
|
||||
- viewing
|
||||
- manual
|
||||
---
|
||||
|
||||
There are four ways to read this manual.
|
||||
|
||||
## The documentation website
|
||||
|
||||
help config --html
|
||||
|
||||
Opens https://fish-config-docs.pages.dev/ in the default browser — the
|
||||
Starlight-powered site built from `docs/manual/**` on every push to `main`.
|
||||
It has a section sidebar and full-text search. Deep links to a specific
|
||||
section aren't supported from the command line; once the site opens, use
|
||||
its search box to jump straight to what you need.
|
||||
|
||||
## As a man page
|
||||
|
||||
help config --man
|
||||
help config pkg --man
|
||||
|
||||
Opens the compiled docs/fish-config.1 directly via man -l, bypassing
|
||||
the pager fallback chain. If a section keyword is given, the pager opens
|
||||
at the nearest matching heading. The symlink is created once on first
|
||||
run (like an install step) and MANPATH is set each session, enabling
|
||||
the standard invocation:
|
||||
|
||||
man fish-config
|
||||
|
||||
NOTE: fish-config (hyphen) is this config's man page. fish_config
|
||||
(underscore) is fish's built-in browser-based configuration tool —
|
||||
a completely separate command. Do not mix them up.
|
||||
|
||||
## In the terminal
|
||||
|
||||
help config
|
||||
help config keybindings
|
||||
|
||||
Without a pager available beyond the basics, `help config [SECTION]` opens
|
||||
the Markdown manual in the best available viewer, falling back through:
|
||||
|
||||
1. ov + bat section navigation + syntax highlighting (best)
|
||||
2. ov alone section navigation, raw Markdown
|
||||
3. bat alone syntax highlighting, use / to search
|
||||
4. man -l pre-compiled man page (if available)
|
||||
5. less plain text with line-jump
|
||||
6. cat plain output
|
||||
|
||||
With ov, the Markdown renders with syntax highlighting and section-based
|
||||
navigation:
|
||||
|
||||
Space next section
|
||||
^ previous section
|
||||
Alt+u toggle section list sidebar
|
||||
/ search forward
|
||||
n / N next / previous search match
|
||||
g go to line number
|
||||
j interactive jump target (line, %, or 'section')
|
||||
q quit
|
||||
|
||||
If SECTION is given, the pager opens at the first heading that matches the
|
||||
keyword (case-insensitive; checks `docs/fish-config.index` aliases first,
|
||||
then falls back to a normalized heading scan):
|
||||
|
||||
help config keybindings
|
||||
help config abbreviations
|
||||
help config pkg
|
||||
help config logs
|
||||
help config fish-deps
|
||||
|
||||
## Reading the source directly
|
||||
|
||||
`docs/manual/**` is the single source of truth this manual, the man page,
|
||||
and the website are all generated from. Numbered files and directories
|
||||
correspond to the numbered sections in this manual — browse them in any
|
||||
editor, or from a shell:
|
||||
|
||||
cd ~/.config/fish/docs/manual
|
||||
grep -rn "keybindings" .
|
||||
@@ -0,0 +1,5 @@
|
||||
title: FISH-CONFIG
|
||||
section: 7
|
||||
header: Fish Shell Configuration User Manual
|
||||
date: June 2026
|
||||
author: Rootiest
|
||||
@@ -1,4 +1,16 @@
|
||||
# Fish Shell Configuration
|
||||
---
|
||||
title: Fish Shell Configuration
|
||||
description: Reference manual for the rootiest fish configuration.
|
||||
manTitle: DESCRIPTION
|
||||
sidebar:
|
||||
order: 3
|
||||
helpKeywords:
|
||||
- description
|
||||
- autopair
|
||||
- puffer
|
||||
- puffer-fish
|
||||
- logging-events
|
||||
---
|
||||
|
||||
A production-grade Fish shell configuration targeting Fish 4.x. It provides:
|
||||
|
||||
@@ -63,17 +75,3 @@ The configuration is split across:
|
||||
wiki/ Markdown wiki (auto-generated by CI)
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [1. Configuration Variables](1-configuration-variables.md)
|
||||
- [2. Path Setup](2-path-setup.md)
|
||||
- [3. Key Bindings](3-key-bindings.md)
|
||||
- [4. Abbreviations](4-abbreviations.md)
|
||||
- [5. Functions Reference](5-functions-reference.md)
|
||||
- [6. Dependency Catalog](6-dependency-catalog.md)
|
||||
- [7. Customization](7-customization.md)
|
||||
- [8. Fisher Plugins](8-fisher-plugins.md)
|
||||
- [9. Installation](9-installation.md)
|
||||
- [10. Personalization](10-personalization.md)
|
||||
- [11. Viewing This Manual](11-viewing-this-manual.md)
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Shared helpers for the docs/manual SSOT pipeline.
|
||||
|
||||
Frontmatter parsing, deterministic tree ordering, and heading level shifts.
|
||||
Used by build-manual.py and verify-manual.py.
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
FENCE_RE = re.compile(r"^\s*(```|~~~)")
|
||||
HEADING_RE = re.compile(r"^(#{1,6})(\s)")
|
||||
|
||||
|
||||
def parse(path: Path) -> tuple[dict, str]:
|
||||
"""Split a markdown file into (frontmatter dict, body text).
|
||||
|
||||
Files without a leading `---` block yield an empty dict and the whole
|
||||
text as body. Body is returned with trailing whitespace stripped.
|
||||
"""
|
||||
text = path.read_text()
|
||||
if not text.startswith("---\n"):
|
||||
return {}, text.rstrip()
|
||||
end = text.find("\n---\n", 4)
|
||||
if end == -1:
|
||||
return {}, text.rstrip()
|
||||
fm = yaml.safe_load(text[4:end]) or {}
|
||||
return fm, text[end + 5 :].removeprefix("\n").rstrip()
|
||||
|
||||
|
||||
def serialize(fm: dict, body: str) -> str:
|
||||
"""Render a frontmatter dict and body back into markdown text."""
|
||||
block = yaml.safe_dump(fm, sort_keys=False, allow_unicode=True).rstrip()
|
||||
return f"---\n{block}\n---\n\n{body.rstrip()}\n"
|
||||
|
||||
|
||||
def shift_headings(body: str, by: int) -> str:
|
||||
"""Add `by` levels to every ATX heading, ignoring fenced code blocks.
|
||||
|
||||
Negative values promote headings. Level is clamped to [1, 6].
|
||||
"""
|
||||
if by == 0:
|
||||
return body
|
||||
out, in_fence = [], False
|
||||
for line in body.split("\n"):
|
||||
if FENCE_RE.match(line):
|
||||
in_fence = not in_fence
|
||||
if not in_fence:
|
||||
line = HEADING_RE.sub(
|
||||
lambda m: "#" * max(1, min(6, len(m.group(1)) + by)) + m.group(2), line
|
||||
)
|
||||
out.append(line)
|
||||
return "\n".join(out)
|
||||
|
||||
|
||||
def _sort_key(entry: Path) -> tuple:
|
||||
"""Order by sidebar.order when present, else by filename. Stable."""
|
||||
target = entry / "index.md" if entry.is_dir() else entry
|
||||
order = None
|
||||
if target.exists():
|
||||
fm, _ = parse(target)
|
||||
order = (fm.get("sidebar") or {}).get("order")
|
||||
return (order is None, order if order is not None else 0, entry.name)
|
||||
|
||||
|
||||
def walk(root: Path, depth: int = 0) -> list[tuple[Path, int]]:
|
||||
"""Return ordered (path, depth) pairs for every markdown file under root.
|
||||
|
||||
A directory sorts at the position of its index.md and its children are
|
||||
emitted immediately afterwards at depth+1.
|
||||
"""
|
||||
entries = [e for e in root.iterdir() if e.is_dir() or e.suffix == ".md"]
|
||||
result: list[tuple[Path, int]] = []
|
||||
for entry in sorted(entries, key=_sort_key):
|
||||
if entry.is_dir():
|
||||
index = entry / "index.md"
|
||||
if index.exists():
|
||||
result.append((index, depth))
|
||||
result.extend(walk(entry, depth + 1))
|
||||
elif entry.name != "index.md" or depth == 0:
|
||||
result.append((entry, depth))
|
||||
return result
|
||||
@@ -0,0 +1,21 @@
|
||||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
# Starlight Starter Kit: Basics
|
||||
|
||||
[](https://starlight.astro.build)
|
||||
|
||||
```
|
||||
npm create astro@latest -- --template starlight
|
||||
```
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro + Starlight project, you'll see the following folders and files:
|
||||
|
||||
```
|
||||
.
|
||||
├── public/
|
||||
├── src/
|
||||
│ ├── assets/
|
||||
│ ├── content/
|
||||
│ │ └── docs/
|
||||
│ └── content.config.ts
|
||||
├── astro.config.mjs
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name.
|
||||
|
||||
Images can be added to `src/assets/` and embedded in Markdown with a relative link.
|
||||
|
||||
Static assets, like favicons, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat).
|
||||
@@ -0,0 +1,32 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import starlight from '@astrojs/starlight';
|
||||
import sidebar from './src/sidebar.json' with { type: 'json' };
|
||||
|
||||
export default defineConfig({
|
||||
site: 'https://fish-config-docs.pages.dev',
|
||||
integrations: [
|
||||
starlight({
|
||||
title: 'Fish Config',
|
||||
description: 'Reference manual for the rootiest fish configuration.',
|
||||
social: [
|
||||
{
|
||||
icon: 'code-branch',
|
||||
label: 'Gitea',
|
||||
href: 'https://git.rootiest.dev/rootiest/fish-config',
|
||||
},
|
||||
],
|
||||
customCss: ['./src/styles/catppuccin.css'],
|
||||
expressiveCode: {
|
||||
// Shiki ships both Catppuccin flavours; Starlight picks by the
|
||||
// reader's colour scheme, matching the palette in catppuccin.css.
|
||||
themes: ['catppuccin-mocha', 'catppuccin-latte'],
|
||||
styleOverrides: {
|
||||
borderRadius: '0.4rem',
|
||||
borderColor: 'var(--sl-color-gray-5)',
|
||||
codeFontSize: '0.875rem',
|
||||
},
|
||||
},
|
||||
sidebar,
|
||||
}),
|
||||
],
|
||||
});
|
||||
Generated
+6904
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "site",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/starlight": "^0.41.4",
|
||||
"astro": "^7.0.2",
|
||||
"sharp": "^0.34.5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M81 36 64 0 47 36l-1 2-9-10a6 6 0 0 0-9 9l10 10h-2L0 64l36 17h2L28 91a6 6 0 1 0 9 9l9-10 1 2 17 36 17-36v-2l9 10a6 6 0 1 0 9-9l-9-9 2-1 36-17-36-17-2-1 9-9a6 6 0 1 0-9-9l-9 10v-2Zm-17 2-2 5c-4 8-11 15-19 19l-5 2 5 2c8 4 15 11 19 19l2 5 2-5c4-8 11-15 19-19l5-2-5-2c-8-4-15-11-19-19l-2-5Z" clip-rule="evenodd"/><path d="M118 19a6 6 0 0 0-9-9l-3 3a6 6 0 1 0 9 9l3-3Zm-96 4c-2 2-6 2-9 0l-3-3a6 6 0 1 1 9-9l3 3c3 2 3 6 0 9Zm0 82c-2-2-6-2-9 0l-3 3a6 6 0 1 0 9 9l3-3c3-2 3-6 0-9Zm96 4a6 6 0 0 1-9 9l-3-3a6 6 0 1 1 9-9l3 3Z"/><style>path{fill:#000}@media (prefers-color-scheme:dark){path{fill:#fff}}</style></svg>
|
||||
|
After Width: | Height: | Size: 696 B |
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
@@ -0,0 +1,25 @@
|
||||
import { defineCollection } from 'astro:content';
|
||||
import { z } from 'astro/zod';
|
||||
import { docsLoader } from '@astrojs/starlight/loaders';
|
||||
import { docsSchema } from '@astrojs/starlight/schema';
|
||||
|
||||
export const collections = {
|
||||
docs: defineCollection({
|
||||
loader: docsLoader(),
|
||||
schema: docsSchema({
|
||||
// z.strictObject (not z.object) so that Zod v4's default key-stripping
|
||||
// doesn't silently swallow typos in generated frontmatter — an unknown
|
||||
// key like `bogusField` must fail the build, not disappear quietly.
|
||||
extend: z.strictObject({
|
||||
// Include this page in the generated man page.
|
||||
man: z.boolean().default(true),
|
||||
// Publish this page to the website.
|
||||
site: z.boolean().default(true),
|
||||
// Verbatim heading text used by the man page renderer.
|
||||
manTitle: z.string().optional(),
|
||||
// Keywords resolving to this page via `help config <keyword>`.
|
||||
helpKeywords: z.array(z.string()).default([]),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
};
|
||||
@@ -0,0 +1,148 @@
|
||||
/* Catppuccin Mocha (dark) / Latte (light) mapped onto Starlight tokens. */
|
||||
:root {
|
||||
--ctp-rosewater: #f5e0dc;
|
||||
--ctp-pink: #f5c2e7;
|
||||
--ctp-mauve: #cba6f7;
|
||||
--ctp-red: #f38ba8;
|
||||
--ctp-peach: #fab387;
|
||||
--ctp-yellow: #f9e2af;
|
||||
--ctp-green: #a6e3a1;
|
||||
--ctp-teal: #94e2d5;
|
||||
--ctp-sky: #89dceb;
|
||||
--ctp-blue: #89b4fa;
|
||||
--ctp-lavender: #b4befe;
|
||||
--ctp-surface: #313244;
|
||||
|
||||
--sl-color-accent-low: #1e1e2e;
|
||||
--sl-color-accent: #89b4fa;
|
||||
--sl-color-accent-high: #b4befe;
|
||||
--sl-color-white: #cdd6f4;
|
||||
--sl-color-gray-1: #bac2de;
|
||||
--sl-color-gray-2: #a6adc8;
|
||||
--sl-color-gray-3: #7f849c;
|
||||
--sl-color-gray-4: #585b70;
|
||||
--sl-color-gray-5: #45475a;
|
||||
--sl-color-gray-6: #313244;
|
||||
--sl-color-black: #181825;
|
||||
}
|
||||
|
||||
:root[data-theme='light'] {
|
||||
--ctp-rosewater: #dc8a78;
|
||||
--ctp-pink: #ea76cb;
|
||||
--ctp-mauve: #8839ef;
|
||||
--ctp-red: #d20f39;
|
||||
--ctp-peach: #fe640b;
|
||||
--ctp-yellow: #df8e1d;
|
||||
--ctp-green: #40a02b;
|
||||
--ctp-teal: #179299;
|
||||
--ctp-sky: #04a5e5;
|
||||
--ctp-blue: #1e66f5;
|
||||
--ctp-lavender: #7287fd;
|
||||
--ctp-surface: #ccd0da;
|
||||
|
||||
--sl-color-accent-low: #dce0e8;
|
||||
--sl-color-accent: #1e66f5;
|
||||
--sl-color-accent-high: #7287fd;
|
||||
--sl-color-white: #4c4f69;
|
||||
--sl-color-gray-1: #5c5f77;
|
||||
--sl-color-gray-2: #6c6f85;
|
||||
--sl-color-gray-3: #7c7f93;
|
||||
--sl-color-gray-4: #9ca0b0;
|
||||
--sl-color-gray-5: #bcc0cc;
|
||||
--sl-color-gray-6: #ccd0da;
|
||||
--sl-color-black: #eff1f5;
|
||||
}
|
||||
|
||||
/* ── Headings ──────────────────────────────────────────────────────── */
|
||||
/* The manual is one long reference; tinting each level makes the
|
||||
hierarchy scannable without relying on size alone. */
|
||||
.sl-markdown-content h1 {
|
||||
color: var(--ctp-lavender);
|
||||
}
|
||||
|
||||
.sl-markdown-content h2 {
|
||||
color: var(--ctp-green);
|
||||
border-bottom: 1px solid var(--sl-color-gray-5);
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
|
||||
.sl-markdown-content h3 {
|
||||
color: var(--ctp-blue);
|
||||
}
|
||||
|
||||
.sl-markdown-content h4 {
|
||||
color: var(--ctp-teal);
|
||||
}
|
||||
|
||||
/* ── Inline code ───────────────────────────────────────────────────── */
|
||||
/* Function names, variables, and flags appear inline constantly; peach
|
||||
separates them from prose the way the fenced blocks separate examples. */
|
||||
.sl-markdown-content :not(pre) > code {
|
||||
color: var(--ctp-peach);
|
||||
background: var(--ctp-surface);
|
||||
border: 1px solid var(--sl-color-gray-5);
|
||||
border-radius: 0.3em;
|
||||
padding: 0.1em 0.35em;
|
||||
}
|
||||
|
||||
.sl-markdown-content a > code {
|
||||
color: var(--ctp-sky);
|
||||
}
|
||||
|
||||
/* ── Links ─────────────────────────────────────────────────────────── */
|
||||
.sl-markdown-content a:not(:where(.not-content *)) {
|
||||
color: var(--ctp-sky);
|
||||
text-decoration-color: var(--sl-color-gray-4);
|
||||
}
|
||||
|
||||
.sl-markdown-content a:not(:where(.not-content *)):hover {
|
||||
color: var(--ctp-teal);
|
||||
text-decoration-color: currentColor;
|
||||
}
|
||||
|
||||
/* ── Cards ─────────────────────────────────────────────────────────── */
|
||||
/* Each function category is a grid of LinkCards; a hover accent makes the
|
||||
grid feel navigable rather than like a wall of boxes. */
|
||||
.card {
|
||||
border-color: var(--sl-color-gray-5);
|
||||
transition:
|
||||
border-color 150ms ease,
|
||||
transform 150ms ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
border-color: var(--ctp-green);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.card .title {
|
||||
color: var(--ctp-lavender);
|
||||
}
|
||||
|
||||
/* ── Asides ────────────────────────────────────────────────────────── */
|
||||
.starlight-aside--note {
|
||||
--sl-color-asides-text-accent: var(--ctp-blue);
|
||||
}
|
||||
|
||||
.starlight-aside--tip {
|
||||
--sl-color-asides-text-accent: var(--ctp-mauve);
|
||||
}
|
||||
|
||||
.starlight-aside--caution {
|
||||
--sl-color-asides-text-accent: var(--ctp-yellow);
|
||||
}
|
||||
|
||||
.starlight-aside--danger {
|
||||
--sl-color-asides-text-accent: var(--ctp-red);
|
||||
}
|
||||
|
||||
/* ── Site chrome ───────────────────────────────────────────────────── */
|
||||
.site-title {
|
||||
color: var(--ctp-green);
|
||||
}
|
||||
|
||||
/* Table headers carry the accent so the many reference tables in the
|
||||
manual read as structured data at a glance. */
|
||||
.sl-markdown-content th {
|
||||
color: var(--ctp-yellow);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [".astro/types.d.ts", "**/*"],
|
||||
"exclude": ["dist"]
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Split docs/fish-config.md into a multi-page Markdown wiki in docs/wiki/.
|
||||
|
||||
Index page: docs/wiki/index.md — DESCRIPTION intro + full ToC
|
||||
Section pages: docs/wiki/<n>-<slug>.md — one per numbered section,
|
||||
with a top-level nav bar linking to every other section.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Sections whose content is merged into the index intro.
|
||||
INTRO_TITLES = {"NAME", "SYNOPSIS", "DESCRIPTION"}
|
||||
|
||||
# Sections that are skipped entirely (replaced by the generated ToC).
|
||||
SKIP_TITLES = {"TABLE OF CONTENTS"}
|
||||
|
||||
|
||||
def strip_front_matter(text: str) -> str:
|
||||
"""Remove pandoc YAML front matter (--- ... ---) from the start."""
|
||||
if text.startswith("---"):
|
||||
end = text.index("\n---\n", 3) + 5
|
||||
return text[end:]
|
||||
return text
|
||||
|
||||
|
||||
def slugify(title: str) -> str:
|
||||
"""Convert a section title to a kebab-case filename slug."""
|
||||
s = title.lower()
|
||||
s = re.sub(r"[^\w\s-]", "", s)
|
||||
s = re.sub(r"[\s_]+", "-", s).strip("-")
|
||||
return s
|
||||
|
||||
|
||||
def build_nav(sections: list, current_filename: str | None = None) -> str:
|
||||
"""Return a one-line navigation bar for a section page."""
|
||||
parts = ["[Index](index.md)"]
|
||||
for s in sections:
|
||||
label = s["title"].title()
|
||||
if s["filename"] == current_filename:
|
||||
parts.append(f"**{label}**")
|
||||
else:
|
||||
parts.append(f"[{label}]({s['filename']})")
|
||||
return "**Sections:** " + " | ".join(parts)
|
||||
|
||||
|
||||
def build_full_toc(sections: list) -> str:
|
||||
"""Return a Markdown ToC list for the index page."""
|
||||
lines = ["## Table of Contents", ""]
|
||||
for s in sections:
|
||||
lines.append(f"- [{s['title'].title()}]({s['filename']})")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
src = Path("docs/fish-config.md")
|
||||
out_dir = Path("docs/wiki")
|
||||
|
||||
if not src.exists():
|
||||
print(f"error: {src} not found", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
text = strip_front_matter(src.read_text())
|
||||
|
||||
# Split on level-1 headings; re.split keeps the delimiters.
|
||||
parts = re.split(r"^(# .+)$", text, flags=re.MULTILINE)
|
||||
# parts[0] — text before first heading (empty after front-matter strip)
|
||||
# parts[1,3,…] — headings
|
||||
# parts[2,4,…] — body content after each heading
|
||||
|
||||
raw_sections = []
|
||||
for i in range(1, len(parts), 2):
|
||||
heading = parts[i].strip()
|
||||
body = parts[i + 1] if i + 1 < len(parts) else ""
|
||||
title = heading[2:].strip() # strip leading '# '
|
||||
raw_sections.append({"heading": heading, "title": title, "body": body})
|
||||
|
||||
intro_parts = []
|
||||
numbered_sections = []
|
||||
for s in raw_sections:
|
||||
if s["title"] in INTRO_TITLES:
|
||||
if s["title"] == "DESCRIPTION":
|
||||
intro_parts.append(s["body"].strip())
|
||||
elif s["title"] in SKIP_TITLES:
|
||||
pass # discard; ToC is auto-generated
|
||||
else:
|
||||
slug = slugify(s["title"])
|
||||
s["filename"] = f"{slug}.md"
|
||||
numbered_sections.append(s)
|
||||
|
||||
# ── Write index.md ──────────────────────────────────────────────────────
|
||||
intro_body = "\n\n".join(intro_parts).rstrip()
|
||||
# Strip any trailing thematic break that the source adds before the ToC.
|
||||
intro_body = re.sub(r"\n+---\s*$", "", intro_body)
|
||||
toc = build_full_toc(numbered_sections)
|
||||
index_content = f"# Fish Shell Configuration\n\n{intro_body}\n\n---\n\n{toc}\n"
|
||||
(out_dir / "index.md").write_text(index_content)
|
||||
print(" wrote docs/wiki/index.md")
|
||||
|
||||
# ── Write section pages ──────────────────────────────────────────────────
|
||||
for s in numbered_sections:
|
||||
nav = build_nav(numbered_sections, current_filename=s["filename"])
|
||||
page_content = (
|
||||
f"{s['heading']}\n\n"
|
||||
f"{nav}\n\n"
|
||||
f"---\n\n"
|
||||
f"{s['body'].strip()}\n"
|
||||
)
|
||||
(out_dir / s["filename"]).write_text(page_content)
|
||||
print(f" wrote docs/wiki/{s['filename']}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,314 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Verification checks for the docs/manual SSOT pipeline."""
|
||||
|
||||
import importlib.util
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import manualtools as mt
|
||||
|
||||
# docs/build-manual.py follows this repo's hyphenated CLI-script naming
|
||||
# convention (matching verify-manual.py), which means it
|
||||
# cannot satisfy a plain `import build_manual` on its own — Python's import
|
||||
# statement never treats a hyphen as an underscore. Load it explicitly under
|
||||
# the name the tests expect and register it in sys.modules; every later
|
||||
# `import build_manual` (including the one inside test_concat_roundtrips_
|
||||
# original below) then finds the cached module instead of touching the path
|
||||
# finder.
|
||||
_build_manual_path = Path(__file__).parent / "build-manual.py"
|
||||
_spec = importlib.util.spec_from_file_location("build_manual", _build_manual_path)
|
||||
_build_manual = importlib.util.module_from_spec(_spec)
|
||||
sys.modules["build_manual"] = _build_manual
|
||||
_spec.loader.exec_module(_build_manual)
|
||||
|
||||
|
||||
def test_parse_roundtrip():
|
||||
fm = {"title": "Git", "sidebar": {"order": 4}, "helpKeywords": ["git", "gi"]}
|
||||
body = "## gitig\n\nManages ignore files."
|
||||
text = mt.serialize(fm, body)
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
p = Path(d) / "t.md"
|
||||
p.write_text(text)
|
||||
got_fm, got_body = mt.parse(p)
|
||||
assert got_fm == fm, f"frontmatter mismatch: {got_fm!r}"
|
||||
assert got_body == body, f"body mismatch: {got_body!r}"
|
||||
|
||||
|
||||
def test_parse_no_frontmatter():
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
p = Path(d) / "t.md"
|
||||
p.write_text("# Plain\n\ntext\n")
|
||||
fm, body = mt.parse(p)
|
||||
assert fm == {}, f"expected empty frontmatter, got {fm!r}"
|
||||
assert body == "# Plain\n\ntext", f"body mismatch: {body!r}"
|
||||
|
||||
|
||||
def test_shift_headings():
|
||||
body = "## a\n\ntext\n\n### b"
|
||||
assert mt.shift_headings(body, 1) == "### a\n\ntext\n\n#### b"
|
||||
|
||||
|
||||
def test_shift_headings_skips_code_fences():
|
||||
body = "## a\n\n```\n# not a heading\n```\n\n## b"
|
||||
got = mt.shift_headings(body, 1)
|
||||
assert "# not a heading" in got, "code fence content was modified"
|
||||
assert got.startswith("### a"), f"heading not shifted: {got[:10]!r}"
|
||||
|
||||
|
||||
def test_walk_orders_by_sidebar_order_then_filename():
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
root = Path(d)
|
||||
(root / "b.md").write_text(mt.serialize({"title": "B", "sidebar": {"order": 1}}, ""))
|
||||
(root / "a.md").write_text(mt.serialize({"title": "A", "sidebar": {"order": 2}}, ""))
|
||||
(root / "c.md").write_text(mt.serialize({"title": "C"}, ""))
|
||||
got = [p.name for p, _ in mt.walk(root)]
|
||||
assert got == ["b.md", "a.md", "c.md"], f"wrong order: {got}"
|
||||
|
||||
|
||||
def test_walk_nests_directory_after_its_index():
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
root = Path(d)
|
||||
(root / "01-first.md").write_text(mt.serialize({"title": "First"}, ""))
|
||||
sub = root / "02-group"
|
||||
sub.mkdir()
|
||||
(sub / "index.md").write_text(mt.serialize({"title": "Group"}, ""))
|
||||
(sub / "01-child.md").write_text(mt.serialize({"title": "Child"}, ""))
|
||||
(root / "03-last.md").write_text(mt.serialize({"title": "Last"}, ""))
|
||||
got = [(p.name, depth) for p, depth in mt.walk(root)]
|
||||
expected = [
|
||||
("01-first.md", 0),
|
||||
("index.md", 0),
|
||||
("01-child.md", 1),
|
||||
("03-last.md", 0),
|
||||
]
|
||||
assert got == expected, f"wrong nesting: {got}"
|
||||
|
||||
|
||||
def test_parse_roundtrip_body_with_leading_blank_line():
|
||||
fm = {"title": "Test"}
|
||||
body = "\nContent starts after blank line."
|
||||
text = mt.serialize(fm, body)
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
p = Path(d) / "t.md"
|
||||
p.write_text(text)
|
||||
got_fm, got_body = mt.parse(p)
|
||||
assert got_fm == fm, f"frontmatter mismatch: {got_fm!r}"
|
||||
assert got_body == body, f"body mismatch: expected {body!r}, got {got_body!r}"
|
||||
|
||||
|
||||
def test_manual_tree_exists():
|
||||
root = Path(__file__).parent / "manual"
|
||||
assert root.is_dir(), "docs/manual/ not generated"
|
||||
assert (root / "index.md").exists(), "docs/manual/index.md missing"
|
||||
fn = root / "05-functions"
|
||||
assert fn.is_dir(), "docs/manual/05-functions/ missing"
|
||||
cats = sorted(p.name for p in fn.glob("*.md") if p.name != "index.md")
|
||||
assert len(cats) == 14, f"expected 14 function categories, got {len(cats)}: {cats}"
|
||||
|
||||
|
||||
def test_function_entries_promoted_to_h2():
|
||||
root = Path(__file__).parent / "manual" / "05-functions"
|
||||
for path in root.glob("*.md"):
|
||||
if path.name == "index.md":
|
||||
continue
|
||||
_, body = mt.parse(path)
|
||||
assert "\n### " not in f"\n{body}", f"{path.name} still has H3 entries"
|
||||
assert "\n## " in f"\n{body}", f"{path.name} has no H2 function entries"
|
||||
|
||||
|
||||
def _normalise(text: str) -> str:
|
||||
"""Collapse whitespace so only content differences survive."""
|
||||
lines = [ln.rstrip() for ln in text.strip().split("\n")]
|
||||
return "\n".join(ln for ln in lines if ln != "")
|
||||
|
||||
|
||||
def test_concat_roundtrips_original():
|
||||
"""The concat of manual/ must reproduce the original fish-config.md exactly.
|
||||
|
||||
Prefers docs/fish-config.md.orig (a snapshot of the pre-migration file)
|
||||
when present. Once that snapshot is deleted post-migration,
|
||||
docs/fish-config.md IS the concat output regenerated in Step 5, so
|
||||
falling back to it turns this into an idempotency regression check
|
||||
instead of going red for a missing file.
|
||||
|
||||
The pass/fail decision is an exact (raw-text) comparison, not a
|
||||
whitespace-normalised one. Blank lines are load-bearing for pandoc
|
||||
(`blank_before_header` is on by default): losing them merges paragraphs
|
||||
and stops headings being headings, so a test that tolerated blank-line
|
||||
or line-joining drift would stay green while the man page silently
|
||||
broke. `_normalise` is used only afterwards, to build a readable diff.
|
||||
"""
|
||||
import build_manual
|
||||
|
||||
docs = Path(__file__).parent
|
||||
original = docs / "fish-config.md.orig"
|
||||
label = "original"
|
||||
if not original.exists():
|
||||
original = docs / "fish-config.md"
|
||||
label = "fish-config.md"
|
||||
got = build_manual.build_concat(docs / "manual")
|
||||
want = original.read_text()
|
||||
if got != want:
|
||||
norm_got = _normalise(got)
|
||||
norm_want = _normalise(want)
|
||||
if norm_got == norm_want:
|
||||
raise AssertionError(
|
||||
"concat differs from original only in whitespace/blank lines "
|
||||
"(exact comparison failed, normalised comparison passed) — "
|
||||
"blank lines are load-bearing for pandoc, this is a real regression"
|
||||
)
|
||||
import difflib
|
||||
|
||||
diff = list(
|
||||
difflib.unified_diff(
|
||||
norm_want.split("\n"), norm_got.split("\n"), label, "concat", lineterm="", n=1
|
||||
)
|
||||
)[:40]
|
||||
raise AssertionError("concat differs from original:\n" + "\n".join(diff))
|
||||
|
||||
|
||||
def test_every_index_keyword_resolves():
|
||||
"""Every keyword in fish-config.index must match a heading in the concat."""
|
||||
import build_manual
|
||||
|
||||
docs = Path(__file__).parent
|
||||
index = docs / "fish-config.index"
|
||||
if not index.exists():
|
||||
print(" SKIP test_every_index_keyword_resolves (no index file)")
|
||||
return
|
||||
concat = build_manual.build_concat(docs / "manual")
|
||||
headings = {ln.strip() for ln in concat.split("\n") if ln.startswith("#")}
|
||||
missing = []
|
||||
for line in index.read_text().splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
keyword, heading = line.split("=", 1)
|
||||
if heading.strip() not in headings:
|
||||
missing.append(f"{keyword.strip()} -> {heading.strip()}")
|
||||
assert not missing, "unresolvable index keywords:\n " + "\n ".join(missing)
|
||||
|
||||
|
||||
def test_site_build_produces_function_pages():
|
||||
import tempfile
|
||||
|
||||
import build_manual
|
||||
|
||||
docs = Path(__file__).parent
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
out = Path(d)
|
||||
sidebar = build_manual.build_site(docs / "manual", out)
|
||||
pages = list(out.rglob("*.md*"))
|
||||
assert (out / "index.md").exists(), "landing page missing"
|
||||
fn_pages = [p for p in pages if "functions" in p.parts and p.name != "index.mdx"]
|
||||
assert len(fn_pages) > 80, f"expected >80 function pages, got {len(fn_pages)}"
|
||||
assert not (out / "00-name.md").exists(), "site:false page was published"
|
||||
assert sidebar, "sidebar structure is empty"
|
||||
for page in pages:
|
||||
fm, _ = mt.parse(page)
|
||||
assert "manTitle" not in fm, f"{page.name} leaked manTitle into site output"
|
||||
assert "title" in fm, f"{page.name} has no title"
|
||||
|
||||
|
||||
def test_prettify_splits_an_entry_block():
|
||||
"""A man-page-style entry becomes fenced code, prose, and a table."""
|
||||
import build_manual
|
||||
|
||||
body = "\n".join(
|
||||
[
|
||||
" Synopsis: rm [-e | args...]",
|
||||
" Safe rm wrapper routing to trash:",
|
||||
"",
|
||||
" (no args) List current trash contents",
|
||||
" -e/--empty Empty the trash",
|
||||
"",
|
||||
" Falls back to /usr/bin/rm when trash is unavailable.",
|
||||
"",
|
||||
" rm file.txt # moves to trash",
|
||||
" rm -e # empty trash",
|
||||
]
|
||||
)
|
||||
out = build_manual.prettify(body, "rm")
|
||||
|
||||
assert "```fish\nrm [-e | args...]\n```" in out, "synopsis was not fenced as fish"
|
||||
assert "```fish\nrm file.txt" in out, "examples were not fenced as fish"
|
||||
assert out.count("```") == 4, f"expected exactly two fences, got:\n{out}"
|
||||
assert "\nSafe rm wrapper routing to trash:" in out, "description stayed indented"
|
||||
assert (
|
||||
"\n (no args) List current trash contents" in out
|
||||
), "option table lost its indentation"
|
||||
assert (
|
||||
"\nFalls back to /usr/bin/rm when trash is unavailable." in out
|
||||
), "trailing prose stayed indented"
|
||||
|
||||
|
||||
def test_prettify_leaves_reference_tables_alone():
|
||||
"""Column-aligned blocks are data, not shell, and must not be fenced."""
|
||||
import build_manual
|
||||
|
||||
table = " XDG_CONFIG_HOME ~/.config\n XDG_CACHE_HOME ~/.cache"
|
||||
assert "```" not in build_manual.prettify(table), "a reference table got fenced"
|
||||
|
||||
binds = " n / nv / neovim nvim\n e edit"
|
||||
assert "```" not in build_manual.prettify(binds), "an abbreviation table got fenced"
|
||||
|
||||
shell = " set -U __fish_user_dots_path /path/to/dots"
|
||||
assert "```fish" in build_manual.prettify(shell), "a shell block was not fenced"
|
||||
|
||||
|
||||
def test_prettify_is_site_only():
|
||||
"""The SSOT keeps the indented form the man-page pipeline depends on."""
|
||||
import build_manual
|
||||
|
||||
manual = Path(__file__).parent / "manual"
|
||||
for path in manual.rglob("*.md"):
|
||||
assert "```" not in path.read_text(), (
|
||||
f"{path.name} contains a fence: prettify must run at site-build "
|
||||
"time, never be written back to the SSOT"
|
||||
)
|
||||
|
||||
|
||||
def test_sidebar_has_no_duplicate_functions_entry():
|
||||
"""The functions group must not also list itself as one of its children."""
|
||||
import build_manual
|
||||
|
||||
docs = Path(__file__).parent
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
sidebar = build_manual.build_site(docs / "manual", Path(d))
|
||||
|
||||
groups = [e for e in sidebar if "items" in e]
|
||||
assert len(groups) == 1, f"expected one sidebar group, got {len(groups)}"
|
||||
group = groups[0]
|
||||
labels = [item["label"] for item in group["items"]]
|
||||
assert group["label"] not in labels[1:], (
|
||||
f"'{group['label']}' is repeated inside its own group: {labels}"
|
||||
)
|
||||
assert labels[0] == "Overview", f"group should lead with Overview, got {labels[0]}"
|
||||
assert not any(
|
||||
"autogenerate" in item for item in group["items"]
|
||||
), "categories should be listed explicitly, not autogenerated from slugs"
|
||||
assert len(labels) == 15, f"expected Overview + 14 categories, got {len(labels)}"
|
||||
|
||||
|
||||
TESTS = [v for k, v in sorted(globals().items()) if k.startswith("test_")]
|
||||
|
||||
|
||||
def main() -> int:
|
||||
failed = 0
|
||||
for t in TESTS:
|
||||
try:
|
||||
t()
|
||||
print(f" PASS {t.__name__}")
|
||||
except AssertionError as e:
|
||||
print(f" FAIL {t.__name__}: {e}", file=sys.stderr)
|
||||
failed += 1
|
||||
print(f"\n{len(TESTS) - failed}/{len(TESTS)} passed")
|
||||
return 1 if failed else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
raise SystemExit(main())
|
||||
@@ -1,74 +0,0 @@
|
||||
# 11. VIEWING THIS MANUAL
|
||||
|
||||
**Sections:** [Index](index.md) | [1. Configuration Variables](1-configuration-variables.md) | [2. Path Setup](2-path-setup.md) | [3. Key Bindings](3-key-bindings.md) | [4. Abbreviations](4-abbreviations.md) | [5. Functions Reference](5-functions-reference.md) | [6. Dependency Catalog](6-dependency-catalog.md) | [7. Customization](7-customization.md) | [8. Fisher Plugins](8-fisher-plugins.md) | [9. Installation](9-installation.md) | [10. Personalization](10-personalization.md) | **11. Viewing This Manual**
|
||||
|
||||
---
|
||||
|
||||
## With ov (recommended)
|
||||
|
||||
help config
|
||||
|
||||
ov renders the Markdown with syntax highlighting and section-based
|
||||
navigation.
|
||||
|
||||
Space next section
|
||||
^ previous section
|
||||
Alt+u toggle section list sidebar
|
||||
/ search forward
|
||||
n / N next / previous search match
|
||||
g go to line number
|
||||
j interactive jump target (line, %, or 'section')
|
||||
q quit
|
||||
|
||||
## With bat
|
||||
|
||||
bat --language=markdown --paging=always ~/.config/fish/docs/fish-config.md
|
||||
|
||||
## As a man page
|
||||
|
||||
help config --man
|
||||
help config pkg --man
|
||||
|
||||
Opens the compiled docs/fish-config.1 directly via man -l, bypassing
|
||||
the pager fallback chain. If a section keyword is given, the pager opens
|
||||
at the nearest matching heading. The symlink is created once on first
|
||||
run (like an install step) and MANPATH is set each session, enabling
|
||||
the standard invocation:
|
||||
|
||||
man fish-config
|
||||
|
||||
NOTE: fish-config (hyphen) is this config's man page. fish_config
|
||||
(underscore) is fish's built-in browser-based configuration tool —
|
||||
a completely separate command. Do not mix them up.
|
||||
|
||||
## In the browser (HTML)
|
||||
|
||||
help config --html
|
||||
help config pkg --html
|
||||
|
||||
Opens docs/html/index.html in the default web browser. If a section
|
||||
keyword is given, the browser opens directly at the matching anchor
|
||||
(resolved via docs/html/sitemap.json). Browser detection queries the
|
||||
system's x-scheme-handler/https MIME entry (via xdg-mime) to find the
|
||||
real browser binary, then falls back through known browser binaries
|
||||
(firefox, chromium, vivaldi, etc.), and finally xdg-open as a last
|
||||
resort. Set $fish_help_browser or $BROWSER to override.
|
||||
|
||||
## As a wiki
|
||||
|
||||
The generated Markdown wiki lives in docs/wiki/. index.md provides the
|
||||
project overview and a full table of contents. Each section page has a
|
||||
navigation bar at the top linking to every other section.
|
||||
|
||||
The wiki is auto-generated from this file by the CI pipeline on every
|
||||
push to main that changes docs/fish-config.md.
|
||||
|
||||
## Jumping to a section
|
||||
|
||||
help config keybindings
|
||||
help config abbreviations
|
||||
help config pkg
|
||||
help config logs
|
||||
help config fish-deps
|
||||
|
||||
The keyword is matched case-insensitively against section headings.
|
||||
File diff suppressed because it is too large
Load Diff
+23
-52
@@ -3,7 +3,7 @@
|
||||
|
||||
# SYNOPSIS
|
||||
# config-help [section]
|
||||
# config-help [section] --html
|
||||
# config-help --html
|
||||
# config-help [section] --man
|
||||
# config-help --help
|
||||
#
|
||||
@@ -14,14 +14,15 @@
|
||||
# that matches the keyword. Lookup order: docs/fish-config.index (exact
|
||||
# keyword aliases), then a normalized heading scan as fallback.
|
||||
# When opened with ov a sticky navigation hint is shown at the top of the
|
||||
# screen. Pass --html / -w to open the pre-built HTML version in the
|
||||
# default browser, jumping to the matching section anchor when possible.
|
||||
# Pass --man / -m to open the compiled man page; if a section keyword is
|
||||
# given, the pager opens at the nearest match. Pass --help or -h for usage.
|
||||
# screen. Pass --html / -w to open the published documentation website in
|
||||
# the default browser (deep links to a section aren't supported there —
|
||||
# use the site's search box). Pass --man / -m to open the compiled man
|
||||
# page; if a section keyword is given, the pager opens at the nearest
|
||||
# match. Pass --help or -h for usage.
|
||||
#
|
||||
# ARGUMENTS
|
||||
# section Optional keyword to jump to a matching section heading
|
||||
# -w, --html Open the offline HTML docs in the default browser
|
||||
# -w, --html Open the published documentation website in the default browser
|
||||
# -m, --man Open the compiled man page via man -l
|
||||
# -h, --help Print usage and navigation reference, then exit
|
||||
#
|
||||
@@ -35,7 +36,6 @@
|
||||
# config-help pkg
|
||||
# config-help fish-deps
|
||||
# config-help --html
|
||||
# config-help keys --html
|
||||
# config-help --man
|
||||
# config-help keys --man
|
||||
# config-help --help
|
||||
@@ -48,8 +48,7 @@ function config-help --description 'Open the offline fish shell configuration ma
|
||||
set -l doc_file "$__fish_config_dir/docs/fish-config.md"
|
||||
set -l idx_file "$__fish_config_dir/docs/fish-config.index"
|
||||
set -l man_file "$__fish_config_dir/docs/fish-config.1"
|
||||
set -l html_dir "$__fish_config_dir/docs/html"
|
||||
set -l sitemap "$html_dir/sitemap.json"
|
||||
set -l site_url "https://fish-config-docs.pages.dev/"
|
||||
|
||||
# ── Extract section keyword (first non-flag argument) ────────
|
||||
set -l section_kw ""
|
||||
@@ -97,49 +96,22 @@ function config-help --description 'Open the offline fish shell configuration ma
|
||||
|
||||
# ── --html / -w ──────────────────────────────────────────────
|
||||
if contains -- --html $argv; or contains -- -w $argv
|
||||
if not test -f "$html_dir/index.html"
|
||||
if test -n "$section_kw"
|
||||
set_color yellow
|
||||
echo "note: deep links aren't available on the website — opening the site root; use its search box to find '$section_kw'" >&2
|
||||
set_color normal
|
||||
end
|
||||
|
||||
if type -q xdg-open
|
||||
xdg-open "$site_url" &>/dev/null &
|
||||
disown
|
||||
else
|
||||
set_color red
|
||||
echo "error: HTML docs not found at $html_dir/index.html" >&2
|
||||
echo "error: no opener found — visit $site_url" >&2
|
||||
set_color normal
|
||||
return 1
|
||||
end
|
||||
|
||||
# Default to the index page; resolve a section fragment when possible.
|
||||
set -l html_path "index.html"
|
||||
if test -n "$found_text"; and test -f "$sitemap"
|
||||
# Convert heading text → pandoc anchor ID:
|
||||
# lowercase → strip non-alphanumeric (keep spaces and hyphens)
|
||||
# → spaces to hyphens → collapse runs → strip edge hyphens.
|
||||
set -l anchor (string lower -- $found_text \
|
||||
| string replace -ra '[^a-z0-9 -]' '' \
|
||||
| string replace -ra ' +' '-' \
|
||||
| string replace -ra -- '-+' '-' \
|
||||
| string trim -c '-')
|
||||
# 1. Sub-section: path stored as "filename.html#anchor"
|
||||
set -l match (grep -o "\"path\":\"[^\"]*#$anchor\"" "$sitemap" | head -1)
|
||||
if test -n "$match"
|
||||
set html_path (string replace -r '"path":"([^"]+)"' '$1' -- $match)
|
||||
else
|
||||
# 2. Top-level section: own page — "id":"anchor"..."path":"filename.html"
|
||||
set -l id_match (grep -o "\"id\":\"$anchor\"[^}]*\"path\":\"[^\"]*\"" "$sitemap" | head -1)
|
||||
if test -n "$id_match"
|
||||
set html_path (string replace -r '.*"path":"([^"]+)"' '$1' -- $id_match)
|
||||
else
|
||||
set_color yellow
|
||||
echo "note: no HTML anchor found for '$section_kw' — opening at top" >&2
|
||||
set_color normal
|
||||
end
|
||||
end
|
||||
else if test -n "$section_kw"
|
||||
set_color yellow
|
||||
echo "note: no section matching '$section_kw' — opening at top" >&2
|
||||
set_color normal
|
||||
end
|
||||
|
||||
set -l page_url "file://$html_dir/$html_path"
|
||||
|
||||
open-url $page_url
|
||||
return $status
|
||||
return 0
|
||||
end
|
||||
|
||||
# ── --man / -m ───────────────────────────────────────────────
|
||||
@@ -197,8 +169,8 @@ function config-help --description 'Open the offline fish shell configuration ma
|
||||
echo " Searches docs/fish-config.index for aliases first, then"
|
||||
echo " falls back to a normalized (case- and punctuation-insensitive)"
|
||||
echo " scan of heading lines."
|
||||
echo " "(set_color yellow)"-w, --html"(set_color normal)" Open the offline HTML docs in the default browser."
|
||||
echo " If a section keyword is given, opens at the matching anchor."
|
||||
echo " "(set_color yellow)"-w, --html"(set_color normal)" Open the published documentation website in the default browser."
|
||||
echo " Deep links aren't supported — use the site's search box."
|
||||
echo " "(set_color yellow)"-m, --man"(set_color normal)" Open the compiled man page via man -l."
|
||||
echo " If a section keyword is given, jumps to the nearest match."
|
||||
echo ""
|
||||
@@ -210,8 +182,7 @@ function config-help --description 'Open the offline fish shell configuration ma
|
||||
echo " "(set_color green)"help config pkg"(set_color normal)" jump to the pkg function entry"
|
||||
echo " "(set_color green)"help config fish-deps"(set_color normal)" jump to fish-deps"
|
||||
echo " "(set_color green)"help config abbreviations"(set_color normal)" jump to Abbreviations section"
|
||||
echo " "(set_color green)"help config --html"(set_color normal)" open HTML docs in browser"
|
||||
echo " "(set_color green)"help config keybindings --html"(set_color normal)" open HTML at Key Bindings"
|
||||
echo " "(set_color green)"help config --html"(set_color normal)" open the documentation website"
|
||||
echo " "(set_color green)"help config --man"(set_color normal)" open compiled man page"
|
||||
echo " "(set_color green)"help config pkg --man"(set_color normal)" open man page at pkg section"
|
||||
echo ""
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#
|
||||
# EXAMPLE
|
||||
# open-url https://git.rootiest.dev/rootiest/fish-config
|
||||
# open-url -v "file://$HOME/.config/fish/docs/html/index.html"
|
||||
# open-url -v https://fish-config-docs.pages.dev/
|
||||
function open-url --description 'Open a URL in the best available web browser'
|
||||
argparse h/help s/silent v/verbose -- $argv
|
||||
or return 1
|
||||
|
||||
Reference in New Issue
Block a user