Merge pull request #243062 from mobusoperandi/doc_watchexec
nixpkgs/NixOS manuals: devmode feature
This commit is contained in:
commit
a7e5800273
9 changed files with 189 additions and 10 deletions
4
doc/common.nix
Normal file
4
doc/common.nix
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
outputPath = "share/doc/nixpkgs";
|
||||
indexPath = "manual.html";
|
||||
}
|
|
@ -23,6 +23,14 @@ $ nix-shell
|
|||
|
||||
If the build succeeds, the manual will be in `./result/share/doc/nixpkgs/manual.html`.
|
||||
|
||||
## devmode {#sec-contributing-devmode}
|
||||
|
||||
The shell in the manual source directory makes available a command, `devmode`.
|
||||
It is a daemon, that:
|
||||
1. watches the manual's source for changes and when they occur — rebuilds
|
||||
2. HTTP serves the manual, injecting a script that triggers reload on changes
|
||||
3. opens the manual in the default browser
|
||||
|
||||
## Syntax {#sec-contributing-markup}
|
||||
|
||||
As per [RFC 0072](https://github.com/NixOS/rfcs/pull/72), all new documentation content should be written in [CommonMark](https://commonmark.org/) Markdown dialect.
|
||||
|
|
|
@ -3,6 +3,8 @@ let
|
|||
inherit (pkgs) lib;
|
||||
inherit (lib) hasPrefix removePrefix;
|
||||
|
||||
common = import ./common.nix;
|
||||
|
||||
lib-docs = import ./doc-support/lib-function-docs.nix {
|
||||
inherit pkgs nixpkgs;
|
||||
libsets = [
|
||||
|
@ -132,15 +134,15 @@ in pkgs.stdenv.mkDerivation {
|
|||
'';
|
||||
|
||||
installPhase = ''
|
||||
dest="$out/share/doc/nixpkgs"
|
||||
dest="$out/${common.outputPath}"
|
||||
mkdir -p "$(dirname "$dest")"
|
||||
mv out "$dest"
|
||||
mv "$dest/index.html" "$dest/manual.html"
|
||||
mv "$dest/index.html" "$dest/${common.indexPath}"
|
||||
|
||||
cp ${epub} "$dest/nixpkgs-manual.epub"
|
||||
|
||||
mkdir -p $out/nix-support/
|
||||
echo "doc manual $dest manual.html" >> $out/nix-support/hydra-build-products
|
||||
echo "doc manual $dest ${common.indexPath}" >> $out/nix-support/hydra-build-products
|
||||
echo "doc manual $dest nixpkgs-manual.epub" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
}
|
||||
|
|
20
doc/shell.nix
Normal file
20
doc/shell.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
let
|
||||
pkgs = import ../. {
|
||||
config = {};
|
||||
overlays = [];
|
||||
};
|
||||
|
||||
common = import ./common.nix;
|
||||
inherit (common) outputPath indexPath;
|
||||
|
||||
web-devmode = import ../pkgs/tools/nix/web-devmode.nix {
|
||||
inherit pkgs;
|
||||
buildArgs = "./.";
|
||||
open = "/${outputPath}/${indexPath}";
|
||||
};
|
||||
in
|
||||
pkgs.mkShell {
|
||||
packages = [
|
||||
web-devmode
|
||||
];
|
||||
}
|
4
nixos/doc/manual/common.nix
Normal file
4
nixos/doc/manual/common.nix
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
outputPath = "share/doc/nixos";
|
||||
indexPath = "index.html";
|
||||
}
|
|
@ -11,6 +11,8 @@ $ nix-build nixos/release.nix -A manual.x86_64-linux
|
|||
|
||||
If the build succeeds, the manual will be in `./result/share/doc/nixos/index.html`.
|
||||
|
||||
There's also [a convenient development daemon](https://nixos.org/manual/nixpkgs/unstable/#sec-contributing-devmode).
|
||||
|
||||
**Contributing to the man pages**
|
||||
|
||||
The man pages are written in [DocBook] which is XML.
|
||||
|
|
|
@ -16,6 +16,8 @@ let
|
|||
|
||||
lib = pkgs.lib;
|
||||
|
||||
common = import ./common.nix;
|
||||
|
||||
manpageUrls = pkgs.path + "/doc/manpage-urls.json";
|
||||
|
||||
# We need to strip references to /nix/store/* from options,
|
||||
|
@ -78,11 +80,11 @@ let
|
|||
substituteInPlace ./nixos-options.md \
|
||||
--replace \
|
||||
'@NIXOS_OPTIONS_JSON@' \
|
||||
${optionsDoc.optionsJSON}/share/doc/nixos/options.json
|
||||
${optionsDoc.optionsJSON}/${common.outputPath}/options.json
|
||||
substituteInPlace ./development/writing-nixos-tests.section.md \
|
||||
--replace \
|
||||
'@NIXOS_TEST_OPTIONS_JSON@' \
|
||||
${testOptionsDoc.optionsJSON}/share/doc/nixos/options.json
|
||||
${testOptionsDoc.optionsJSON}/${common.outputPath}/options.json
|
||||
sed -e '/@PYTHON_MACHINE_METHODS@/ {' -e 'r ${testDriverMachineDocstrings}/machine-methods.md' -e 'd' -e '}' \
|
||||
-i ./development/writing-nixos-tests.section.md
|
||||
'';
|
||||
|
@ -99,7 +101,7 @@ in rec {
|
|||
}
|
||||
''
|
||||
# Generate the HTML manual.
|
||||
dst=$out/share/doc/nixos
|
||||
dst=$out/${common.outputPath}
|
||||
mkdir -p $dst
|
||||
|
||||
cp ${../../../doc/style.css} $dst/style.css
|
||||
|
@ -120,7 +122,7 @@ in rec {
|
|||
--toc-depth 1 \
|
||||
--chunk-toc-depth 1 \
|
||||
./manual.md \
|
||||
$dst/index.html
|
||||
$dst/${common.indexPath}
|
||||
|
||||
mkdir -p $out/nix-support
|
||||
echo "nix-build out $out" >> $out/nix-support/hydra-build-products
|
||||
|
@ -131,7 +133,7 @@ in rec {
|
|||
manual = manualHTML;
|
||||
|
||||
# Index page of the NixOS manual.
|
||||
manualHTMLIndex = "${manualHTML}/share/doc/nixos/index.html";
|
||||
manualHTMLIndex = "${manualHTML}/${common.outputPath}/${common.indexPath}";
|
||||
|
||||
manualEpub = runCommand "nixos-manual-epub"
|
||||
{ nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin buildPackages.zip ];
|
||||
|
@ -162,7 +164,7 @@ in rec {
|
|||
}
|
||||
''
|
||||
# Generate the epub manual.
|
||||
dst=$out/share/doc/nixos
|
||||
dst=$out/${common.outputPath}
|
||||
|
||||
xsltproc \
|
||||
--param chapter.autolabel 0 \
|
||||
|
@ -197,7 +199,7 @@ in rec {
|
|||
mkdir -p $out/share/man/man5
|
||||
nixos-render-docs -j $NIX_BUILD_CORES options manpage \
|
||||
--revision ${lib.escapeShellArg revision} \
|
||||
${optionsJSON}/share/doc/nixos/options.json \
|
||||
${optionsJSON}/${common.outputPath}/options.json \
|
||||
$out/share/man/man5/configuration.nix.5
|
||||
'';
|
||||
|
||||
|
|
20
nixos/doc/manual/shell.nix
Normal file
20
nixos/doc/manual/shell.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
let
|
||||
pkgs = import ../../.. {
|
||||
config = {};
|
||||
overlays = [];
|
||||
};
|
||||
|
||||
common = import ./common.nix;
|
||||
inherit (common) outputPath indexPath;
|
||||
|
||||
web-devmode = import ../../../pkgs/tools/nix/web-devmode.nix {
|
||||
inherit pkgs;
|
||||
buildArgs = "../../release.nix -A manualHTML.${builtins.currentSystem}";
|
||||
open = "/${outputPath}/${indexPath}";
|
||||
};
|
||||
in
|
||||
pkgs.mkShell {
|
||||
packages = [
|
||||
web-devmode
|
||||
];
|
||||
}
|
117
pkgs/tools/nix/web-devmode.nix
Normal file
117
pkgs/tools/nix/web-devmode.nix
Normal file
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
pkgs,
|
||||
# arguments to `nix-build`, e.g. `"foo.nix -A bar"`
|
||||
buildArgs,
|
||||
# what path to open a browser at
|
||||
open,
|
||||
}: let
|
||||
inherit (pkgs) lib;
|
||||
|
||||
error_page = pkgs.writeShellScriptBin "error_page" ''
|
||||
echo "<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root { filter: invert(100%); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body><pre>$1</pre></body>
|
||||
</html>"
|
||||
'';
|
||||
|
||||
# The following would have been simpler:
|
||||
# 1. serve from `$serve`
|
||||
# 2. pass each build a `--out-link $serve/result`
|
||||
# But that way live-server does not seem to detect changes and therefore no
|
||||
# auto-reloads occur.
|
||||
# Instead, we copy the contents of each build to the `$serve` directory.
|
||||
# Using rsync here, instead of `cp`, to get as close to an atomic
|
||||
# directory copy operation as possible. `--delay-updates` should
|
||||
# also go towards that.
|
||||
build_and_copy = pkgs.writeShellScriptBin "build_and_copy" ''
|
||||
set -euxo pipefail
|
||||
|
||||
set +e
|
||||
stderr=$(2>&1 nix-build --out-link $out_link ${buildArgs})
|
||||
exit_status=$?
|
||||
set -e
|
||||
|
||||
if [ $exit_status -eq 0 ];
|
||||
then
|
||||
# setting permissions to be able to clean up
|
||||
${lib.getBin pkgs.rsync}/bin/rsync \
|
||||
--recursive \
|
||||
--chmod=u=rwX \
|
||||
--delete-before \
|
||||
--delay-updates \
|
||||
$out_link/ \
|
||||
$serve/
|
||||
else
|
||||
set +x
|
||||
${lib.getBin error_page}/bin/error_page "$stderr" > $error_page_absolute
|
||||
set -x
|
||||
|
||||
${lib.getBin pkgs.findutils}/bin/find $serve \
|
||||
-type f \
|
||||
! -name $error_page_relative \
|
||||
-delete
|
||||
fi
|
||||
'';
|
||||
|
||||
# https://watchexec.github.io/
|
||||
watcher = pkgs.writeShellScriptBin "watcher" ''
|
||||
set -euxo pipefail
|
||||
|
||||
${lib.getBin pkgs.watchexec}/bin/watchexec \
|
||||
--shell=none \
|
||||
--restart \
|
||||
--print-events \
|
||||
${lib.getBin build_and_copy}/bin/build_and_copy
|
||||
'';
|
||||
|
||||
# A Rust alternative to live-server exists, but it was not in nixpkgs.
|
||||
# `--no-css-inject`: without this it seems that only CSS is auto-reloaded.
|
||||
# https://www.npmjs.com/package/live-server
|
||||
server = pkgs.writeShellScriptBin "server" ''
|
||||
set -euxo pipefail
|
||||
|
||||
${lib.getBin pkgs.nodePackages_latest.live-server}/bin/live-server \
|
||||
--host=127.0.0.1 \
|
||||
--verbose \
|
||||
--no-css-inject \
|
||||
--entry-file=$error_page_relative \
|
||||
--open=${open} \
|
||||
$serve
|
||||
'';
|
||||
|
||||
devmode =
|
||||
pkgs.writeShellScriptBin "devmode"
|
||||
''
|
||||
set -euxo pipefail
|
||||
|
||||
function handle_exit {
|
||||
rm -rf "$tmpdir"
|
||||
}
|
||||
|
||||
tmpdir=$(mktemp -d)
|
||||
trap handle_exit EXIT
|
||||
|
||||
export out_link="$tmpdir/result"
|
||||
export serve="$tmpdir/serve"
|
||||
mkdir $serve
|
||||
export error_page_relative=error.html
|
||||
export error_page_absolute=$serve/$error_page_relative
|
||||
${lib.getBin error_page}/bin/error_page "building …" > $error_page_absolute
|
||||
|
||||
${lib.getBin pkgs.parallel}/bin/parallel \
|
||||
--will-cite \
|
||||
--line-buffer \
|
||||
--tagstr '{/}' \
|
||||
::: \
|
||||
"${lib.getBin watcher}/bin/watcher" \
|
||||
"${lib.getBin server}/bin/server"
|
||||
'';
|
||||
in
|
||||
devmode
|
Loading…
Reference in a new issue