# Sphinx configuration for zsh documentation (rST from yodl2rst).
#
# Used via: make -f sphinx.mk html|html-web|man|pdf|fallback-pdf|…
# Config directory is Doc/sphinx-config/; sources live in Doc/source/.
#
# HTML themes (selected with Sphinx tags, not -D):
#   default     — basic, no sidebar, no search/JS  → distribution / lynx-friendly
#   -t web      — Furo (light/dark)                → website
#
# PDF: primary is latexpdf (make -f sphinx.mk pdf); rst2pdf is fallback-pdf only.

import re
import sys
from pathlib import Path

# Ensure sphinx-config/ is importable when using: sphinx-build -c sphinx-config
sys.path.insert(0, str(Path(__file__).resolve().parent))

# -- Project information -----------------------------------------------------

project = "Zsh"
author = "Zsh Development Group"
copyright = "1990–2026, Zsh Development Group"

# Prefer the tree's Config/version.mk when present.
_version = "unknown"
_version_mk = Path(__file__).resolve().parents[2] / "Config" / "version.mk"
if _version_mk.is_file():
    _m = re.search(r"^VERSION=(.+)$", _version_mk.read_text(), re.M)
    if _m:
        _version = _m.group(1).strip()
release = _version
version = _version.split("-")[0]

# -- General configuration ---------------------------------------------------

# zsh_roles registers :var:`...` → HTML <var> / man \fI / texinfo @var
# (must be an extension module so Sphinx can pickle custom nodes).
# zsh_sectref is a deprecated Yodl sectref/subref bridge; remove when
# grep finds zero :zshsectref: under source/.
extensions = [
    "zsh_roles",
    "zsh_sectref",  # deprecated bridge; remove when no :zshsectref: remain
    "intro_zsh_examples",
]

# Number captioned code-blocks as "Example m.n:" (chapter.example).
# HTML and LaTeX use Sphinx numfig / section numbers natively.
numfig = True
numfig_secnum_depth = 1
numfig_format = {
    "code-block": "Example %s:",
}

# Optional: rst2pdf builder for fallback-pdf only (see sphinx.mk).
try:
    import rst2pdf.pdfbuilder  # noqa: F401

    extensions.append("rst2pdf.pdfbuilder")
except ImportError:
    pass


templates_path = ["_templates"]
exclude_patterns = [
    "Thumbs.db",
    ".DS_Store",
    # Fragments are included into Zsh/modules; not standalone documents.
    "Zsh/mod_*.rst",
]

# Partial conversions leave dangling :ref:`...` targets; keep builds usable.
nitpicky = False

root_doc = "index"

# zrst.yo emits |release| / |today|; Sphinx defines those by default.

# Brand orange (website + distro accent). Dark UIs use a lighter valuation.
_ZSH_ORANGE = "#f15a24"
_ZSH_ORANGE_LIGHT = "#ff7a4d"

# -- Options for HTML output -------------------------------------------------

html_static_path = ["_static"]
html_title = f"Zsh {release} documentation"
html_copy_source = False
html_show_sourcelink = False
html_permalinks = True

# ``tags`` is injected by Sphinx when conf.py is executed.
_web = tags.has("web")  # noqa: F821 — Sphinx conf namespace

if _web:
    # Website skin (graphical browsers; Furo has its own light/dark toggle).
    html_theme = "furo"
    html_theme_options = {
        "light_css_variables": {
            "color-brand-primary": _ZSH_ORANGE,
            "color-brand-content": _ZSH_ORANGE,
        },
        "dark_css_variables": {
            "color-brand-primary": _ZSH_ORANGE_LIGHT,
            "color-brand-content": _ZSH_ORANGE_LIGHT,
        },
    }
    html_css_files = ["zsh-var.css", "intro_zsh.css"]
else:
    # Distribution HTML: basic theme, no sidebar, no search chrome, no JS.
    # Light/dark via prefers-color-scheme in zsh-plain.css (lynx ignores CSS).
    html_theme = "basic"
    html_theme_options = {
        "nosidebar": True,
    }
    html_sidebars = {}
    html_css_files = ["zsh-plain.css", "zsh-var.css", "intro_zsh.css"]
    html_js_files = []


def _strip_distro_js(app, pagename, templatename, context, doctree):
    """Remove Sphinx/theme script tags from distribution HTML pages."""
    if app.tags.has("web"):
        return
    context["script_files"] = []


def setup(app):
    app.connect("html-page-context", _strip_distro_js)


# -- Options for man page output ---------------------------------------------
#
# Document name is relative to Doc/source/ (no .rst). The man page file
# name is the second element (e.g. zshbuiltins.1).
#
# Build with the ``man`` tag so ``.. only:: man`` blocks from zrst are kept:
#   make -f sphinx.mk man

_man_authors = [author]

man_pages = [
    # Chapter / shell path → traditional man page name (Makefile.in MAN order).
    ("Zsh/zsh", "zsh", "the Z shell", _man_authors, 1),
    ("Zsh/zshall", "zshall", "the Z shell meta-man page", _man_authors, 1),
    ("Zsh/roadmap", "zshroadmap", "informal introduction to the zsh manual", _man_authors, 1),
    ("Zsh/misc", "zshmisc", "everything and then some", _man_authors, 1),
    ("Zsh/expn", "zshexpn", "zsh expansion and substitution", _man_authors, 1),
    ("Zsh/params", "zshparam", "zsh parameters", _man_authors, 1),
    ("Zsh/options", "zshoptions", "zsh options", _man_authors, 1),
    ("Zsh/builtins", "zshbuiltins", "zsh built-in commands", _man_authors, 1),
    ("Zsh/zle", "zshzle", "zsh command line editor", _man_authors, 1),
    ("Zsh/compwid", "zshcompwid", "zsh completion widgets", _man_authors, 1),
    ("Zsh/compsys", "zshcompsys", "zsh completion system", _man_authors, 1),
    ("Zsh/compctl", "zshcompctl", "zsh programmable completion", _man_authors, 1),
    ("Zsh/modules", "zshmodules", "zsh loadable modules", _man_authors, 1),
    ("Zsh/calsys", "zshcalsys", "zsh calendar system", _man_authors, 1),
    ("Zsh/tcpsys", "zshtcpsys", "zsh tcp system", _man_authors, 1),
    ("Zsh/zftpsys", "zshzftpsys", "zftp function front-end", _man_authors, 1),
    ("Zsh/contrib", "zshcontrib", "user contributions to zsh", _man_authors, 1),
]

man_show_urls = False

# -- Options for Texinfo / Info output ---------------------------------------
#
# Entry document is manual.rst (full Yodl zsh.info chapter order).
# Build without -t man so .. only:: man blocks are excluded:
#   make -f sphinx.mk texinfo|info

texinfo_documents = [
    (
        "manual",
        "zsh",
        "The Z Shell Manual",
        author,
        "zsh",
        "the Z shell",
        "Software Development",
    ),
]

# -- Options for LaTeX / PDF output ------------------------------------------
#
# Primary PDF: sphinx.mk ``pdf`` / ``intro_zsh.*.pdf`` → latexpdf.
# Fallback PDF: sphinx.mk ``fallback-pdf`` → vanilla rst2pdf (presentation gaps).
# Paper-size tags: -t intro_zsh_a4 | -t intro_zsh_us

_intro_zsh_title = "An Introduction to the Z Shell"
_intro_zsh_authors = r"Paul Falstad \and Bas de Bakker"

latex_documents = [
    (
        "intro_zsh/index",
        "intro_zsh.tex",
        _intro_zsh_title,
        _intro_zsh_authors,
        "manual",
    ),
]

latex_elements = {
    "papersize": "a4paper",
}
# ``tags`` is injected by Sphinx when conf.py is executed.
if tags.has("intro_zsh_us"):  # noqa: F821 — Sphinx conf namespace
    latex_elements["papersize"] = "letterpaper"
elif tags.has("intro_zsh_a4"):  # noqa: F821
    latex_elements["papersize"] = "a4paper"

# rst2pdf fallback (make -f sphinx.mk fallback-pdf)
pdf_documents = [
    (
        "intro_zsh/index",
        "intro_zsh",
        _intro_zsh_title,
        r"Paul Falstad\\Bas de Bakker",
    ),
]

# Styles live under sphinx-config/styles/ (see intro_zsh.yaml for :kbd: reverse).
pdf_style_path = [str(Path(__file__).resolve().parent / "styles")]

pdf_stylesheets = ["sphinx", "a4", "intro_zsh"]
if tags.has("intro_zsh_us"):  # noqa: F821
    pdf_stylesheets = ["sphinx", "letter", "intro_zsh"]
elif tags.has("intro_zsh_a4"):  # noqa: F821
    pdf_stylesheets = ["sphinx", "a4", "intro_zsh"]

pdf_break_level = 1
pdf_compressed = True

