nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix

nixpkgs/NixOS manuals: devmode feature

Co-authored-by: Alejandro Sanchez Medina <alejandrosanchzmedina@gmail.com>

+167
+8
doc/contributing/contributing-to-documentation.chapter.md
··· 23 23 24 24 If the build succeeds, the manual will be in `./result/share/doc/nixpkgs/manual.html`. 25 25 26 + ## devmode {#sec-contributing-devmode} 27 + 28 + The shell in the manual source directory makes available a command, `devmode`. 29 + It is a daemon, that: 30 + 1. watches the manual's source for changes and when they occur — rebuilds 31 + 2. HTTP serves the manual, injecting a script that triggers reload on changes 32 + 3. opens the manual in the default browser 33 + 26 34 ## Syntax {#sec-contributing-markup} 27 35 28 36 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.
+20
doc/shell.nix
··· 1 + let 2 + pkgs = import ../. { 3 + config = {}; 4 + overlays = []; 5 + }; 6 + 7 + common = import ./common.nix; 8 + inherit (common) outputPath indexPath; 9 + 10 + web-devmode = import ../pkgs/tools/nix/web-devmode.nix { 11 + inherit pkgs; 12 + buildArgs = "./."; 13 + open = "/${outputPath}/${indexPath}"; 14 + }; 15 + in 16 + pkgs.mkShell { 17 + packages = [ 18 + web-devmode 19 + ]; 20 + }
+2
nixos/doc/manual/contributing-to-this-manual.chapter.md
··· 11 11 12 12 If the build succeeds, the manual will be in `./result/share/doc/nixos/index.html`. 13 13 14 + There's also [a convenient development daemon](https://nixos.org/manual/nixpkgs/unstable/#sec-contributing-devmode). 15 + 14 16 **Contributing to the man pages** 15 17 16 18 The man pages are written in [DocBook] which is XML.
+20
nixos/doc/manual/shell.nix
··· 1 + let 2 + pkgs = import ../../.. { 3 + config = {}; 4 + overlays = []; 5 + }; 6 + 7 + common = import ./common.nix; 8 + inherit (common) outputPath indexPath; 9 + 10 + web-devmode = import ../../../pkgs/tools/nix/web-devmode.nix { 11 + inherit pkgs; 12 + buildArgs = "../../release.nix -A manualHTML.${builtins.currentSystem}"; 13 + open = "/${outputPath}/${indexPath}"; 14 + }; 15 + in 16 + pkgs.mkShell { 17 + packages = [ 18 + web-devmode 19 + ]; 20 + }
+117
pkgs/tools/nix/web-devmode.nix
··· 1 + { 2 + pkgs, 3 + # arguments to `nix-build`, e.g. `"foo.nix -A bar"` 4 + buildArgs, 5 + # what path to open a browser at 6 + open, 7 + }: let 8 + inherit (pkgs) lib; 9 + 10 + error_page = pkgs.writeShellScriptBin "error_page" '' 11 + echo "<!DOCTYPE html> 12 + <html> 13 + <head> 14 + <style> 15 + @media (prefers-color-scheme: dark) { 16 + :root { filter: invert(100%); } 17 + } 18 + </style> 19 + </head> 20 + <body><pre>$1</pre></body> 21 + </html>" 22 + ''; 23 + 24 + # The following would have been simpler: 25 + # 1. serve from `$serve` 26 + # 2. pass each build a `--out-link $serve/result` 27 + # But that way live-server does not seem to detect changes and therefore no 28 + # auto-reloads occur. 29 + # Instead, we copy the contents of each build to the `$serve` directory. 30 + # Using rsync here, instead of `cp`, to get as close to an atomic 31 + # directory copy operation as possible. `--delay-updates` should 32 + # also go towards that. 33 + build_and_copy = pkgs.writeShellScriptBin "build_and_copy" '' 34 + set -euxo pipefail 35 + 36 + set +e 37 + stderr=$(2>&1 nix-build --out-link $out_link ${buildArgs}) 38 + exit_status=$? 39 + set -e 40 + 41 + if [ $exit_status -eq 0 ]; 42 + then 43 + # setting permissions to be able to clean up 44 + ${lib.getBin pkgs.rsync}/bin/rsync \ 45 + --recursive \ 46 + --chmod=u=rwX \ 47 + --delete-before \ 48 + --delay-updates \ 49 + $out_link/ \ 50 + $serve/ 51 + else 52 + set +x 53 + ${lib.getBin error_page}/bin/error_page "$stderr" > $error_page_absolute 54 + set -x 55 + 56 + ${lib.getBin pkgs.findutils}/bin/find $serve \ 57 + -type f \ 58 + ! -name $error_page_relative \ 59 + -delete 60 + fi 61 + ''; 62 + 63 + # https://watchexec.github.io/ 64 + watcher = pkgs.writeShellScriptBin "watcher" '' 65 + set -euxo pipefail 66 + 67 + ${lib.getBin pkgs.watchexec}/bin/watchexec \ 68 + --shell=none \ 69 + --restart \ 70 + --print-events \ 71 + ${lib.getBin build_and_copy}/bin/build_and_copy 72 + ''; 73 + 74 + # A Rust alternative to live-server exists, but it was not in nixpkgs. 75 + # `--no-css-inject`: without this it seems that only CSS is auto-reloaded. 76 + # https://www.npmjs.com/package/live-server 77 + server = pkgs.writeShellScriptBin "server" '' 78 + set -euxo pipefail 79 + 80 + ${lib.getBin pkgs.nodePackages_latest.live-server}/bin/live-server \ 81 + --host=127.0.0.1 \ 82 + --verbose \ 83 + --no-css-inject \ 84 + --entry-file=$error_page_relative \ 85 + --open=${open} \ 86 + $serve 87 + ''; 88 + 89 + devmode = 90 + pkgs.writeShellScriptBin "devmode" 91 + '' 92 + set -euxo pipefail 93 + 94 + function handle_exit { 95 + rm -rf "$tmpdir" 96 + } 97 + 98 + tmpdir=$(mktemp -d) 99 + trap handle_exit EXIT 100 + 101 + export out_link="$tmpdir/result" 102 + export serve="$tmpdir/serve" 103 + mkdir $serve 104 + export error_page_relative=error.html 105 + export error_page_absolute=$serve/$error_page_relative 106 + ${lib.getBin error_page}/bin/error_page "building …" > $error_page_absolute 107 + 108 + ${lib.getBin pkgs.parallel}/bin/parallel \ 109 + --will-cite \ 110 + --line-buffer \ 111 + --tagstr '{/}' \ 112 + ::: \ 113 + "${lib.getBin watcher}/bin/watcher" \ 114 + "${lib.getBin server}/bin/server" 115 + ''; 116 + in 117 + devmode