mirror of
https://github.com/nix-community/nixvim.git
synced 2025-11-09 03:56:05 +01:00
docs/modules: init
Modules to represent pages in the docs
This commit is contained in:
parent
9faa339d9e
commit
4414d8aa14
6 changed files with 309 additions and 187 deletions
|
|
@ -6,64 +6,40 @@
|
||||||
writers,
|
writers,
|
||||||
nixdoc,
|
nixdoc,
|
||||||
nixvim,
|
nixvim,
|
||||||
pageSpecs ? import ./pages.nix,
|
pageSpecs ? ./pages.nix,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
# Some pages are just menu entries, others have an actual markdown page that
|
pageConfiguration = lib.evalModules {
|
||||||
# needs rendering.
|
modules = [
|
||||||
shouldRenderPage = page: page ? file || page ? markdown;
|
pageSpecs
|
||||||
|
|
||||||
# Normalise a page node, recursively normalise its children
|
|
||||||
elaboratePage =
|
|
||||||
loc:
|
|
||||||
{
|
{
|
||||||
title ? "",
|
freeformType = lib.types.attrsOf (
|
||||||
markdown ? null,
|
lib.types.submoduleWith {
|
||||||
file ? null,
|
modules = [ ../modules/page.nix ];
|
||||||
pages ? { },
|
|
||||||
}@page:
|
|
||||||
{
|
|
||||||
name = lib.attrsets.showAttrPath loc;
|
|
||||||
loc = lib.throwIfNot (
|
|
||||||
builtins.head loc == "lib"
|
|
||||||
) "All pages must be within `lib`, unexpected root `${builtins.head loc}`" (builtins.tail loc);
|
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (shouldRenderPage page) {
|
);
|
||||||
inherit
|
|
||||||
file
|
|
||||||
title
|
|
||||||
;
|
|
||||||
markdown =
|
|
||||||
if builtins.isString markdown then
|
|
||||||
builtins.toFile "${lib.strings.replaceStrings [ "/" "-" ] (lib.lists.last loc)}.md" markdown
|
|
||||||
else
|
|
||||||
markdown;
|
|
||||||
outFile = lib.strings.concatStringsSep "/" (loc ++ [ "index.md" ]);
|
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (page ? pages) {
|
];
|
||||||
pages = elaboratePages loc pages;
|
|
||||||
};
|
};
|
||||||
|
pages = pageConfiguration.config;
|
||||||
# Recursively normalise page nodes
|
|
||||||
elaboratePages = prefix: builtins.mapAttrs (name: elaboratePage (prefix ++ [ name ]));
|
|
||||||
|
|
||||||
# Collect all page nodes into a list of page entries
|
# Collect all page nodes into a list of page entries
|
||||||
collectPages =
|
collectPages =
|
||||||
pages:
|
pages:
|
||||||
builtins.concatMap (
|
builtins.concatMap (
|
||||||
page:
|
node:
|
||||||
[ (builtins.removeAttrs page [ "pages" ]) ]
|
let
|
||||||
++ lib.optionals (page ? pages) (collectPages page.pages)
|
children = builtins.removeAttrs node [ "_page" ];
|
||||||
|
in
|
||||||
|
lib.optional (node ? _page) node._page ++ lib.optionals (children != { }) (collectPages children)
|
||||||
) (builtins.attrValues pages);
|
) (builtins.attrValues pages);
|
||||||
|
|
||||||
# Normalised page specs
|
# Normalised page specs
|
||||||
elaboratedPageSpecs = elaboratePages [ ] pageSpecs;
|
pageList = collectPages pages;
|
||||||
pageList = collectPages elaboratedPageSpecs;
|
pagesToRender = builtins.filter (page: page.hasContent) pageList;
|
||||||
pagesToRender = builtins.filter (page: page ? outFile) pageList;
|
|
||||||
pagesWithFunctions = builtins.filter (page: page.file or null != null) pageList;
|
|
||||||
in
|
|
||||||
|
|
||||||
|
result =
|
||||||
runCommand "nixvim-lib-docs"
|
runCommand "nixvim-lib-docs"
|
||||||
{
|
{
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
|
|
@ -75,25 +51,22 @@ runCommand "nixvim-lib-docs"
|
||||||
inherit lib;
|
inherit lib;
|
||||||
rootPath = nixvim;
|
rootPath = nixvim;
|
||||||
functionSet = lib.extend nixvim.lib.overlay;
|
functionSet = lib.extend nixvim.lib.overlay;
|
||||||
pathsToScan = builtins.catAttrs "loc" pagesWithFunctions;
|
pathsToScan = lib.pipe pageList [
|
||||||
|
(map (x: x.functions))
|
||||||
|
(builtins.filter (x: x.file != null))
|
||||||
|
(map (x: x.loc))
|
||||||
|
];
|
||||||
revision = nixvim.rev or "main";
|
revision = nixvim.rev or "main";
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
passthru.config = pageConfiguration;
|
||||||
|
|
||||||
passthru.menu = import ./menu.nix {
|
passthru.menu = import ./menu.nix {
|
||||||
inherit lib;
|
inherit lib pages;
|
||||||
pageSpecs = elaboratedPageSpecs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
passthru.pages = builtins.listToAttrs (
|
passthru.pages = map (page: "${result}/${page.target}") pagesToRender;
|
||||||
builtins.map (
|
|
||||||
{ name, outFile, ... }:
|
|
||||||
{
|
|
||||||
inherit name;
|
|
||||||
value = outFile;
|
|
||||||
}
|
|
||||||
) pagesToRender
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
''
|
''
|
||||||
function docgen {
|
function docgen {
|
||||||
|
|
@ -121,7 +94,7 @@ runCommand "nixvim-lib-docs"
|
||||||
--locs "$locations" \
|
--locs "$locations" \
|
||||||
--category "$name" \
|
--category "$name" \
|
||||||
--description "REMOVED BY TAIL" \
|
--description "REMOVED BY TAIL" \
|
||||||
--prefix "" \
|
--prefix "lib" \
|
||||||
--anchor-prefix "" \
|
--anchor-prefix "" \
|
||||||
| tail --lines +2 \
|
| tail --lines +2 \
|
||||||
> functions.md
|
> functions.md
|
||||||
|
|
@ -159,20 +132,21 @@ runCommand "nixvim-lib-docs"
|
||||||
|
|
||||||
${lib.concatMapStringsSep "\n" (
|
${lib.concatMapStringsSep "\n" (
|
||||||
{
|
{
|
||||||
name,
|
functions,
|
||||||
file,
|
source,
|
||||||
markdown,
|
target,
|
||||||
outFile,
|
|
||||||
title ? "",
|
title ? "",
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
lib.escapeShellArgs [
|
lib.escapeShellArgs [
|
||||||
"docgen"
|
"docgen"
|
||||||
"${lib.optionalString (markdown != null) markdown}" # md_file
|
"${lib.optionalString (source != null) source}" # md_file
|
||||||
"${lib.optionalString (file != null) file}" # in_file
|
"${lib.optionalString (functions.file != null) functions.file}" # in_file
|
||||||
name # name
|
(lib.showAttrPath functions.loc) # name
|
||||||
outFile # out_file
|
target # out_file
|
||||||
title # title
|
title # title
|
||||||
]
|
]
|
||||||
) pagesToRender}
|
) pagesToRender}
|
||||||
''
|
'';
|
||||||
|
in
|
||||||
|
result
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,31 @@
|
||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
pageSpecs,
|
pages,
|
||||||
indentSize ? " ",
|
indentSize ? " ",
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
pageToLines =
|
pageToLines =
|
||||||
indent: parentName:
|
indent: parent: node:
|
||||||
{
|
|
||||||
name,
|
|
||||||
outFile ? "",
|
|
||||||
pages ? { },
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
menuName = lib.strings.removePrefix (parentName + ".") name;
|
|
||||||
children = builtins.attrValues pages;
|
children = lib.pipe node [
|
||||||
|
(lib.flip builtins.removeAttrs [ "_page" ])
|
||||||
|
builtins.attrValues
|
||||||
|
];
|
||||||
# Only add node to the menu if it has content or multiple children
|
# Only add node to the menu if it has content or multiple children
|
||||||
useNodeInMenu = outFile != "" || builtins.length children > 1;
|
useNodeInMenu = node._page.target != "" || node._page.children > 1;
|
||||||
parentOfChildren = if useNodeInMenu then name else parentName;
|
nextParent = if useNodeInMenu then node else parent;
|
||||||
|
nextIndent = if useNodeInMenu then indent + indentSize else indent;
|
||||||
|
loc = lib.lists.removePrefix (parent._page.loc or [ ]) node._page.loc;
|
||||||
|
menuName = lib.attrsets.showAttrPath loc;
|
||||||
in
|
in
|
||||||
lib.optional useNodeInMenu "${indent}- [${menuName}](${outFile})"
|
lib.optional useNodeInMenu "${indent}- [${menuName}](${node._page.target})"
|
||||||
++ lib.optionals (children != [ ]) (
|
++ lib.optionals (children != [ ]) (
|
||||||
builtins.concatMap (pageToLines (indent + indentSize) parentOfChildren) children
|
builtins.concatMap (pageToLines nextIndent nextParent) children
|
||||||
);
|
);
|
||||||
in
|
in
|
||||||
lib.pipe pageSpecs [
|
lib.pipe pages [
|
||||||
builtins.attrValues
|
builtins.attrValues
|
||||||
(builtins.concatMap (pageToLines "" ""))
|
(builtins.concatMap (pageToLines "" null))
|
||||||
lib.concatLines
|
lib.concatLines
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,19 @@
|
||||||
# If there is an issue parsing the file, the resulting markdown will not contain any function docs.
|
# If there is an issue parsing the file, the resulting markdown will not contain any function docs.
|
||||||
|
|
||||||
{
|
{
|
||||||
lib.pages = {
|
lib.nixvim = {
|
||||||
nixvim = {
|
_page = {
|
||||||
title = "Nixvim's functions";
|
title = "Nixvim's functions";
|
||||||
markdown = ./index.md;
|
source = ./index.md;
|
||||||
|
};
|
||||||
|
|
||||||
pages = {
|
utils._page = {
|
||||||
utils = {
|
|
||||||
file = ../../lib/utils.nix;
|
|
||||||
title = "utility functions";
|
title = "utility functions";
|
||||||
|
functions.file = ../../lib/utils.nix;
|
||||||
};
|
};
|
||||||
lua = {
|
lua._page = {
|
||||||
file = ../../lib/to-lua.nix;
|
|
||||||
title = "lua functions";
|
title = "lua functions";
|
||||||
};
|
functions.file = ../../lib/to-lua.nix;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ let
|
||||||
../user-guide/faq.md
|
../user-guide/faq.md
|
||||||
../user-guide/config-examples.md
|
../user-guide/config-examples.md
|
||||||
]
|
]
|
||||||
++ lib.mapAttrsToList (name: file: "${lib-docs}/${file}") lib-docs.pages;
|
++ lib-docs.pages;
|
||||||
|
|
||||||
manHeader =
|
manHeader =
|
||||||
runCommand "nixvim-general-doc-manpage"
|
runCommand "nixvim-general-doc-manpage"
|
||||||
{
|
{
|
||||||
|
|
|
||||||
104
docs/modules/page-options.nix
Normal file
104
docs/modules/page-options.nix
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
prefix,
|
||||||
|
name,
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config._page;
|
||||||
|
opts = options._page;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options._page = {
|
||||||
|
loc = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
description = "Page's location in the menu.";
|
||||||
|
default = prefix ++ [ name ];
|
||||||
|
defaultText = lib.literalExpression "prefix ++ [ name ]";
|
||||||
|
readOnly = true;
|
||||||
|
};
|
||||||
|
target = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = lib.optionalString cfg.hasContent (lib.concatStringsSep "/" (cfg.loc ++ [ "index.md" ]));
|
||||||
|
defaultText = lib.literalMD ''
|
||||||
|
`""` if page has no content, otherwise a filepath derived from the page's `loc`.
|
||||||
|
'';
|
||||||
|
description = "Where to render content and link menu entries.";
|
||||||
|
};
|
||||||
|
title = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
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 = lib.lists.removePrefix [ "lib" ] 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`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
children = lib.mkOption {
|
||||||
|
type = lib.types.ints.unsigned;
|
||||||
|
description = ''
|
||||||
|
The number of child pages.
|
||||||
|
'';
|
||||||
|
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
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
45
docs/modules/page.nix
Normal file
45
docs/modules/page.nix
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# This module represents a node in a tree of pages.
|
||||||
|
# Its freeformType is is recursive: attrs of another node submodule.
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
prefix,
|
||||||
|
name,
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
freeformType = lib.types.attrsOf (
|
||||||
|
lib.types.submoduleWith {
|
||||||
|
specialArgs.prefix = prefix ++ [ name ];
|
||||||
|
modules = [ ./page.nix ];
|
||||||
|
}
|
||||||
|
// {
|
||||||
|
description = "page submodule";
|
||||||
|
descriptionClass = "noun";
|
||||||
|
# Alternative to `visible = "shallow"`, avoid inf-recursion when collecting options for docs
|
||||||
|
getSubOptions = _: { };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
# The _page option contains options for this page node
|
||||||
|
imports = [
|
||||||
|
./page-options.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
# Ensure the `prefix` arg exists
|
||||||
|
# Usually shadowed by `specialArgs.prefix`
|
||||||
|
_module.args.prefix = [ ];
|
||||||
|
|
||||||
|
_page = {
|
||||||
|
# Freeform definitions are children; count definitions without a
|
||||||
|
# corresponding option
|
||||||
|
children = lib.pipe config [
|
||||||
|
builtins.attrNames
|
||||||
|
(lib.count (name: !(options ? ${name})))
|
||||||
|
lib.mkForce
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue