-
-
Notifications
You must be signed in to change notification settings - Fork 347
docs/lib: generate function docs from RFC145 doc-comments #3049
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
dfaea59
docs/lib: init
MattSturgeon 1c6dd65
docs: include function docs
MattSturgeon 0c7e2aa
docs: `user-guide/helpers.md` → `lib/index.md`
MattSturgeon 83d3535
docs/man: include all sections from `lib-doc`
MattSturgeon 0f8dc10
docs/man: move FAQ and examples before functions
MattSturgeon 2ee5d71
doc/lib/index.md: update heading title
MattSturgeon 5cf8cb5
lib/utils: split into public and internal files
MattSturgeon bda4be0
docs/lib: enable `lib.nixvim.utils` docs
MattSturgeon 4a272ca
docs/lib: enable `lib.nixvim.lua` docs
MattSturgeon f4a7447
lib/util: move docs from `lib/index` to doc-comments
MattSturgeon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
# Generates the documentation for library functions using nixdoc. | ||
# See https://github.com/nix-community/nixdoc | ||
{ | ||
lib, | ||
runCommand, | ||
writers, | ||
nixdoc, | ||
nixvim, | ||
pageSpecs ? import ./pages.nix, | ||
}: | ||
|
||
let | ||
# Some pages are just menu entries, others have an actual markdown page that | ||
# needs rendering. | ||
shouldRenderPage = page: page ? file || page ? markdown; | ||
|
||
# Normalise a page node, recursively normalise its children | ||
elaboratePage = | ||
loc: | ||
{ | ||
title ? "", | ||
markdown ? null, | ||
file ? null, | ||
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; | ||
}; | ||
|
||
# Recursively normalise page nodes | ||
elaboratePages = prefix: builtins.mapAttrs (name: elaboratePage (prefix ++ [ name ])); | ||
|
||
# Collect all page nodes into a list of page entries | ||
collectPages = | ||
pages: | ||
builtins.concatMap ( | ||
page: | ||
[ (builtins.removeAttrs page [ "pages" ]) ] | ||
++ lib.optionals (page ? pages) (collectPages page.pages) | ||
) (builtins.attrValues pages); | ||
|
||
# Normalised page specs | ||
elaboratedPageSpecs = elaboratePages [ ] pageSpecs; | ||
pageList = collectPages elaboratedPageSpecs; | ||
pagesToRender = builtins.filter (page: page ? outFile) pageList; | ||
pagesWithFunctions = builtins.filter (page: page.file or null != null) pageList; | ||
in | ||
|
||
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 = builtins.catAttrs "loc" pagesWithFunctions; | ||
revision = nixvim.rev or "main"; | ||
} | ||
); | ||
|
||
passthru.menu = import ./menu.nix { | ||
inherit lib; | ||
pageSpecs = elaboratedPageSpecs; | ||
}; | ||
|
||
passthru.pages = builtins.listToAttrs ( | ||
builtins.map ( | ||
{ name, outFile, ... }: | ||
{ | ||
inherit name; | ||
value = outFile; | ||
} | ||
) pagesToRender | ||
); | ||
} | ||
'' | ||
function docgen { | ||
md_file="$1" | ||
in_file="$2" | ||
name="$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 $name" | ||
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 "$name" \ | ||
--description "REMOVED BY TAIL" \ | ||
--prefix "" \ | ||
--anchor-prefix "" \ | ||
| tail --lines +2 \ | ||
> functions.md | ||
fi | ||
|
||
default_heading="# $name" | ||
if [[ -n "$title" ]]; then | ||
default_heading+=": $title" | ||
fi | ||
|
||
print_heading=true | ||
if [[ -f "$md_file" ]] && [[ "$(head --lines 1 "$md_file")" == '# '* ]]; then | ||
>&2 echo "NOTE: markdown file for $name starts with a <h1> heading. Skipping default heading \"$default_heading\"." | ||
>&2 echo " Found \"$(head --lines 1 "$md_file")\" in: $md_file" | ||
print_heading=false | ||
fi | ||
|
||
mkdir -p $(dirname "$out_file") | ||
( | ||
if [[ "$print_heading" = true ]]; then | ||
echo "$default_heading" | ||
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" ( | ||
{ | ||
name, | ||
file, | ||
markdown, | ||
outFile, | ||
title ? "", | ||
... | ||
}: | ||
lib.escapeShellArgs [ | ||
"docgen" | ||
"${lib.optionalString (markdown != null) markdown}" # md_file | ||
"${lib.optionalString (file != null) file}" # in_file | ||
name # name | ||
outFile # out_file | ||
title # title | ||
] | ||
) pagesToRender} | ||
'' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Generates an attrset of "function name" → "markdown location", | ||
# for use with nixdoc's `--locs` option. | ||
# | ||
# { | ||
# "lib.nixvim.foo.bar" = "[lib/foo.nix:123](https://github.com/nix-community/nixvim/blob/«rev»/lib/foo.nix#L123) in `<nixvim>`"; | ||
# } | ||
{ | ||
rootPath, | ||
lib, | ||
functionSet, | ||
pathsToScan, | ||
revision, | ||
functionSetName ? "lib", | ||
url ? "https://github.com/nix-community/nixvim/blob", | ||
}: | ||
let | ||
rootPathString = toString rootPath; | ||
urlPrefix = "${url}/${revision}"; | ||
|
||
sanitizeId = builtins.replaceStrings [ "'" ] [ "-prime" ]; | ||
|
||
# Like `isAttrs`, but returns `false` if `v` throws | ||
tryIsAttrs = v: (builtins.tryEval (builtins.isAttrs v)).value; | ||
|
||
# Collect position entries from an attrset | ||
# `prefix` is used in the human-readable name, | ||
# and for determining whether to recurse into attrs | ||
collectPositionEntriesInSet = | ||
prefix: set: | ||
builtins.concatMap ( | ||
name: | ||
[ | ||
{ | ||
name = lib.showAttrPath ( | ||
builtins.concatMap lib.toList [ | ||
functionSetName | ||
prefix | ||
name | ||
] | ||
); | ||
location = builtins.unsafeGetAttrPos name set; | ||
} | ||
] | ||
++ lib.optionals (prefix == [ ] && tryIsAttrs set.${name}) ( | ||
collectPositionEntriesInSet (prefix ++ [ name ]) set.${name} | ||
) | ||
) (builtins.attrNames set); | ||
|
||
# Collect position entries from each `pathsToScan` in `set` | ||
collectPositionEntriesFromPaths = | ||
set: | ||
builtins.concatMap (loc: collectPositionEntriesInSet loc (lib.getAttrFromPath loc set)) pathsToScan; | ||
|
||
# Remove the tree root (usually the top-level store path) | ||
removeNixvimPrefix = lib.flip lib.pipe [ | ||
(lib.strings.removePrefix rootPathString) | ||
(lib.strings.removePrefix "/") | ||
]; | ||
|
||
# Create a name-value-pair for use with `listToAttrs` | ||
entryToNameValuePair = | ||
{ name, location }: | ||
{ | ||
name = sanitizeId name; | ||
value = | ||
let | ||
file = removeNixvimPrefix location.file; | ||
line = builtins.toString location.line; | ||
text = "${file}:${line}"; | ||
target = "${urlPrefix}/${file}#L${line}"; | ||
in | ||
"[${text}](${target}) in `<nixvim>`"; | ||
}; | ||
in | ||
lib.pipe functionSet [ | ||
# Get the entries | ||
collectPositionEntriesFromPaths | ||
# Only include entries that have a location | ||
(builtins.filter (entry: entry.location != null)) | ||
# No need to include out-of-tree entries | ||
(builtins.filter (entry: lib.strings.hasPrefix rootPathString entry.location.file)) | ||
# Convert entries to attrset | ||
(builtins.map entryToNameValuePair) | ||
builtins.listToAttrs | ||
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
lib, | ||
pageSpecs, | ||
indentSize ? " ", | ||
}: | ||
let | ||
pageToLines = | ||
indent: parentName: | ||
{ | ||
name, | ||
outFile ? "", | ||
pages ? { }, | ||
... | ||
}: | ||
let | ||
menuName = lib.strings.removePrefix (parentName + ".") name; | ||
children = builtins.attrValues pages; | ||
# Only add node to the menu if it has content or multiple children | ||
useNodeInMenu = outFile != "" || builtins.length children > 1; | ||
parentOfChildren = if useNodeInMenu then name else parentName; | ||
in | ||
lib.optional useNodeInMenu "${indent}- [${menuName}](${outFile})" | ||
++ lib.optionals (children != [ ]) ( | ||
builtins.concatMap (pageToLines (indent + indentSize) parentOfChildren) children | ||
); | ||
in | ||
lib.pipe pageSpecs [ | ||
builtins.attrValues | ||
(builtins.concatMap (pageToLines "" "")) | ||
lib.concatLines | ||
] |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we could simplify this by using the module system to evaluate
pages.nix
.Most of this "normalisation" could be done by a
page
submodule.I'll plan to address this in a follow up PR.