diff --git a/docs/lib/default.nix b/docs/lib/default.nix
index c5fea47f..5b63fb0c 100644
--- a/docs/lib/default.nix
+++ b/docs/lib/default.nix
@@ -1,5 +1,3 @@
-# Generates the documentation for library functions using nixdoc.
-# See https://github.com/nix-community/nixdoc
{
lib,
runCommand,
@@ -32,23 +30,51 @@ let
# Normalised page specs
pageList = collectPages pages;
- pagesToRender = builtins.filter (page: page.hasContent) pageList;
+ pagesToRender = builtins.filter (page: page.target != "") pageList;
+
+ # Function(s) to render page sections
+ renderSection = {
+ __functor =
+ self: section:
+ let
+ names = builtins.attrNames section;
+ tag = builtins.head names;
+ in
+ assert
+ builtins.length names == 1
+ || throw "Section type should have 1 attribute, found ${toString (builtins.length names)}.";
+ self.${tag} section.${tag};
+
+ # Embed text as-is
+ title = title: "printf '# %s\\n' ${lib.escapeShellArg title}";
+ file = file: "cat ${file}";
+ text = text: "printf '%s\\n' ${lib.escapeShellArg text}";
+
+ # Generates the documentation for library functions using nixdoc.
+ # See https://github.com/nix-community/nixdoc
+ functions = { file, loc }: ''
+ ${lib.getExe nixdoc} \
+ --file ${file} \
+ --locs "$locations" \
+ --category ${lib.escapeShellArg (lib.showAttrPath loc)} \
+ --description "REMOVED BY TAIL" \
+ --prefix "lib" \
+ --anchor-prefix "" \
+ | tail --lines +2
+ '';
+ };
result =
runCommand "nixvim-lib-docs"
{
- nativeBuildInputs = [
- nixdoc
- ];
-
locations = writers.writeJSON "locations.json" (
import ./function-locations.nix {
inherit lib;
rootPath = nixvim;
functionSet = lib.extend nixvim.lib.overlay;
pathsToScan = lib.pipe pageList [
- (map (x: x.functions))
- (builtins.filter (x: x.file != null))
+ (lib.concatMap (page: page.content))
+ (lib.catAttrs "functions")
(map (x: x.loc))
];
revision = nixvim.rev or "main";
@@ -62,80 +88,29 @@ let
passthru.pages = map (page: "${result}/${page.target}") pagesToRender;
}
''
- function docgen {
- md_file="$1"
- in_file="$2"
- category="$3"
- out_file="$out/$4"
- title="$5"
-
- if [[ -z "$in_file" ]]; then
- if [[ -z "$md_file" ]]; then
- >&2 echo "No markdown or nix file for $category"
- exit 1
- fi
- elif [[ -f "$in_file/default.nix" ]]; then
- in_file+="/default.nix"
- elif [[ ! -f "$in_file" ]]; then
- >&2 echo "File not found: $in_file"
- exit 1
- fi
-
- if [[ -n "$in_file" ]]; then
- nixdoc \
- --file "$in_file" \
- --locs "$locations" \
- --category "$category" \
- --description "REMOVED BY TAIL" \
- --prefix "lib" \
- --anchor-prefix "" \
- | tail --lines +2 \
- > functions.md
- fi
-
- print_title=true
- if [[ -f "$md_file" ]] && [[ "$(head --lines 1 "$md_file")" == '# '* ]]; then
- if [[ -n "$title" ]]; then
- >&2 echo "NOTE: markdown file for $category starts with a
heading. Skipping title \"$title\"."
- >&2 echo " Found \"$(head --lines 1 "$md_file")\" in: $md_file"
- fi
- print_title=false
- fi
-
- mkdir -p $(dirname "$out_file")
- (
- if [[ "$print_title" = true ]]; then
- echo "# $title"
- echo
- fi
- if [[ -f "$md_file" ]]; then
- cat "$md_file"
- echo
- fi
- if [[ -f functions.md ]]; then
- cat functions.md
- fi
- ) > "$out_file"
- }
-
mkdir -p "$out"
${lib.concatMapStringsSep "\n" (
{
- functions,
- source,
+ title,
+ content,
target,
- title ? "",
...
}:
- lib.escapeShellArgs [
- "docgen"
- "${lib.optionalString (source != null) source}" # md_file
- "${lib.optionalString (functions.file != null) functions.file}" # in_file
- (lib.showAttrPath functions.loc) # category
- target # out_file
- title # title
- ]
+ let
+ sections = lib.optional (title != null) { inherit title; } ++ content;
+ in
+ ''
+ ${lib.toShellVars { inherit target; }}
+ mkdir -p "$(dirname "$out/$target")"
+ {
+ ${lib.pipe sections [
+ (map renderSection)
+ (lib.intersperse "echo")
+ lib.concatLines
+ ]}
+ } >"$out/$target"
+ ''
) pagesToRender}
'';
in
diff --git a/docs/lib/pages.nix b/docs/lib/pages.nix
index 8bc5f0a5..3d746e3f 100644
--- a/docs/lib/pages.nix
+++ b/docs/lib/pages.nix
@@ -10,22 +10,30 @@
lib.nixvim = {
_page = {
title = "lib.nixvim: Nixvim's functions";
- source = ./index.md;
+ content = [
+ ./index.md
+ ];
};
modules._page = {
title = "lib.nixvim.modules: module functions";
- functions.file = ../../lib/modules.nix;
+ content = [
+ { functions.file = ../../lib/modules.nix; }
+ ];
};
utils._page = {
title = "lib.nixvim.utils: utility functions";
- functions.file = ../../lib/utils.nix;
+ content = [
+ { functions.file = ../../lib/utils.nix; }
+ ];
};
lua._page = {
title = "lib.nixvim.lua: lua functions";
- functions.file = ../../lib/to-lua.nix;
+ content = [
+ { functions.file = ../../lib/to-lua.nix; }
+ ];
};
};
};
diff --git a/docs/modules/page-options.nix b/docs/modules/page-options.nix
index 6300cc05..a84db706 100644
--- a/docs/modules/page-options.nix
+++ b/docs/modules/page-options.nix
@@ -8,7 +8,52 @@
}:
let
cfg = config._page;
- opts = options._page;
+
+ contentType = lib.types.coercedTo lib.types.path (file: { inherit file; }) (
+ lib.types.attrTag {
+ file = lib.mkOption {
+ description = "A markdown file.";
+ type = lib.types.path;
+ };
+ text = lib.mkOption {
+ description = "Lines of markdown.";
+ type = lib.types.lines;
+ };
+ functions = lib.mkOption {
+ description = "Nix file to scan for RFC145 doc comments.";
+ type = lib.types.submodule {
+ options.file = lib.mkOption {
+ type = lib.types.path;
+ description = "Nix file.";
+ };
+ options.loc = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ default = if lib.lists.hasPrefix [ "lib" ] cfg.loc then builtins.tail cfg.loc else cfg.loc;
+ defaultText = lib.literalMD ''
+ `loc`'s attrpath, without any leading "lib"
+ '';
+ description = ''
+ Optional attrpath where functions are defined.
+ Provided to `nixdoc` as `--category`.
+
+ Will scan `lib` for attribute locations in the functions set at this attrpath.
+
+ Used in conjunction with `nix`.
+ '';
+ };
+ };
+ };
+ options = lib.mkOption {
+ description = ''
+ Set of options or list of option docs-templates.
+
+ If an attrset is provided, it will be coerced using `lib.options.optionAttrSetToDocList`.
+ '';
+ type = lib.types.raw;
+ apply = opts: if builtins.isAttrs opts then lib.options.optionAttrSetToDocList opts else opts;
+ };
+ }
+ );
in
{
options._page = {
@@ -21,7 +66,9 @@ in
};
target = lib.mkOption {
type = lib.types.str;
- default = lib.optionalString cfg.hasContent (lib.concatStringsSep "/" (cfg.loc ++ [ "index.md" ]));
+ default = lib.optionalString (cfg.content != [ ]) (
+ lib.concatStringsSep "/" (cfg.loc ++ [ "index.md" ])
+ );
defaultText = lib.literalMD ''
`""` if page has no content, otherwise a filepath derived from the page's `loc`.
'';
@@ -32,45 +79,10 @@ in
default = null;
description = "Page's heading title.";
};
- text = lib.mkOption {
- type = lib.types.nullOr lib.types.lines;
- default = null;
- description = "Optional markdown text to include after the title.";
- };
- source = lib.mkOption {
- type = lib.types.nullOr lib.types.path;
- default = null;
- description = "Optional markdown file to include after the title.";
- };
- functions.file = lib.mkOption {
- type = lib.types.nullOr lib.types.path;
- default = null;
- description = "Optional nix file to scan for RFC145 doc comments.";
- };
- functions.loc = lib.mkOption {
- type = lib.types.listOf lib.types.str;
- default = if lib.lists.hasPrefix [ "lib" ] cfg.loc then builtins.tail cfg.loc else cfg.loc;
- defaultText = lib.literalMD ''
- `loc`'s attrpath, without any leading "lib"
- '';
- description = ''
- Optional attrpath where functions are defined.
- Provided to `nixdoc` as `--category`.
-
- Will scan `lib` for attribute locations in the functions set at this attrpath.
-
- Used in conjunction with `nix`.
- '';
- };
- options = lib.mkOption {
- type = lib.types.nullOr lib.types.raw;
- default = null;
- apply = opts: if builtins.isAttrs opts then lib.options.optionAttrSetToDocList opts else opts;
- description = ''
- Optional set of options or list of option docs-templates.
-
- If an attrset is provided, it will be coerced using `lib.options.optionAttrSetToDocList`.
- '';
+ content = lib.mkOption {
+ type = lib.types.listOf contentType;
+ default = [ ];
+ description = "Optional content sections rendered after the title.";
};
toMenu = lib.mkOption {
type = lib.types.functionTo lib.types.str;
@@ -103,28 +115,9 @@ in
'';
readOnly = true;
};
- hasContent = lib.mkOption {
- type = lib.types.bool;
- description = ''
- Whether this page has any docs content.
-
- When `false`, this page represents an _empty_ menu entry.
- '';
- readOnly = true;
- };
};
config._page = {
- source = lib.mkIf (cfg.text != null) (
- lib.mkDerivedConfig opts.text (builtins.toFile "docs-${lib.attrsets.showAttrPath cfg.loc}-text.md")
- );
-
- hasContent = builtins.any (x: x != null) [
- cfg.source # markdown
- cfg.functions.file # doc-comments
- cfg.options # module options
- ];
-
toMenu = import ./to-menu.nix {
inherit lib;
optionNames = builtins.attrNames options;