Files
fish-config/functions/config_help.fish
T
rootiest 12d83112ea fix(config_help): use string split -m 1 to extract line number and text
string split -f does not accept ranges like '2-'; split on the first
colon only with -m 1 to correctly separate the grep line number from
the heading text without erroring on every heading line.
2026-06-06 03:40:43 -04:00

108 lines
3.8 KiB
Fish

# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# config_help [section]
#
# DESCRIPTION
# 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).
#
# ARGUMENTS
# section Optional keyword to jump to a matching section heading
#
# RETURNS
# 0 Manual displayed
# 1 Documentation file not found
#
# EXAMPLE
# config_help
# config_help keybindings
# config_help pkg
# 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 man_file "$__fish_config_dir/docs/fish-config.1"
if not test -f "$doc_file"
set_color red
echo "error: documentation not found at $doc_file" >&2
set_color normal
return 1
end
# ── Resolve section start line ───────────────────────────────
# Normalize both sides: strip non-alphanumeric chars and lowercase.
# This lets "keybindings" match "KEY BINDINGS", "fish-deps" match
# "fish-deps", etc. without requiring exact punctuation or case.
set -l start_line 1
if test -n "$argv[1]"
set -l norm_kw (string lower -- $argv[1] | string replace -ra '[^a-z0-9]' '')
set -l found ""
for entry in (grep -n "^#" "$doc_file")
set -l parts (string split -m 1 ':' -- $entry)
set -l lnum $parts[1]
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 $lnum
break
end
end
if test -n "$found"
set start_line $found
else
set_color yellow
echo "note: no section matching '$argv[1]' — opening at top" >&2
set_color normal
end
end
# ── Viewer fallback chain ────────────────────────────────────
# bat colors the output; ov matches headers via an ANSI-aware regex.
# bat emits: ESC[<color>m# ... so delimiter ^(\x1b\[[0-9;]*m)+# matches
# any 8/24-bit color sequence before a '#', theme-agnostic.
# Section nav: Space (next), ^ (previous), Alt+u (section list sidebar).
# psub creates a seekable temp file so --jump-target works on bat output.
if type -q ov; and type -q bat
set -l ov_args \
--section-delimiter "^(\x1b\[[0-9;]*m)+#" \
--section-header
if test $start_line -gt 1
set -a ov_args --jump-target $start_line
end
ov $ov_args (bat --color=always --style=plain --language=markdown "$doc_file" | psub)
# 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
set -a ov_args --jump-target $start_line
end
ov $ov_args "$doc_file"
# bat alone: syntax highlighting with built-in paging; no line jump.
else if type -q bat
if test $start_line -gt 1
set_color brblack
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"
man -l "$man_file"
else if type -q less
less +"$start_line" "$doc_file"
else
cat "$doc_file"
end
end