From 229fe85d6b4bb54fa77061f0aee6519dd37a4741 Mon Sep 17 00:00:00 2001 From: traxys Date: Mon, 6 Nov 2023 11:52:30 +0100 Subject: [PATCH] docs: Allow to generate man pages for nixvim (#686) --- flake.nix | 6 +- man-docs/default.nix | 50 ++++++++ man-docs/nixvim-render-docs/default.nix | 31 +++++ .../src/nixvim_render_docs/__init__.py | 113 ++++++++++++++++++ .../nixvim-render-docs/src/pyproject.toml | 14 +++ 5 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 man-docs/default.nix create mode 100644 man-docs/nixvim-render-docs/default.nix create mode 100644 man-docs/nixvim-render-docs/src/nixvim_render_docs/__init__.py create mode 100644 man-docs/nixvim-render-docs/src/pyproject.toml diff --git a/flake.nix b/flake.nix index b8435a60..3ba668e3 100644 --- a/flake.nix +++ b/flake.nix @@ -102,7 +102,11 @@ modules = modules pkgs; }; } - // (import ./helpers pkgs); + // (import ./helpers pkgs) + // (import ./man-docs { + pkgs = pkgs-unfree; + modules = modules pkgs; + }); legacyPackages = rec { makeNixvimWithModule = import ./wrappers/standalone.nix pkgs modules; makeNixvim = configuration: diff --git a/man-docs/default.nix b/man-docs/default.nix new file mode 100644 index 00000000..3406c737 --- /dev/null +++ b/man-docs/default.nix @@ -0,0 +1,50 @@ +{ + pkgs, + modules, +}: let + nixvimPath = toString ./..; + + gitHubDeclaration = user: repo: subpath: { + url = "https://github.com/${user}/${repo}/blob/master/${subpath}"; + name = "<${repo}/${subpath}>"; + }; +in rec { + nixvim-render-docs = pkgs.callPackage ./nixvim-render-docs {}; + + man-docs = let + eval = pkgs.lib.evalModules { + inherit modules; + }; + + options = pkgs.nixosOptionsDoc { + inherit (eval) options; + warningsAreErrors = false; + transformOptions = opt: + opt + // { + declarations = + map ( + decl: + if pkgs.lib.hasPrefix nixvimPath (toString decl) + then + gitHubDeclaration "nix-community" "nixvim" + (pkgs.lib.removePrefix "/" (pkgs.lib.removePrefix nixvimPath (toString decl))) + else if decl == "lib/modules.nix" + then gitHubDeclaration "NixOS" "nixpkgs" decl + else decl + ) + opt.declarations; + }; + }; + in + pkgs.runCommand "nixvim-configuration-reference-manpage" { + nativeBuildInputs = with pkgs; [installShellFiles nixvim-render-docs]; + } '' + # Generate man-pages + mkdir -p $out/share/man/man5 + nixvim-render-docs -j $NIX_BUILD_CORES options manpage \ + --revision unstable \ + ${options.optionsJSON}/share/doc/nixos/options.json \ + $out/share/man/man5/nixvim.5 + ''; +} diff --git a/man-docs/nixvim-render-docs/default.nix b/man-docs/nixvim-render-docs/default.nix new file mode 100644 index 00000000..2dc26a59 --- /dev/null +++ b/man-docs/nixvim-render-docs/default.nix @@ -0,0 +1,31 @@ +{ + python3, + lib, + nixos-render-docs, +}: +python3.pkgs.buildPythonApplication { + pname = "nixvim-render-docs"; + version = "0.0"; + format = "pyproject"; + + src = lib.cleanSourceWith { + filter = name: type: + lib.cleanSourceFilter name type + && ! (type + == "directory" + && builtins.elem (baseNameOf name) [ + ".pytest_cache" + ".mypy_cache" + "__pycache__" + ]); + src = ./src; + }; + + nativeBuildInputs = with python3.pkgs; [ + setuptools + ]; + + propagatedBuildInputs = [ + nixos-render-docs + ]; +} diff --git a/man-docs/nixvim-render-docs/src/nixvim_render_docs/__init__.py b/man-docs/nixvim-render-docs/src/nixvim_render_docs/__init__.py new file mode 100644 index 00000000..000d13ed --- /dev/null +++ b/man-docs/nixvim-render-docs/src/nixvim_render_docs/__init__.py @@ -0,0 +1,113 @@ +# Very laregly inspired by nixos_render_docs, in nixpkgs at: +# `pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs` + +import argparse +import sys +import traceback +import json + +import nixos_render_docs +from nixos_render_docs import parallel +from nixos_render_docs import options as nx_options +from nixos_render_docs.manpage import man_escape +from nixos_render_docs.md import md_escape + + +class NixvimManpageConverter(nx_options.ManpageConverter): + def __init__(self, revision, *, _options_by_id=None): + super().__init__(revision, _options_by_id=_options_by_id) + + def finalize(self): + result = [] + + result += [ + r'''.TH "NIXVIM" "5" "01/01/1980" "Nixvim" "Nixvim Reference Pages"''', + r""".\" disable hyphenation""", + r""".nh""", + r""".\" disable justification (adjust text to left margin only)""", + r""".ad l""", + r""".\" enable line breaks after slashes""", + r""".cflags 4 /""", + r'''.SH "NAME"''', + self._render("nixvim options specification"), + r'''.SH "DESCRIPTION"''', + r""".PP""", + self._render( + "This page lists all the options that can be used in nixvim. " + "Nixvim can either be used as a Home-Manager module, an NixOS module or a standalone package. " + "Please refer to the installation instructions for more details." + ), + r'''.SH "OPTIONS"''', + r""".PP""", + self._render("You can use the following options in a nixvim module."), + ] + + for name, opt in self._sorted_options(): + result += [ + ".PP", + f"\\fB{man_escape(name)}\\fR", + ".RS 4", + ] + result += opt.lines + if links := opt.links: + result.append(self.__option_block_separator__) + md_links = "" + for i in range(0, len(links)): + md_links += "\n" if i > 0 else "" + if links[i].startswith("#opt-"): + md_links += f"{i+1}. see the {{option}}`{self._options_by_id[links[i]]}` option" + else: + md_links += f"{i+1}. " + md_escape(links[i]) + result.append(self._render(md_links)) + + result.append(".RE") + + result += [ + r'''.SH "AUTHORS"''', + r""".PP""", + r"""nixvim maintainers""", + ] + + return "\n".join(result) + + +def run_manpage_options(args): + md = NixvimManpageConverter(revision=args.revision) + + with open(args.infile, "r") as f: + md.add_options(json.load(f)) + with open(args.outfile, "w") as f: + f.write(md.finalize()) + + +def run_options(args): + if args.format == "manpage": + run_manpage_options(args) + else: + raise RuntimeError("format not hooked up", args) + + +def main(): + parser = argparse.ArgumentParser(description="render nixos manual bits") + parser.add_argument("-j", "--jobs", type=int, default=None) + + commands = parser.add_subparsers(dest="command", required=True) + options = commands.add_parser("options") + + formats = options.add_subparsers(dest="format", required=True) + manpage = formats.add_parser("manpage") + manpage.add_argument("--revision", required=True) + manpage.add_argument("infile") + manpage.add_argument("outfile") + + args = parser.parse_args() + try: + parallel.pool_processes = args.jobs + if args.command == "options": + run_options(args) + else: + raise RuntimeError("command not hooked up", args) + except Exception as e: + traceback.print_exc() + nixos_render_docs.pretty_print_exc(e) + sys.exit(1) diff --git a/man-docs/nixvim-render-docs/src/pyproject.toml b/man-docs/nixvim-render-docs/src/pyproject.toml new file mode 100644 index 00000000..93545d63 --- /dev/null +++ b/man-docs/nixvim-render-docs/src/pyproject.toml @@ -0,0 +1,14 @@ +[project] +name = "nixvim-render-docs" +version = "0.0" +description = "Renderer for Nixvim option docs" +classifiers = [ + "Programming Language :: Python :: 3", + "Operating System :: OS Independent", +] + +[project.scripts] +nixvim-render-docs = "nixvim_render_docs:main" + +[build-system] +requires = ["setuptools"]