fix(config_help): reliable section lookup and jump via index + tail-slice

- Add docs/fish-config.index mapping 100+ keyword aliases to exact heading
  text; config_help looks up here first, falls back to normalized heading
  scan (strips non-alphanumeric, lowercases both sides) for unknown terms.
- Resolve line numbers at runtime with grep -F so the index never goes
  stale from doc edits — only heading renames require an update.
- Fix section jump: --section-header pins delimiter lines as sticky headers
  removing them from ov pattern-search scope. Replace --pattern with
  tail -n +$start_line piped before ov; the target section is the first
  line so no search is needed and forward section nav still works.
- Fix empty sections sidebar: ov matches --section-delimiter against
  logical (ANSI-stripped) text, so "^#" is correct for bat-colored output;
  the previous ANSI escape-sequence regex never matched anything.
This commit is contained in:
2026-06-06 04:09:12 -04:00
parent 02c27c6907
commit 368b714a98
3 changed files with 262 additions and 13 deletions
+176
View File
@@ -0,0 +1,176 @@
# Fish Config Help Index
# Format: keyword=exact heading text as it appears in fish-config.md
# Multiple keywords may map to the same heading.
# Update this file whenever headings are added, removed, or renamed.
# config_help uses this for fast exact lookups; unknown keywords fall back
# to a normalized heading scan automatically.
# ── Top-level ─────────────────────────────────────────────────
name=# NAME
synopsis=# SYNOPSIS
description=# DESCRIPTION
toc=# TABLE OF CONTENTS
contents=# TABLE OF CONTENTS
# ── Section 1: Configuration Variables ───────────────────────
variables=# 1. CONFIGURATION VARIABLES
config=# 1. CONFIGURATION VARIABLES
xdg=## Environment Directories (XDG)
toolhomes=## Tool Homes (XDG-compliant)
editor=## Editor and Pager
pager=## Editor and Pager
scrollback=## Scrollback History
# ── Section 2: PATH ───────────────────────────────────────────
path=# 2. PATH SETUP
# ── Section 3: Key Bindings ───────────────────────────────────
keybindings=# 3. KEY BINDINGS
bindings=# 3. KEY BINDINGS
key-bindings=# 3. KEY BINDINGS
keys=# 3. KEY BINDINGS
fzf-bindings=## FZF Bindings (from fzf --fish integration)
fzf=## FZF Bindings (from fzf --fish integration)
# ── Section 4: Abbreviations ──────────────────────────────────
abbreviations=# 4. ABBREVIATIONS
abbr=# 4. ABBREVIATIONS
abbrs=# 4. ABBREVIATIONS
editors-abbr=## 4.1 Editors
nav=## 4.2 Navigation and Listing
navigation=## 4.2 Navigation and Listing
listing=## 4.2 Navigation and Listing
git-abbr=## 4.3 Git
terminal=## 4.4 Terminal Windows, Tabs, and Panes
panes=## 4.4 Terminal Windows, Tabs, and Panes
windows=## 4.4 Terminal Windows, Tabs, and Panes
tabs=## 4.4 Terminal Windows, Tabs, and Panes
chezmoi=## 4.5 Chezmoi
docker=## 4.6 Docker
systemctl=## 4.7 Systemctl
systemd=## 4.7 Systemctl
ai-abbr=## 4.8 AI Assistants
history=## 4.9 History Expansion
misc-abbr=## 4.10 Miscellaneous
# ── Section 5: Functions ──────────────────────────────────────
functions=# 5. FUNCTIONS REFERENCE
files=## 5.1 File and Directory
cat=### cat
copy=### copy
du=### du
dusize=### dusize
ls=### ls
lsr=### lsr
lss=### lss
lstree=### lstree
lt=### lt
ltr=### ltr
lx=### lx
mkdir=### mkdir
mkcd=### mkcd
poke=### poke
rm=### rm
scrub=### scrub
nav-fns=## 5.2 Navigation
cdi=### cdi
clone=### clone
clonet=### clonet
editors=## 5.3 Editors and Viewers
edit=### edit
fc=### fc
less=### less
rawfish=### rawfish
view=### view
git=## 5.4 Git and Version Control
branch=### branch
gi=### gi
gitignore=### gi
git-clean=### git-clean
gitup=### gitup
gitui=### gitui
hist=### hist
pkg=### pkg
package=### pkg
package-manager=## 5.5 Package Management
packages=## 5.5 Package Management
search=### search
upgrade=### upgrade
cleanup=### cleanup
parur=### parur
deps=## 5.6 Dependency Management
fish-deps=### fish-deps
check-deps=### check_fish_deps
system=## 5.7 System and Monitoring
top=### top
swapstat=### swapstat
sbver=### sbver
ports=### ports
screensleep=### screensleep
lock=### lock
sudo-toggle=### sudo-toggle
limine=### limine-edit
terminal-mgmt=## 5.8 Terminal Management
tab=### tab
split=### split
spwin=### spwin
detach=### detach
bkg=### bkg
ssh=### ssh
clipboard=## 5.9 Clipboard
copy-fn=### y
paste=### paste
network=## 5.10 Network
gip=### gip
ping=### ping
qr=### qr
logging=## 5.11 Pager and Logging
logs=### logs
smart-exit=### smart_exit
ai=## 5.12 AI and Developer Tools
antigravity=### antigravity
claude=### claude-resume
claude-docs=### claude-docs
claude-pr=### claude-pr
code-resume=### code-resume
superpowers=### superpowers
media=## 5.13 Media and Utilities
dng2avif=### dng2avif
spark=### spark
miscfns=## 5.14 Miscellaneous
bash=### bash
cheat=### cheat
dockup=### dockup
joplin=### joplin
replay=### replay
tmux=### tmux-clean
wake-lock=### wake-lock
zellij=### zellij
# ── Section 6: Dependency Catalog ────────────────────────────
catalog=# 6. DEPENDENCY CATALOG
deps-catalog=# 6. DEPENDENCY CATALOG
required=## Required
integrations=## Integrations
recommended=## Recommended
install-methods=## Install Methods
# ── Section 7: Customization ──────────────────────────────────
customization=# 7. CUSTOMIZATION
customize=# 7. CUSTOMIZATION
local=## Machine-local Configuration
secrets=## Secrets and API Keys
overrides=## Overriding Configuration Variables
universal=## Fish Universal Variables
# ── Section 8: Fisher Plugins ─────────────────────────────────
plugins=# 8. FISHER PLUGINS
fisher=# 8. FISHER PLUGINS
# ── Section 9: Viewing This Manual ───────────────────────────
viewing=# 9. VIEWING THIS MANUAL
manual=# 9. VIEWING THIS MANUAL
ov=## With ov (recommended)
man-page=## As a man page (if compiled)
manpage=## As a man page (if compiled)
jump=## Jumping to a section
+10 -1
View File
@@ -1216,7 +1216,16 @@ calls fisher update as its first step.
config_help
ov renders the Markdown with syntax highlighting and section-based
navigation. Use , and . to jump between sections. Press / to search.
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
+76 -12
View File
@@ -8,7 +8,11 @@
# Opens the offline fish shell configuration manual in the best available
# pager. Falls back through ov -> bat -> man -> less -> cat.
# If a section keyword is provided, the pager opens at the first heading
# that matches the keyword (case-insensitive).
# that matches the keyword. Lookup order: docs/fish-config.index (exact
# keyword aliases), then a normalized heading scan as fallback.
# When jumping to a section the file is sliced from that line onwards so
# ov never has to search through section-header lines (which --section-header
# pins and hides from pattern matching).
#
# ARGUMENTS
# section Optional keyword to jump to a matching section heading
@@ -24,6 +28,7 @@
# config_help fish-deps
function config_help --description 'Open the offline fish shell configuration manual'
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"
if not test -f "$doc_file"
@@ -34,11 +39,47 @@ function config_help --description 'Open the offline fish shell configuration ma
end
# ── Resolve section start line ───────────────────────────────
# 1. Look up keyword in fish-config.index (keyword → exact heading text).
# 2. Fall back to normalized scan of heading lines if not in index.
# 3. Resolve start_line via grep -F on the heading text (immune to line
# number drift — only breaks if the heading itself is renamed).
set -l start_line 1
if test -n "$argv[1]"
set -l found (grep -n -im 1 "^#\+.*$argv[1]" "$doc_file" | cut -d: -f1)
if test -n "$found"
set start_line $found
set -l norm_kw (string lower -- $argv[1] | string replace -ra '[^a-z0-9]' '')
set -l found_text ""
# ── Index lookup ─────────────────────────────────────────
if test -f "$idx_file"
while read -l idxline
string match -qr '^[[:space:]]*(#|$)' -- $idxline; and continue
set -l kv (string split -m 1 '=' -- $idxline)
test (count $kv) -lt 2; and continue
set -l k (string lower -- $kv[1] | string replace -ra '[^a-z0-9]' '')
if test "$k" = "$norm_kw"
set found_text $kv[2]
break
end
end < "$idx_file"
end
# ── Normalized scan fallback ─────────────────────────────
if test -z "$found_text"
for entry in (grep -n "^#" "$doc_file")
set -l parts (string split -m 1 ':' -- $entry)
set -l text $parts[2]
set -l norm_text (string lower -- $text | string replace -ra '[^a-z0-9]' '')
if string match -q "*$norm_kw*" $norm_text
set found_text $text
break
end
end
end
if test -n "$found_text"
set -l lnum (grep -Fn "$found_text" "$doc_file" | cut -d: -f1 | head -1)
if test -n "$lnum"
set start_line $lnum
end
else
set_color yellow
echo "note: no section matching '$argv[1]' — opening at top" >&2
@@ -47,23 +88,46 @@ function config_help --description 'Open the offline fish shell configuration ma
end
# ── Viewer fallback chain ────────────────────────────────────
if type -q ov
ov --syntax --syntax-name markdown \
--section-delimiter "^#" \
--section-header \
+"$start_line" "$doc_file"
# When jumping to a section, slice the file from start_line so ov
# opens with that section at the top without needing --pattern.
# --pattern on section-delimiter lines is unreliable: --section-header
# pins those lines as sticky headers, removing them from search scope.
# Section nav: Space (next), ^ (previous), Alt+u (section list sidebar).
if type -q ov; and type -q bat
set -l ov_args \
--section-delimiter "^#" \
--section-header
if test $start_line -gt 1
bat --color=always --style=plain --language=markdown "$doc_file" \
| tail -n +$start_line \
| ov $ov_args
else
bat --color=always --style=plain --language=markdown "$doc_file" \
| ov $ov_args
end
# ov alone: section navigation on raw Markdown; no code highlighting.
else if type -q ov
set -l ov_args \
--section-delimiter "^#" \
--section-header
if test $start_line -gt 1
tail -n +$start_line "$doc_file" | ov $ov_args
else
ov $ov_args "$doc_file"
end
# bat alone: syntax highlighting with built-in paging; no line jump.
else if type -q bat
if test $start_line -gt 1
# bat can't jump to a line in paging mode; show a hint instead
set_color brblack
echo "note: bat pager active — use / to search for your section" >&2
echo "note: bat pager — use / to search for your section" >&2
set_color normal
end
bat --language=markdown --paging=always "$doc_file"
# Pre-compiled man page (generated by CI after merge).
else if test -f "$man_file"
# Pre-compiled man page as a pager-independent fallback
man -l "$man_file"
else if type -q less