mirror of
https://github.com/nix-community/nixvim.git
synced 2025-06-20 16:15:43 +02:00
Long descriptions for plugins will shove the plugin's source link and maintainer information far down the page. Since those are fairly short and the description is a variable size. Moving below to maintain consistent placement.
272 lines
7.9 KiB
Nix
272 lines
7.9 KiB
Nix
{
|
|
pkgs,
|
|
lib,
|
|
evaledModules,
|
|
nixosOptionsDoc,
|
|
transformOptions,
|
|
hmOptions,
|
|
search,
|
|
}:
|
|
with lib;
|
|
let
|
|
inherit (evaledModules.config.meta) nixvimInfo;
|
|
|
|
mkMDDoc =
|
|
options:
|
|
(nixosOptionsDoc {
|
|
inherit options transformOptions;
|
|
warningsAreErrors = false;
|
|
}).optionsCommonMark;
|
|
|
|
removeUnwanted =
|
|
attrs:
|
|
builtins.removeAttrs attrs [
|
|
"_module"
|
|
"_freeformOptions"
|
|
"warnings"
|
|
"assertions"
|
|
"content"
|
|
];
|
|
|
|
removeWhitespace = builtins.replaceStrings [ " " ] [ "" ];
|
|
|
|
getSubOptions =
|
|
opts: path: optionalAttrs (isVisible opts) (removeUnwanted (opts.type.getSubOptions path));
|
|
|
|
isVisible =
|
|
opts:
|
|
if isOption opts then
|
|
opts.visible or true
|
|
else if opts.isOption then
|
|
opts.index.options.visible or true
|
|
else
|
|
let
|
|
filterFunc = filterAttrs (_: v: if isAttrs v then isVisible v else true);
|
|
|
|
hasEmptyIndex = (filterFunc opts.index.options) == { };
|
|
hasEmptyComponents = (filterFunc opts.components) == { };
|
|
in
|
|
!hasEmptyIndex || !hasEmptyComponents;
|
|
|
|
wrapModule = path: opts: isOpt: rec {
|
|
index = {
|
|
options =
|
|
if isOpt then
|
|
opts
|
|
else
|
|
filterAttrs (_: component: component.isOption && (isVisible component)) opts;
|
|
path = removeWhitespace (concatStringsSep "/" path);
|
|
moduleDoc =
|
|
let
|
|
info = optionalAttrs (hasAttrByPath path nixvimInfo) (getAttrFromPath path nixvimInfo);
|
|
maintainers = lib.unique (evaledModules.config.meta.maintainers.${info.file} or [ ]);
|
|
maintainersNames = builtins.map maintToMD maintainers;
|
|
maintToMD = m: if m ? github then "[${m.name}](https://github.com/${m.github})" else m.name;
|
|
in
|
|
# Make sure this path has a valid info attrset
|
|
if info ? file && info ? description && info ? url then
|
|
"# ${lib.last path}\n\n"
|
|
+ (lib.optionalString (info.url != null) "**URL:** [${info.url}](${info.url})\n\n")
|
|
+ (lib.optionalString (
|
|
maintainers != [ ]
|
|
) "**Maintainers:** ${lib.concatStringsSep ", " maintainersNames}\n\n")
|
|
+ lib.optionalString (info.description != null) ''
|
|
|
|
---
|
|
|
|
${info.description}
|
|
|
|
''
|
|
else
|
|
null;
|
|
};
|
|
|
|
components =
|
|
if isOpt then
|
|
{ }
|
|
else
|
|
filterAttrs (_: component: !component.isOption && (isVisible component)) opts;
|
|
|
|
hasComponents = components != { };
|
|
|
|
isOption = isOpt;
|
|
};
|
|
|
|
processModulesRec =
|
|
modules:
|
|
let
|
|
recurse =
|
|
path: mods:
|
|
let
|
|
g =
|
|
name: opts:
|
|
if !isOption opts then
|
|
wrapModule (path ++ [ name ]) (recurse (path ++ [ name ]) opts) false
|
|
else
|
|
let
|
|
subOpts = getSubOptions opts (path ++ [ name ]);
|
|
in
|
|
if subOpts != { } then
|
|
wrapModule (path ++ [ name ]) (
|
|
(recurse (path ++ [ name ]) subOpts)
|
|
// {
|
|
# This is necessary to include the submodule option's definition in the docs (description, type, etc.)
|
|
# For instance, this helps submodules like "autoCmd" to include their base definitions and examples in the docs
|
|
# Though there might be a better, less "hacky" solution than this.
|
|
${name} = recursiveUpdate opts {
|
|
isOption = true;
|
|
type.getSubOptions = _: _: { }; # Used to exclude suboptions from the submodule definition itself
|
|
};
|
|
}
|
|
) false
|
|
else
|
|
wrapModule (path ++ [ name ]) opts true;
|
|
in
|
|
mapAttrs g mods;
|
|
in
|
|
foldlAttrs (
|
|
acc: name: opts:
|
|
let
|
|
group = if !opts.hasComponents then "Neovim Options" else "none";
|
|
|
|
last =
|
|
acc.${group} or {
|
|
index = {
|
|
options = { };
|
|
path = removeWhitespace "${group}";
|
|
moduleDoc = null;
|
|
};
|
|
components = { };
|
|
isGroup = true;
|
|
hasComponents = false;
|
|
};
|
|
|
|
isOpt = !opts.hasComponents && (isOption opts.index.options);
|
|
in
|
|
acc
|
|
// {
|
|
${group} = recursiveUpdate last {
|
|
index.options = optionalAttrs isOpt { ${name} = opts.index.options; };
|
|
|
|
components = optionalAttrs (!isOpt) {
|
|
${name} = recursiveUpdate opts {
|
|
index.path = removeWhitespace (
|
|
concatStringsSep "/" ((optional (group != "none") group) ++ [ opts.index.path ])
|
|
);
|
|
hasComponents = true;
|
|
};
|
|
};
|
|
|
|
hasComponents = last.components != { };
|
|
};
|
|
}
|
|
) { } (recurse [ ] modules);
|
|
|
|
mapModulesToString =
|
|
f: modules:
|
|
let
|
|
recurse =
|
|
mods:
|
|
let
|
|
g =
|
|
name: opts:
|
|
if (opts ? "isGroup") then
|
|
if name != "none" then (f name opts) + ("\n" + recurse opts.components) else recurse opts.components
|
|
else if opts.hasComponents then
|
|
(f name opts) + ("\n" + recurse opts.components)
|
|
else
|
|
f name opts;
|
|
in
|
|
concatStringsSep "\n" (mapAttrsToList g mods);
|
|
in
|
|
recurse modules;
|
|
|
|
docs = rec {
|
|
modules = processModulesRec (removeUnwanted evaledModules.options);
|
|
commands = mapModulesToString (
|
|
name: opts:
|
|
let
|
|
isBranch = if (hasSuffix "index" opts.index.path) then true else opts.hasComponents;
|
|
path = if isBranch then "${opts.index.path}/index.md" else "${opts.index.path}.md";
|
|
in
|
|
(optionalString isBranch "mkdir -p ${opts.index.path}\n")
|
|
+ (
|
|
if opts.index.moduleDoc == null then
|
|
"cp ${mkMDDoc opts.index.options} ${path}"
|
|
else
|
|
# Including moduleDoc's text directly will result in bash interpreting special chars,
|
|
# write it to the nix store and `cat` the file instead.
|
|
''
|
|
{
|
|
cat ${pkgs.writeText "module-doc" opts.index.moduleDoc}
|
|
cat ${mkMDDoc opts.index.options}
|
|
} > ${path}
|
|
''
|
|
)
|
|
) modules;
|
|
};
|
|
|
|
mdbook = {
|
|
nixvimOptions = mapModulesToString (
|
|
name: opts:
|
|
let
|
|
isBranch = if name == "index" then true else opts.hasComponents && opts.index.options != { };
|
|
|
|
path =
|
|
if isBranch then
|
|
"${opts.index.path}/index.md"
|
|
else if !opts.hasComponents then
|
|
"${opts.index.path}.md"
|
|
else
|
|
"";
|
|
|
|
indentLevel = with builtins; length (filter isString (split "/" opts.index.path)) - 1;
|
|
|
|
padding = concatStrings (builtins.genList (_: "\t") indentLevel);
|
|
in
|
|
"${padding}- [${name}](${path})"
|
|
) docs.modules;
|
|
};
|
|
|
|
prepareMD = ''
|
|
# Copy inputs into the build directory
|
|
cp -r --no-preserve=all $inputs/* ./
|
|
cp ${../../CONTRIBUTING.md} ./CONTRIBUTING.md
|
|
cp -r ${../user-guide} ./user-guide
|
|
cp -r ${../modules} ./modules
|
|
|
|
# Copy the generated MD docs into the build directory
|
|
# Using pkgs.writeShellScript helps to avoid the "bash: argument list too long" error
|
|
bash -e ${pkgs.writeShellScript "copy_docs" docs.commands}
|
|
|
|
# Prepare SUMMARY.md for mdBook
|
|
# Using pkgs.writeText helps to avoid the same error as above
|
|
substituteInPlace ./SUMMARY.md \
|
|
--replace-fail "@NIXVIM_OPTIONS@" "$(cat ${pkgs.writeText "nixvim-options-summary.md" mdbook.nixvimOptions})"
|
|
|
|
substituteInPlace ./modules/hm.md \
|
|
--replace-fail "@HM_OPTIONS@" "$(cat ${mkMDDoc hmOptions})"
|
|
'';
|
|
in
|
|
pkgs.stdenv.mkDerivation {
|
|
name = "nixvim-docs";
|
|
|
|
phases = [ "buildPhase" ];
|
|
|
|
buildInputs = [ pkgs.mdbook ];
|
|
inputs = sourceFilesBySuffices ./. [
|
|
".md"
|
|
".toml"
|
|
".js"
|
|
];
|
|
|
|
buildPhase = ''
|
|
dest=$out/share/doc/nixvim
|
|
mkdir -p $dest
|
|
${prepareMD}
|
|
mdbook build
|
|
cp -r ./book/* $dest
|
|
mkdir -p $dest/search
|
|
cp -r ${search}/* $dest/search
|
|
'';
|
|
}
|