From 8674027ae1a8ac6d3386d811583f26dd9e5a25ed Mon Sep 17 00:00:00 2001 From: Madeleine Sydney Date: Sat, 11 Jan 2025 12:28:07 -0700 Subject: [PATCH] wip: feat: Gen man pages --- flake.lock | 180 +++++++++++++++++- flake.nix | 2 + hosts/nixos-testbed/configuration.nix | 3 +- scripts/sydnix/deps-lock.json | 45 +++++ scripts/sydnix/deps.edn | 2 + scripts/sydnix/flake.nix | 38 ++-- scripts/sydnix/src/sydnix/cli_table.clj | 2 +- .../sydnix/src/sydnix/commands/deps-lock.json | 151 +++++++++++++++ scripts/sydnix/src/sydnix/commands/help.clj | 89 ++++----- .../sydnix/src/sydnix/commands/rebuild.clj | 18 +- scripts/sydnix/src/sydnix/commands/status.clj | 10 +- scripts/sydnix/src/sydnix/commands/util.clj | 8 + .../src/sydnix/commands/util/mangen.clj | 46 +++++ scripts/sydnix/src/sydnix/main.clj | 28 +-- scripts/sydnix/src/sydnix/mangen.clj | 94 +++++++++ scripts/sydnix/src/sydnix/prelude.clj | 21 ++ 16 files changed, 640 insertions(+), 97 deletions(-) create mode 100644 scripts/sydnix/src/sydnix/commands/deps-lock.json create mode 100644 scripts/sydnix/src/sydnix/commands/util.clj create mode 100644 scripts/sydnix/src/sydnix/commands/util/mangen.clj create mode 100644 scripts/sydnix/src/sydnix/mangen.clj create mode 100644 scripts/sydnix/src/sydnix/prelude.clj diff --git a/flake.lock b/flake.lock index 413df9b..b0f5aec 100755 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,47 @@ { "nodes": { + "clj-nix": { + "inputs": { + "devshell": "devshell", + "nix-fetcher-data": "nix-fetcher-data", + "nixpkgs": "nixpkgs_6" + }, + "locked": { + "lastModified": 1732920288, + "narHash": "sha256-w04hFhbutbob60xy6wUYdawBCVK0qAzBfhGsD+bPypU=", + "owner": "jlesquembre", + "repo": "clj-nix", + "rev": "6e829214a303d2f921c7919f6fb7a2721069c608", + "type": "github" + }, + "original": { + "owner": "jlesquembre", + "repo": "clj-nix", + "type": "github" + } + }, + "devshell": { + "inputs": { + "nixpkgs": [ + "sydnix-cli", + "clj-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1728330715, + "narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=", + "owner": "numtide", + "repo": "devshell", + "rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, "disko": { "inputs": { "nixpkgs": "nixpkgs" @@ -18,6 +60,42 @@ "type": "github" } }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1719745305, + "narHash": "sha256-xwgjVUpqSviudEkpQnioeez1Uo2wzrsMaJKJClh+Bls=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c3c5ecc05edc7dafba779c6c1a61cd08ac6583e9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": "nixpkgs_2" @@ -108,6 +186,29 @@ "type": "github" } }, + "nix-fetcher-data": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": [ + "sydnix-cli", + "clj-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1728229178, + "narHash": "sha256-p5Fx880uBYstIsbaDYN7sECJT11oHxZQKtHgMAVblWA=", + "owner": "jlesquembre", + "repo": "nix-fetcher-data", + "rev": "f3a73c34d28db49ef90fd7872a142bfe93120e55", + "type": "github" + }, + "original": { + "owner": "jlesquembre", + "repo": "nix-fetcher-data", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1733749988, @@ -124,6 +225,18 @@ "type": "github" } }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1717284937, + "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + } + }, "nixpkgs-stable": { "locked": { "lastModified": 1734017764, @@ -204,6 +317,38 @@ "type": "github" } }, + "nixpkgs_6": { + "locked": { + "lastModified": 1728492678, + "narHash": "sha256-9UTxR8eukdg+XZeHgxW5hQA9fIKHsKCdOIUycTryeVw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5633bcff0c6162b9e4b5f1264264611e950c8ec7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1736012469, + "narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "disko": "disko", @@ -211,7 +356,8 @@ "impermanence": "impermanence", "niri": "niri", "nixpkgs": "nixpkgs_4", - "sops-nix": "sops-nix" + "sops-nix": "sops-nix", + "sydnix-cli": "sydnix-cli" } }, "sops-nix": { @@ -232,6 +378,38 @@ "type": "github" } }, + "sydnix-cli": { + "inputs": { + "clj-nix": "clj-nix", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs_7" + }, + "locked": { + "lastModified": 1736880634, + "narHash": "sha256-uFPSHfiWP3tGACvTjrGvWaR6m9w2O2D74yK2GujTFfw=", + "path": "/persist/dots/scripts/sydnix", + "type": "path" + }, + "original": { + "path": "/persist/dots/scripts/sydnix", + "type": "path" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "xwayland-satellite-stable": { "flake": false, "locked": { diff --git a/flake.nix b/flake.nix index 6e08ac2..393fb73 100755 --- a/flake.nix +++ b/flake.nix @@ -15,6 +15,8 @@ niri.url = "github:sodiboo/niri-flake"; sops-nix.url = "github:Mic92/sops-nix"; + + sydnix-cli.url = "path:///persist/dots/scripts/sydnix"; }; outputs = { nixpkgs, ... }@inputs: diff --git a/hosts/nixos-testbed/configuration.nix b/hosts/nixos-testbed/configuration.nix index 92b2a8e..d971b42 100755 --- a/hosts/nixos-testbed/configuration.nix +++ b/hosts/nixos-testbed/configuration.nix @@ -1,4 +1,4 @@ -{ config, pkgs, lib, disko, ... }: +{ config, pkgs, lib, disko, sydnix-cli, ... }: { imports = [ ./hardware-configuration.nix @@ -73,6 +73,7 @@ environment.systemPackages = with pkgs; [ neovim git + sydnix-cli.packages.x86_64-linux.default ]; services.openssh.enable = true; diff --git a/scripts/sydnix/deps-lock.json b/scripts/sydnix/deps-lock.json index 39656b7..7cba38c 100644 --- a/scripts/sydnix/deps-lock.json +++ b/scripts/sydnix/deps-lock.json @@ -2,6 +2,26 @@ "lock-version": 4, "git-deps": [], "mvn-deps": [ + { + "mvn-path": "babashka/fs/0.5.24/fs-0.5.24.jar", + "mvn-repo": "https://repo.clojars.org/", + "hash": "sha256-owunNIWFqt6xNGhNV6vFs7GyYEz8z8wHRT7TSw1MDlU=" + }, + { + "mvn-path": "babashka/fs/0.5.24/fs-0.5.24.pom", + "mvn-repo": "https://repo.clojars.org/", + "hash": "sha256-E1jX6M3DeoTXVU6Vzd6xIpE0s9QAZpZALJl4nSKU8E8=" + }, + { + "mvn-path": "babashka/process/0.5.22/process-0.5.22.jar", + "mvn-repo": "https://repo.clojars.org/", + "hash": "sha256-22BH7RRkuVkJ2+/dHOD2dZ/bVroQS2ySO/dhFGToz0Y=" + }, + { + "mvn-path": "babashka/process/0.5.22/process-0.5.22.pom", + "mvn-repo": "https://repo.clojars.org/", + "hash": "sha256-Ijax5VAq9/FFnKomP+huFSOKh/HWGiwXLAZty/1iwo8=" + }, { "mvn-path": "cider/cider-nrepl/0.50.2/cider-nrepl-0.50.2.jar", "mvn-repo": "https://repo.clojars.org/", @@ -22,6 +42,26 @@ "mvn-repo": "https://repo.clojars.org/", "hash": "sha256-eUGmk2TB2JzLpi2p+Ge//udJO7t/o339YCaPNt7KFek=" }, + { + "mvn-path": "clojure-lanterna/clojure-lanterna/0.9.7/clojure-lanterna-0.9.7.jar", + "mvn-repo": "https://repo.clojars.org/", + "hash": "sha256-rv2Pp1B4p64VdjzXBdJskFzPrK6gVZAL7JfWDfHQikU=" + }, + { + "mvn-path": "clojure-lanterna/clojure-lanterna/0.9.7/clojure-lanterna-0.9.7.pom", + "mvn-repo": "https://repo.clojars.org/", + "hash": "sha256-a1fotCBLdq5aa6ioMIMvLowMJfVYMx4P2oJSj9VS3Cc=" + }, + { + "mvn-path": "com/googlecode/lanterna/lanterna/2.1.7/lanterna-2.1.7.jar", + "mvn-repo": "https://repo1.maven.org/maven2/", + "hash": "sha256-Xr24XNnqvVTsGf+MoESc23RZWc6NTDGSWbs5rOS3hhg=" + }, + { + "mvn-path": "com/googlecode/lanterna/lanterna/2.1.7/lanterna-2.1.7.pom", + "mvn-repo": "https://repo1.maven.org/maven2/", + "hash": "sha256-INQIUi0aEHp7mBvoD0f7t3c2NmMtqZS8/VlJb5JKW/4=" + }, { "mvn-path": "com/kohlschutter/junixsocket/junixsocket-common/2.3.2/junixsocket-common-2.3.2.jar", "mvn-repo": "https://repo1.maven.org/maven2/", @@ -257,6 +297,11 @@ "mvn-repo": "https://repo1.maven.org/maven2/", "hash": "sha256-PLp+DcwIXEzpLd3/6iJhJP+sF4vnm9A3m1suMKlpy+o=" }, + { + "mvn-path": "org/sonatype/oss/oss-parent/7/oss-parent-7.pom", + "mvn-repo": "https://repo1.maven.org/maven2/", + "hash": "sha256-tR+IZ8kranIkmVV/w6H96ne9+e9XRyL+kM5DailVlFQ=" + }, { "mvn-path": "spec-dict/spec-dict/0.2.1/spec-dict-0.2.1.jar", "mvn-repo": "https://repo.clojars.org/", diff --git a/scripts/sydnix/deps.edn b/scripts/sydnix/deps.edn index 4d9b15a..88ccb8b 100644 --- a/scripts/sydnix/deps.edn +++ b/scripts/sydnix/deps.edn @@ -1,4 +1,6 @@ {:deps {org.babashka/cli {:mvn/version "0.8.62"} + babashka/process {:mvn/version "0.5.22"} + babashka/fs {:mvn/version "0.5.24"} org.clojure/clojure {:mvn/version "1.12.0"} org.clojure/core.match {:mvn/version "1.1.0"} spec-dict/spec-dict {:mvn/version "0.2.1"}} diff --git a/scripts/sydnix/flake.nix b/scripts/sydnix/flake.nix index 80bb78c..26028ff 100644 --- a/scripts/sydnix/flake.nix +++ b/scripts/sydnix/flake.nix @@ -1,3 +1,6 @@ +# Generate lock file: +# nix run github:jlesquembre/clj-nix#deps-lock + { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; @@ -14,15 +17,25 @@ clj-nix.overlays.default ]; }; - in { - packages.default = pkgs.mkCljBin { - name = "msyds/sydnix"; - main-ns = "sydnix.main"; - projectSrc = ./.; - # nativeImage.enable = true; - # customJdk.enable = true; - }; + sydnix = pkgs.mkCljBin { + name = "msyds/sydnix"; + main-ns = "sydnix.main"; + projectSrc = ./.; + + buildInputs = with pkgs; [ + asciidoctor + ]; + nativeBuildInputs = with pkgs; [ + makeWrapper + ]; + postInstall = '' + wrapProgram $out/bin/sydnix \ + --set ADOC_PROCESSOR "${pkgs.asciidoctor}/bin/asciidoctor" + ''; + }; + in { + packages.default = sydnix; devShells.default = pkgs.mkShell { inputsFrom = [ @@ -31,10 +44,11 @@ # self.packages.${system}.default ]; - packages = [ - pkgs.clojure-lsp - pkgs.clojure - pkgs.babashka + packages = with pkgs; [ + clojure-lsp + clojure + babashka + asciidoctor ]; }; }); diff --git a/scripts/sydnix/src/sydnix/cli_table.clj b/scripts/sydnix/src/sydnix/cli_table.clj index e4bac5b..f9beaec 100644 --- a/scripts/sydnix/src/sydnix/cli_table.clj +++ b/scripts/sydnix/src/sydnix/cli_table.clj @@ -1,3 +1,3 @@ (ns sydnix.cli-table) -(def ^:dynamic *cli-table*) +(def *cli-table (atom nil)) diff --git a/scripts/sydnix/src/sydnix/commands/deps-lock.json b/scripts/sydnix/src/sydnix/commands/deps-lock.json new file mode 100644 index 0000000..b25327a --- /dev/null +++ b/scripts/sydnix/src/sydnix/commands/deps-lock.json @@ -0,0 +1,151 @@ +{ + "lock-version": 4, + "git-deps": [], + "mvn-deps": [ + { + "mvn-path": "org/clojure/clojure/1.10.3/clojure-1.10.3.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-fxJHLa7Y9rUXSYqqKrE6ViR1w+31FHjkWBzHYemJeaM=" + }, + { + "mvn-path": "org/clojure/clojure/1.10.3/clojure-1.10.3.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-GJwAxDNAdJai+7DsyzeQjJSVXZHq0b5IFWdE7MGBbZQ=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.0/clojure-1.11.0.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-PiH6daB+yd278bK1A1bPGAcQ0DmN6qT0TpHNYwRVWUc=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.0/clojure-1.11.0.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-SQjMS0yeYsmoFJb5PLWsb2lBd8xkXc87jOXkkavOHro=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.1/clojure-1.11.1.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-I4G26UI6tGUVFFWUSQPROlYkPWAGuRlK/Bv0+HEMtN4=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.1/clojure-1.11.1.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-IMRaGr7b2L4grvk2BQrjGgjBZ0CzL4dAuIOM3pb/y4o=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.2/clojure-1.11.2.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-iPqZkT1pIs+39kn1xGdQOHfLb8yMwW02948mSAhLqZc=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.2/clojure-1.11.2.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-FzbP/xCV4dT+/raogrut9ttB7+MV8pbw/aMtt//EExE=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.3/clojure-1.11.3.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-nDBUCTKOK5boXdK160t1gQxnt2unCuTQ9t3pvPtVsbc=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.3/clojure-1.11.3.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-DA2+Ge4NKpxXMQzr3dNWRD8NFlFMQmBHsGLjpXwNuK0=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.4/clojure-1.11.4.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-/H/xtmENDjSUp1zBHvgYEL2kAqwVcBL+TjuJlYbPQTM=" + }, + { + "mvn-path": "org/clojure/clojure/1.11.4/clojure-1.11.4.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-a6YADmhI+Cw5y5tJqyqmo6Vi9MJNUrMeUZCuZJXwwwk=" + }, + { + "mvn-path": "org/clojure/clojure/1.12.0/clojure-1.12.0.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-xFMzAGRBoFnqn9sTQfxsH0C5IaENzNgmZTEeSKA4R2M=" + }, + { + "mvn-path": "org/clojure/clojure/1.12.0/clojure-1.12.0.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-KfRiqonLl2RXWEGKXwjUwagrc1yW569JgX0WqpuQgVA=" + }, + { + "mvn-path": "org/clojure/core.specs.alpha/0.2.56/core.specs.alpha-0.2.56.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-/PRCveArBKhj8vzFjuaiowxM8Mlw99q4VjTwq3ERZrY=" + }, + { + "mvn-path": "org/clojure/core.specs.alpha/0.2.56/core.specs.alpha-0.2.56.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-AarxdIP/HHSCySoHKV1+e8bjszIt9EsptXONAg/wB0A=" + }, + { + "mvn-path": "org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-Bu6owHC75FwVhWfkQ0OWgbyMRukSNBT4G/oyukLWy8g=" + }, + { + "mvn-path": "org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-F3i70Ti9GFkLgFS+nZGdG+toCfhbduXGKFtn1Ad9MA4=" + }, + { + "mvn-path": "org/clojure/core.specs.alpha/0.4.74/core.specs.alpha-0.4.74.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-63OsCM9JuoQMiLpnvu8RM2ylVDM9lAiAjXiUbg/rnds=" + }, + { + "mvn-path": "org/clojure/core.specs.alpha/0.4.74/core.specs.alpha-0.4.74.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-M0EOuKpz1S2Vez3G4KZfOZisBiPL2BPZDDPm5onEJCk=" + }, + { + "mvn-path": "org/clojure/pom.contrib/0.3.0/pom.contrib-0.3.0.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-fxgrOypUPgV0YL+T/8XpzvasUn3xoTdqfZki6+ee8Rk=" + }, + { + "mvn-path": "org/clojure/pom.contrib/1.1.0/pom.contrib-1.1.0.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-EOzku1+YKQENwWVh9C67g7ry9HYFtR+RBbkvPKoIlxU=" + }, + { + "mvn-path": "org/clojure/pom.contrib/1.2.0/pom.contrib-1.2.0.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-CRbXpBVYuVAKQnyIb6KYJ6zlJZIGvjrTPmTilvwaYRE=" + }, + { + "mvn-path": "org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-z2iZ+YUpjGSxPqEplGrZAo3uja3w6rmuGORVAn04JJw=" + }, + { + "mvn-path": "org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-WhHw4eizwFLmUcSYxpRbRNs1Nb8sGHGf3PZd8fiLE+Y=" + }, + { + "mvn-path": "org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-Z+yJjrVcZqlXpVJ53YXRN2u5lL2HZosrDeHrO5foquA=" + }, + { + "mvn-path": "org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-bY3hTDrIdXYMX/kJVi/5hzB3AxxquTnxyxOeFp/pB1g=" + }, + { + "mvn-path": "org/clojure/spec.alpha/0.5.238/spec.alpha-0.5.238.jar", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-lM2ZtupjlkHzevSGCmQ7btOZ7lqL5dcXz/C2Y8jXUHc=" + }, + { + "mvn-path": "org/clojure/spec.alpha/0.5.238/spec.alpha-0.5.238.pom", + "mvn-repo": "https://repo.maven.apache.org/maven2/", + "hash": "sha256-PLp+DcwIXEzpLd3/6iJhJP+sF4vnm9A3m1suMKlpy+o=" + } + ] +} diff --git a/scripts/sydnix/src/sydnix/commands/help.clj b/scripts/sydnix/src/sydnix/commands/help.clj index c529a3a..f8a6860 100644 --- a/scripts/sydnix/src/sydnix/commands/help.clj +++ b/scripts/sydnix/src/sydnix/commands/help.clj @@ -1,65 +1,40 @@ (ns sydnix.commands.help (:require - [clojure.pprint :refer [pprint]] - [asciidoc.render :as ar] - [clojure.spec.alpha :as s] - [clojure.string :as str] - [clojure.zip :as zip] - [spec-dict :refer [dict]] - [sydnix.cli-table :refer [*cli-table*]])) + [babashka.process :as p] + [sydnix.mangen :as mangen])) -(defn- find-satisfying [p xs] - (->> xs (filter p) first)) -(defn- find-dispatched [dispatch] - (find-satisfying #(= dispatch (:cmds %)) *cli-table*)) - -(defn- format-p [s] - (-> s - (str/replace #"^ +" " ") - (str/replace #"\n +" "\n"))) - -(defn- docs-for-command [command-spec] - (let [command (cons "sydnix" (:cmds command-spec))] - [:document {:title (str (str/join "-" command) - "(1)") - :author "Madeleine Sydney Ślaga" - :a {:doctype "manpage" - :manmanual "SYDNIX" - :mansource "SYDNIX"}} - [:section {:title "Name"} - [:p (format "%s - %s" - (str/join " " command) - (:desc command-spec))]] - [:section {:title "Synopsis"} - [:p (format "%s [_option_…]" - (str/join " " command))]] - (concat [:section {:title "Options"}] - (for [[opt opt-spec] (:spec command-spec)] - [:description {:described (format "*--%s%s*" - (name opt) - (if-let [ref (:ref opt-spec)] - (str "=" ref) - ""))} - [:p (format-p (:desc opt-spec))]]))])) - -(defn- render-docs-for-command [command-spec] - (try (ar/render (docs-for-command command-spec)) - (catch Exception e - (prn e) - (s/explain :asciidoc.types/document command-spec) - (throw e)))) - - - -(defn- command-fn [opts] - (prn "help" opts)) - -(defn adorn-with-help-option [command-fn] - (fn [{:keys [opts dispatch] :as w}] +(defn adorn-with-help-option [wrapped-command-fn] + (fn [{:keys [opts dispatch]}] (if (:help opts) - (render-docs-for-command (find-dispatched dispatch)) - (command-fn opts)))) + (mangen/with-pipe + (fn [man->] + (mangen/write-man-for-command (mangen/find-dispatched dispatch) + :out man->)) + (fn [->man] + (p/shell {:in ->man} + "man -l -"))) + (wrapped-command-fn opts)))) + +(defn- view-man-for-command [command-spec] + (mangen/with-pipe + (fn [man->] + (mangen/write-man-for-command command-spec :out man->)) + (fn [->man] + (p/shell {:in ->man} "man -l -")))) + +(defn- wrap-command-fn [wrapped-fn] + (fn [info] + (if (:help (:opts info)) + (view-man-for-command (mangen/find-dispatched (:dispatch info))) + (when-not (nil? wrapped-fn) + (wrapped-fn info))))) + +(defn adorn-with-help-option* [command-spec] + (update command-spec :fn wrap-command-fn)) + +(defn- command-fn [_opts] + (view-man-for-command (mangen/find-dispatched []))) (def command {:cmds ["help"] diff --git a/scripts/sydnix/src/sydnix/commands/rebuild.clj b/scripts/sydnix/src/sydnix/commands/rebuild.clj index abcb7e7..b12d4a2 100644 --- a/scripts/sydnix/src/sydnix/commands/rebuild.clj +++ b/scripts/sydnix/src/sydnix/commands/rebuild.clj @@ -1,13 +1,13 @@ (ns sydnix.commands.rebuild (:require [clojure.java.shell :refer [sh]] - [sydnix.commands.help :refer [adorn-with-help-option]])) + [sydnix.commands.help :refer [adorn-with-help-option*]])) (def command-options-spec {:flake {:coerce :string - :ref "«URI»" - :desc "«URI» is a path to a Flake, which is passed to `nixos-rebuild - --flake «URI»` as is." + :ref "URI" + :desc "URI is a path to a Flake, which is passed to `nixos-rebuild + --flake URI` as is." :default "path:///persist/dots"}}) (defn- command-fn [{:keys [args opts]}] @@ -18,8 +18,8 @@ (apply println "$" rebuild-cmd) (apply sh rebuild-cmd))) -(def command - {:cmds ["rebuild"] - :desc "Rebuild the system NixOS and Home-manager configuration" - :fn (adorn-with-help-option command-fn) - :spec command-options-spec}) +(def commands + [{:cmds ["rebuild"] + :desc "Rebuild the system NixOS and Home-manager configuration" + :fn command-fn + :spec command-options-spec}]) diff --git a/scripts/sydnix/src/sydnix/commands/status.clj b/scripts/sydnix/src/sydnix/commands/status.clj index eb03dce..7a046f8 100644 --- a/scripts/sydnix/src/sydnix/commands/status.clj +++ b/scripts/sydnix/src/sydnix/commands/status.clj @@ -1,11 +1,11 @@ (ns sydnix.commands.status (:require - [sydnix.commands.help :refer [adorn-with-help-option]])) + [sydnix.commands.help :refer [adorn-with-help-option*]])) (defn- command-fn [opts] (prn opts)) -(def command - {:cmds ["status"] - :desc "View system info" - :fn (adorn-with-help-option command-fn)}) +(def commands + [{:cmds ["status"] + :desc "View system info" + :fn command-fn}]) diff --git a/scripts/sydnix/src/sydnix/commands/util.clj b/scripts/sydnix/src/sydnix/commands/util.clj new file mode 100644 index 0000000..5d6a465 --- /dev/null +++ b/scripts/sydnix/src/sydnix/commands/util.clj @@ -0,0 +1,8 @@ +(ns sydnix.commands.util + (:require + [sydnix.commands.util.mangen :as cmd-util-mangen])) + +(def commands + [{:cmds ["util"] + :desc "Infrequently-used utilities such as docgen and shell completions."} + cmd-util-mangen/command]) diff --git a/scripts/sydnix/src/sydnix/commands/util/mangen.clj b/scripts/sydnix/src/sydnix/commands/util/mangen.clj new file mode 100644 index 0000000..48b91bb --- /dev/null +++ b/scripts/sydnix/src/sydnix/commands/util/mangen.clj @@ -0,0 +1,46 @@ +(ns sydnix.commands.util.mangen + (:require + [asciidoc.render] + [babashka.fs :as fs] + [babashka.process :as p] + [sydnix.mangen :as mangen] + [clojure.java.io :as io] + [clojure.spec.alpha :as s] + [clojure.string :as str] + [sydnix.cli-table :refer [*cli-table]] + [sydnix.commands.help :refer [adorn-with-help-option*]] + [sydnix.prelude :as prelude])) + +(defn command-fn [{:keys [yes output-directory]}] + (if (or yes + (prelude/y-or-n? (format "Write a bunch of man pages to %s?" + output-directory))) + (doseq [cmd-spec (deref *cli-table)] + (let [man-file-name (fs/file + output-directory + (str (str/join "-" (cons "sydnix" (:cmds cmd-spec))) + ".1"))] + (with-open [man-file (io/writer man-file-name)] + (mangen/write-man-for-command cmd-spec :out man-file)) + (printf "wrote %s\n" man-file-name) + (flush))) + (System/exit 1))) + +(def command-options-spec + {:output-directory {:coerce :string + :ref "DIRECTORY" + :alias :o + :desc "Directory to which the generated man pages will be + written." + :require true + :validate fs/directory?} + :yes {:coerce :bool + :desc "Don't ask for confirmation." + :default false}}) + +(def command + (adorn-with-help-option* + {:cmds ["util" "mangen"] + :desc "Generate man pages for each subcommand of `sydnix`." + :fn command-fn + :spec command-options-spec})) diff --git a/scripts/sydnix/src/sydnix/main.clj b/scripts/sydnix/src/sydnix/main.clj index 15ad8bf..3112f9c 100755 --- a/scripts/sydnix/src/sydnix/main.clj +++ b/scripts/sydnix/src/sydnix/main.clj @@ -1,19 +1,25 @@ (ns sydnix.main (:require [babashka.cli :as cli] - [sydnix.cli-table :refer [*cli-table*]] - [sydnix.commands.help :as cmd-help] + [sydnix.cli-table :refer [*cli-table]] + [sydnix.commands.help :as cmd-help :refer [adorn-with-help-option*]] + [sydnix.commands.rebuild :as cmd-rebuild] [sydnix.commands.status :as cmd-status] - [sydnix.commands.rebuild :as cmd-rebuild]) + [sydnix.commands.util :as cmd-util]) (:gen-class)) -(def cli-table - [cmd-status/command - cmd-rebuild/command - cmd-help/command - ;; Show help when no other command matches. - (assoc cmd-help/command :cmds [])]) +(def real-cli-table + (map adorn-with-help-option* + (concat cmd-status/commands + cmd-rebuild/commands + cmd-util/commands + [cmd-help/command + ;; Show help when no other command matches. + (assoc cmd-help/command :cmds [])]))) (defn -main [& args] - (binding [*cli-table* cli-table] - (cli/dispatch cli-table args))) + (reset! *cli-table real-cli-table) + (cli/dispatch @*cli-table args) + ;; Process may hang without this form. D:{ + ;; https://github.com/babashka/process?tab=readme-ov-file#script-termination + (shutdown-agents)) diff --git a/scripts/sydnix/src/sydnix/mangen.clj b/scripts/sydnix/src/sydnix/mangen.clj new file mode 100644 index 0000000..fc104be --- /dev/null +++ b/scripts/sydnix/src/sydnix/mangen.clj @@ -0,0 +1,94 @@ +(ns sydnix.mangen + (:require + [asciidoc.render] + [asciidoc.types] + [babashka.fs :as fs] + [babashka.process :as p] + [clojure.spec.alpha :as s] + [clojure.string :as str] + [sydnix.cli-table :refer [*cli-table]]) + (:import + [java.io BufferedReader PipedReader PipedWriter])) + +(defn- format-p [s] + (-> s + (str/replace #"^ +" " ") + (str/replace #"\n +" "\n"))) + +(defn- docs-for-command [command-spec] + (let [command (cons "sydnix" (:cmds command-spec))] + [:document {:title (str (str/join "-" command) + "(1)") + :author "Madeleine Sydney Ślaga" + :a {:doctype "manpage" + :manmanual "SYDNIX" + :mansource "SYDNIX"}} + [:section {:title "Name"} + [:p (format "%s - %s" + (str/join " " command) + (:desc command-spec))]] + [:section {:title "Synopsis"} + [:p (format "%s [_option_…]" + (str/join " " command))]] + (concat [:section {:title "Options"}] + (for [[opt opt-spec] (:spec command-spec)] + [:description {:described (format "*--%s%s*" + (name opt) + (if-let [ref (:ref opt-spec)] + (str "=" ref) + ""))} + [:p (format-p (:desc opt-spec))]]))])) + +(defn render-docs-for-command [command-spec] + (try (asciidoc.render/render (docs-for-command command-spec)) + (catch Exception e + (prn e) + (s/explain :asciidoc.types/document command-spec) + (throw e)))) + +(defn- find-satisfying [p xs] + (->> xs (filter p) first)) + +(defn find-dispatched [dispatch] + (find-satisfying #(= dispatch (:cmds %)) (deref *cli-table))) + +(defn- find-adoc-processor + "Looks for a suitable AsciiDoc processor. In order of precedence, it will try + `$ADOC_PROCESSOR`, then `asciidoctor`." + [& {:keys [throw?]}] + (letfn [(suitable [x] + (when (and x (fs/executable? x)) + x))] + (or (suitable (System/getenv "ADOC_PROCESSOR")) + (suitable (fs/which "asciidoctor")) + (when throw? + (throw (ex-info "Can't find a suitable AsciiDoc processor" {})))))) + +(defn asciidoctor + "Shell out to AsciiDoctor (`$ADOC_PROCESSOR`, actually) to create ROFF markup + for man pages." + [& {:keys [asciidoctor-bin in out err] + :or {asciidoctor-bin (find-adoc-processor :throw? true) + in *in* + out *out* + err *err*}}] + (p/shell {:in in :out out :err err} + asciidoctor-bin "-o" "-" "-b" "manpage" "-")) + +(defn with-pipe [with-out with-in] + (let [out (PipedWriter.) + in (PipedReader. out)] + (future (with-out out) + (.close out)) + (with-in (BufferedReader. in)))) + +(defn write-man-for-command + [command-spec & {:keys [out err] + :or {out *out* + err *err*}}] + (with-pipe + (fn [adoc->] + (binding [*out* adoc->] + (render-docs-for-command command-spec))) + (fn [->adoc] + (asciidoctor :in ->adoc :out out :err err)))) diff --git a/scripts/sydnix/src/sydnix/prelude.clj b/scripts/sydnix/src/sydnix/prelude.clj new file mode 100644 index 0000000..c7208a0 --- /dev/null +++ b/scripts/sydnix/src/sydnix/prelude.clj @@ -0,0 +1,21 @@ +(ns sydnix.prelude + (:require + [clojure.core.match :refer [match]])) + +(defn y-or-n? + [prompt + & {:keys [default] + :or {default :n} + :as opts}] + (let [y-n-indicator (case default + :y " [Y/n] " + :n " [y/N] ")] + (print (str prompt y-n-indicator)) + (flush)) + (let [line (read-line)] + (match line + "" (case default :y true :n false) + (:or "y" "Y") true + (:or "n" "N") false + _ (do (println "Please enter y or n.") + (recur prompt opts)))))