summary refs log tree commit diff
diff options
context:
space:
mode:
authorShahar "Dawn" Or <mightyiampresence@gmail.com>2023-07-12 18:50:47 +0700
committerShahar "Dawn" Or <mightyiampresence@gmail.com>2023-07-25 17:03:15 +0700
commita064709342b6adfcafe5bdcff3b5ace453359761 (patch)
tree53df37db251fc57e72c70fba1ac65f0a0129865a
parenta49d40a00523a9ba6714d91f157c0c764b674230 (diff)
downloadnixpkgs-a064709342b6adfcafe5bdcff3b5ace453359761.tar
nixpkgs-a064709342b6adfcafe5bdcff3b5ace453359761.tar.gz
nixpkgs-a064709342b6adfcafe5bdcff3b5ace453359761.tar.bz2
nixpkgs-a064709342b6adfcafe5bdcff3b5ace453359761.tar.lz
nixpkgs-a064709342b6adfcafe5bdcff3b5ace453359761.tar.xz
nixpkgs-a064709342b6adfcafe5bdcff3b5ace453359761.tar.zst
nixpkgs-a064709342b6adfcafe5bdcff3b5ace453359761.zip
nixpkgs/NixOS manuals: devmode feature
Co-authored-by: Alejandro Sanchez Medina <alejandrosanchzmedina@gmail.com>
-rw-r--r--doc/contributing/contributing-to-documentation.chapter.md8
-rw-r--r--doc/shell.nix20
-rw-r--r--nixos/doc/manual/contributing-to-this-manual.chapter.md2
-rw-r--r--nixos/doc/manual/shell.nix20
-rw-r--r--pkgs/tools/nix/web-devmode.nix117
5 files changed, 167 insertions, 0 deletions
diff --git a/doc/contributing/contributing-to-documentation.chapter.md b/doc/contributing/contributing-to-documentation.chapter.md
index a732eee4b96..0b7b49bf7dd 100644
--- a/doc/contributing/contributing-to-documentation.chapter.md
+++ b/doc/contributing/contributing-to-documentation.chapter.md
@@ -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.
diff --git a/doc/shell.nix b/doc/shell.nix
new file mode 100644
index 00000000000..d71e3f3a709
--- /dev/null
+++ b/doc/shell.nix
@@ -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
+    ];
+  }
diff --git a/nixos/doc/manual/contributing-to-this-manual.chapter.md b/nixos/doc/manual/contributing-to-this-manual.chapter.md
index c306cc084cd..4633c7e1b05 100644
--- a/nixos/doc/manual/contributing-to-this-manual.chapter.md
+++ b/nixos/doc/manual/contributing-to-this-manual.chapter.md
@@ -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.
diff --git a/nixos/doc/manual/shell.nix b/nixos/doc/manual/shell.nix
new file mode 100644
index 00000000000..70500a12b03
--- /dev/null
+++ b/nixos/doc/manual/shell.nix
@@ -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
+    ];
+  }
diff --git a/pkgs/tools/nix/web-devmode.nix b/pkgs/tools/nix/web-devmode.nix
new file mode 100644
index 00000000000..6ebdc31118f
--- /dev/null
+++ b/pkgs/tools/nix/web-devmode.nix
@@ -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