mirror of
https://github.com/nix-community/nixvim.git
synced 2025-06-21 16:39:00 +02:00
This requires pulling quite a lot of code from nixpkgs in order to make the `either` type work correctly, the effects can be seen for example in the documentation of `ollama.promps` and `ollama.actions`
255 lines
8.8 KiB
Nix
255 lines
8.8 KiB
Nix
{
|
||
lib,
|
||
modules,
|
||
pkgs,
|
||
}: let
|
||
nixvimPath = toString ./..;
|
||
|
||
gitHubDeclaration = user: repo: subpath: {
|
||
url = "https://github.com/${user}/${repo}/blob/master/${subpath}";
|
||
name = "<${repo}/${subpath}>";
|
||
};
|
||
|
||
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;
|
||
};
|
||
|
||
getSubOptions' = type: loc: let
|
||
types =
|
||
# Composite types
|
||
{
|
||
either =
|
||
(getSubOptions' type.nestedTypes.left loc)
|
||
// (getSubOptions' type.nestedTypes.right loc);
|
||
nullOr = getSubOptions' type.nestedTypes.elemType loc;
|
||
lazyAttrsOf = getSubOptions' type.nestedTypes.elemType (loc ++ ["<name>"]);
|
||
attrsOf = getSubOptions' type.nestedTypes.elemType (loc ++ ["<name>"]);
|
||
listOf = getSubOptions' type.nestedTypes.elemType (loc ++ ["*"]);
|
||
functionTo = getSubOptions' type.nestedTypes.elemType (loc ++ ["<function body>"]);
|
||
|
||
# Taken from lib/types.nix
|
||
submodule = let
|
||
base = lib.evalModules {
|
||
modules =
|
||
[
|
||
{
|
||
_module.args.name = lib.mkOptionDefault "‹name›";
|
||
}
|
||
]
|
||
++ type.getSubModules;
|
||
};
|
||
inherit (base._module) freeformType;
|
||
in
|
||
(base.extendModules
|
||
{prefix = loc;})
|
||
.options
|
||
// lib.optionalAttrs (freeformType != null) {
|
||
_freeformOptions = getSubOptions' freeformType loc;
|
||
};
|
||
}
|
||
# Leaf types
|
||
// lib.genAttrs [
|
||
"raw"
|
||
"bool"
|
||
"optionType"
|
||
"unspecified"
|
||
"str"
|
||
"attrs"
|
||
"rawLua"
|
||
"int"
|
||
"package"
|
||
"numberBetween"
|
||
"enum"
|
||
"anything"
|
||
"separatedString"
|
||
"path"
|
||
"maintainer"
|
||
"unsignedInt"
|
||
"float"
|
||
"positiveInt"
|
||
"intBetween"
|
||
"nullType"
|
||
"nonEmptyStr"
|
||
] (_: {});
|
||
in
|
||
# For recursive types avoid calculating sub options, else this
|
||
# will end up in an unbounded recursion
|
||
if loc == ["plugins" "packer" "plugins" "*" "requires"]
|
||
then {}
|
||
else if builtins.hasAttr type.name types
|
||
then types.${type.name}
|
||
else throw "unhandled type in documentation: ${type.name}";
|
||
|
||
mkOptionsJSON = options: let
|
||
# Mainly present to patch the type.getSubOptions of `either`, but we need to patch all
|
||
# the options in order to correctly handle other composite options
|
||
# The code that follows is taken almost exactly from nixpkgs,
|
||
# by changing type.getSubOptions to getSubOptions'
|
||
# lib/options.nix
|
||
optionAttrSetToDocList' = _: options:
|
||
lib.concatMap (opt: let
|
||
name = lib.showOption opt.loc;
|
||
docOption =
|
||
{
|
||
inherit (opt) loc;
|
||
inherit name;
|
||
description = opt.description or null;
|
||
declarations = builtins.filter (x: x != lib.unknownModule) opt.declarations;
|
||
internal = opt.internal or false;
|
||
visible =
|
||
if (opt ? visible && opt.visible == "shallow")
|
||
then true
|
||
else opt.visible or true;
|
||
readOnly = opt.readOnly or false;
|
||
type = opt.type.description or "unspecified";
|
||
}
|
||
// lib.optionalAttrs (opt ? example) {
|
||
example = builtins.addErrorContext "while evaluating the example of option `${name}`" (
|
||
lib.options.renderOptionValue opt.example
|
||
);
|
||
}
|
||
// lib.optionalAttrs (opt ? defaultText || opt ? default) {
|
||
default =
|
||
builtins.addErrorContext "while evaluating the ${
|
||
if opt ? defaultText
|
||
then "defaultText"
|
||
else "default value"
|
||
} of option `${name}`" (
|
||
lib.options.renderOptionValue (opt.defaultText or opt.default)
|
||
);
|
||
}
|
||
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != null) {inherit (opt) relatedPackages;};
|
||
|
||
subOptions = let
|
||
ss = getSubOptions' opt.type opt.loc;
|
||
in
|
||
if ss != {}
|
||
then optionAttrSetToDocList' opt.loc ss
|
||
else [];
|
||
subOptionsVisible = docOption.visible && opt.visible or null != "shallow";
|
||
in
|
||
# To find infinite recursion in NixOS option docs:
|
||
# builtins.trace opt.loc
|
||
[docOption] ++ lib.optionals subOptionsVisible subOptions) (lib.collect lib.isOption options);
|
||
|
||
# Generate documentation template from the list of option declaration like
|
||
# the set generated with filterOptionSets.
|
||
optionAttrSetToDocList = optionAttrSetToDocList' [];
|
||
|
||
# nixos/lib/make-options-doc/default.nix
|
||
|
||
rawOpts = optionAttrSetToDocList options;
|
||
transformedOpts = map transformOptions rawOpts;
|
||
filteredOpts = lib.filter (opt: opt.visible && !opt.internal) transformedOpts;
|
||
|
||
# Generate DocBook documentation for a list of packages. This is
|
||
# what `relatedPackages` option of `mkOption` from
|
||
# ../../../lib/options.nix influences.
|
||
#
|
||
# Each element of `relatedPackages` can be either
|
||
# - a string: that will be interpreted as an attribute name from `pkgs` and turned into a link
|
||
# to search.nixos.org,
|
||
# - a list: that will be interpreted as an attribute path from `pkgs` and turned into a link
|
||
# to search.nixos.org,
|
||
# - an attrset: that can specify `name`, `path`, `comment`
|
||
# (either of `name`, `path` is required, the rest are optional).
|
||
#
|
||
# NOTE: No checks against `pkgs` are made to ensure that the referenced package actually exists.
|
||
# Such checks are not compatible with option docs caching.
|
||
genRelatedPackages = packages: optName: let
|
||
unpack = p:
|
||
if lib.isString p
|
||
then {name = p;}
|
||
else if lib.isList p
|
||
then {path = p;}
|
||
else p;
|
||
describe = args: let
|
||
title = args.title or null;
|
||
name = args.name or (lib.concatStringsSep "." args.path);
|
||
in ''
|
||
- [${lib.optionalString (title != null) "${title} aka "}`pkgs.${name}`](
|
||
https://search.nixos.org/packages?show=${name}&sort=relevance&query=${name}
|
||
)${
|
||
lib.optionalString (args ? comment) "\n\n ${args.comment}"
|
||
}
|
||
'';
|
||
in
|
||
lib.concatMapStrings (p: describe (unpack p)) packages;
|
||
|
||
nixvimOptionsList =
|
||
lib.flip map filteredOpts
|
||
(
|
||
opt:
|
||
opt
|
||
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) {
|
||
relatedPackages = genRelatedPackages opt.relatedPackages opt.name;
|
||
}
|
||
);
|
||
|
||
nixvimOptionsNix = builtins.listToAttrs (map (o: {
|
||
inherit (o) name;
|
||
value = removeAttrs o ["name" "visible" "internal"];
|
||
})
|
||
nixvimOptionsList);
|
||
in
|
||
pkgs.runCommand "options.json"
|
||
{
|
||
meta.description = "List of NixOS options in JSON format";
|
||
nativeBuildInputs = [
|
||
pkgs.brotli
|
||
pkgs.python3Minimal
|
||
];
|
||
options =
|
||
builtins.toFile "options.json"
|
||
(builtins.unsafeDiscardStringContext (builtins.toJSON nixvimOptionsNix));
|
||
baseJSON = builtins.toFile "base.json" "{}";
|
||
}
|
||
''
|
||
# Export list of options in different format.
|
||
dst=$out/share/doc/nixos
|
||
mkdir -p $dst
|
||
|
||
TOUCH_IF_DB=$dst/.used-docbook \
|
||
python ${pkgs.path}/nixos/lib/make-options-doc/mergeJSON.py \
|
||
$baseJSON $options \
|
||
> $dst/options.json
|
||
|
||
if grep /nixpkgs/nixos/modules $dst/options.json; then
|
||
echo "The manual appears to depend on the location of Nixpkgs, which is bad"
|
||
echo "since this prevents sharing via the NixOS channel. This is typically"
|
||
echo "caused by an option default that refers to a relative path (see above"
|
||
echo "for hints about the offending path)."
|
||
exit 1
|
||
fi
|
||
|
||
brotli -9 < $dst/options.json > $dst/options.json.br
|
||
|
||
mkdir -p $out/nix-support
|
||
echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
|
||
echo "file json-br $dst/options.json.br" >> $out/nix-support/hydra-build-products
|
||
'';
|
||
in
|
||
rec {
|
||
options-json = mkOptionsJSON (lib.evalModules {inherit modules;}).options;
|
||
man-docs = pkgs.callPackage ./man {inherit options-json;};
|
||
}
|
||
# Do not check if documentation builds fine on darwin as it fails:
|
||
# > sandbox-exec: pattern serialization length 69298 exceeds maximum (65535)
|
||
// lib.optionalAttrs (!pkgs.stdenv.isDarwin) {
|
||
docs = pkgs.callPackage ./mdbook {
|
||
inherit mkOptionsJSON modules getSubOptions';
|
||
};
|
||
}
|