summary refs log tree commit diff
path: root/lib/cli.nix
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2022-05-31 09:59:33 +0000
committerAlyssa Ross <hi@alyssa.is>2022-05-31 09:59:57 +0000
commit9ff36293d1e428cd7bf03e8d4b03611b6d361c28 (patch)
tree1ab51a42b868c55b83f6ccdb80371b9888739dd9 /lib/cli.nix
parent1c4fcd0d4b0541e674ee56ace1053e23e562cc80 (diff)
parentddc3c396a51918043bb0faa6f676abd9562be62c (diff)
downloadnixpkgs-9ff36293d1e428cd7bf03e8d4b03611b6d361c28.tar
nixpkgs-9ff36293d1e428cd7bf03e8d4b03611b6d361c28.tar.gz
nixpkgs-9ff36293d1e428cd7bf03e8d4b03611b6d361c28.tar.bz2
nixpkgs-9ff36293d1e428cd7bf03e8d4b03611b6d361c28.tar.lz
nixpkgs-9ff36293d1e428cd7bf03e8d4b03611b6d361c28.tar.xz
nixpkgs-9ff36293d1e428cd7bf03e8d4b03611b6d361c28.tar.zst
nixpkgs-9ff36293d1e428cd7bf03e8d4b03611b6d361c28.zip
Last good Nixpkgs for Weston+nouveau? archive
I came this commit hash to terwiz[m] on IRC, who is trying to figure out
what the last version of Spectrum that worked on their NUC with Nvidia
graphics is.
Diffstat (limited to 'lib/cli.nix')
-rw-r--r--lib/cli.nix83
1 files changed, 83 insertions, 0 deletions
diff --git a/lib/cli.nix b/lib/cli.nix
new file mode 100644
index 00000000000..c96d4dbb043
--- /dev/null
+++ b/lib/cli.nix
@@ -0,0 +1,83 @@
+{ lib }:
+
+rec {
+  /* Automatically convert an attribute set to command-line options.
+
+     This helps protect against malformed command lines and also to reduce
+     boilerplate related to command-line construction for simple use cases.
+
+     `toGNUCommandLine` returns a list of nix strings.
+     `toGNUCommandLineShell` returns an escaped shell string.
+
+     Example:
+       cli.toGNUCommandLine {} {
+         data = builtins.toJSON { id = 0; };
+         X = "PUT";
+         retry = 3;
+         retry-delay = null;
+         url = [ "https://example.com/foo" "https://example.com/bar" ];
+         silent = false;
+         verbose = true;
+       }
+       => [
+         "-X" "PUT"
+         "--data" "{\"id\":0}"
+         "--retry" "3"
+         "--url" "https://example.com/foo"
+         "--url" "https://example.com/bar"
+         "--verbose"
+       ]
+
+       cli.toGNUCommandLineShell {} {
+         data = builtins.toJSON { id = 0; };
+         X = "PUT";
+         retry = 3;
+         retry-delay = null;
+         url = [ "https://example.com/foo" "https://example.com/bar" ];
+         silent = false;
+         verbose = true;
+       }
+       => "'-X' 'PUT' '--data' '{\"id\":0}' '--retry' '3' '--url' 'https://example.com/foo' '--url' 'https://example.com/bar' '--verbose'";
+  */
+  toGNUCommandLineShell =
+    options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs);
+
+  toGNUCommandLine = {
+    # how to string-format the option name;
+    # by default one character is a short option (`-`),
+    # more than one characters a long option (`--`).
+    mkOptionName ?
+      k: if builtins.stringLength k == 1
+          then "-${k}"
+          else "--${k}",
+
+    # how to format a boolean value to a command list;
+    # by default it’s a flag option
+    # (only the option name if true, left out completely if false).
+    mkBool ? k: v: lib.optional v (mkOptionName k),
+
+    # how to format a list value to a command list;
+    # by default the option name is repeated for each value
+    # and `mkOption` is applied to the values themselves.
+    mkList ? k: v: lib.concatMap (mkOption k) v,
+
+    # how to format any remaining value to a command list;
+    # on the toplevel, booleans and lists are handled by `mkBool` and `mkList`,
+    # though they can still appear as values of a list.
+    # By default, everything is printed verbatim and complex types
+    # are forbidden (lists, attrsets, functions). `null` values are omitted.
+    mkOption ?
+      k: v: if v == null
+            then []
+            else [ (mkOptionName k) (lib.generators.mkValueStringDefault {} v) ]
+    }:
+    options:
+      let
+        render = k: v:
+          if      builtins.isBool v then mkBool k v
+          else if builtins.isList v then mkList k v
+          else mkOption k v;
+
+      in
+        builtins.concatLists (lib.mapAttrsToList render options);
+}