diff options
Diffstat (limited to 'users/sterni/nint')
-rw-r--r-- | users/sterni/nint/README.md | 85 | ||||
-rw-r--r-- | users/sterni/nint/default.nix | 14 | ||||
-rw-r--r-- | users/sterni/nint/nint.rs | 110 |
3 files changed, 0 insertions, 209 deletions
diff --git a/users/sterni/nint/README.md b/users/sterni/nint/README.md deleted file mode 100644 index ddd8045f7378..000000000000 --- a/users/sterni/nint/README.md +++ /dev/null @@ -1,85 +0,0 @@ -# nint — Nix INTerpreter - -`nint` is a shebang compatible interpreter for nix. It is currently -implemented as a fairly trivial wrapper around `nix-instantiate --eval`. -It allows to run nix expressions as command line tools if they conform -to the following calling convention: - -* Every nix script needs to evaluate to a function which takes an - attribute set as its single argument. Ideally a set pattern with - an ellipsis should be used. By default `nint` passes the following - arguments: - - * `currentDir`: the current working directory as a nix path - * `argv`: a list of arguments to the invokation including the - program name at `builtins.head argv`. - * Extra arguments can be manually passed as described below. - -* The return value should always be a string (throwing is also okay) - which is printed to stdout by `nint`. - -## Usage - -``` -nint [ --arg ARG VALUE … ] script.nix [ ARGS … ] -``` - -Instead of `--arg`, `--argstr` can also be used. They both work -like the flags of the same name for `nix-instantiate` and may -be specified any number of times as long as they are passed -*before* the nix expression to run. - -Below is a shebang which also passes `depot` as an argument -(note the usage of `env -S` to get around the shebang limitation -to two arguments). - -```nix -#!/usr/bin/env -S nint --arg depot /path/to/depot -``` - -## Limitations - -* No side effects except for writing to `stdout`. - -* Output is not streaming, i. e. even if the output is incrementally - calculated, nothing will be printed until the full output is available. - With plain nix strings we can't do better anyways. - -* Limited error handling for the script, no way to set the exit code etc. - -Some of these limitations may be possible to address in the future by using -an alternative nix interpreter and a more elaborate calling convention. - -## Example - -Below is a (very simple) implementation of a `ls(1)`-like program in nix: - -```nix -#!/usr/bin/env nint -{ currentDir, argv, ... }: - -let - lib = import <nixpkgs/lib>; - - dirs = - let - args = builtins.tail argv; - in - if args == [] - then [ currentDir ] - else args; - - makeAbsolute = p: - if builtins.isPath p - then p - else if builtins.match "^/.*" p != null - then p - else "${toString currentDir}/${p}"; -in - - lib.concatStringsSep "\n" - (lib.flatten - (builtins.map - (d: (builtins.attrNames (builtins.readDir (makeAbsolute d)))) - dirs)) + "\n" -``` diff --git a/users/sterni/nint/default.nix b/users/sterni/nint/default.nix deleted file mode 100644 index 5cf83d15d6f3..000000000000 --- a/users/sterni/nint/default.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ depot, pkgs, ... }: - -let - inherit (depot.nix.writers) - rustSimpleBin - ; -in - - rustSimpleBin { - name = "nint"; - dependencies = [ - depot.third_party.rust-crates.serde_json - ]; - } (builtins.readFile ./nint.rs) diff --git a/users/sterni/nint/nint.rs b/users/sterni/nint/nint.rs deleted file mode 100644 index 3d430612851a..000000000000 --- a/users/sterni/nint/nint.rs +++ /dev/null @@ -1,110 +0,0 @@ -extern crate serde_json; - -use serde_json::Value; -use std::ffi::OsString; -use std::os::unix::ffi::{OsStringExt, OsStrExt}; -use std::io::{Error, ErrorKind, Write}; -use std::process::Command; - -fn render_nix_string(s: &OsString) -> OsString { - let mut rendered = Vec::new(); - - rendered.extend(b"\""); - - for b in s.as_os_str().as_bytes() { - match char::from(*b) { - '\"' => rendered.extend(b"\\\""), - '\\' => rendered.extend(b"\\\\"), - '$' => rendered.extend(b"\\$"), - _ => rendered.push(*b), - } - } - - rendered.extend(b"\""); - - OsString::from_vec(rendered) -} - -fn render_nix_list(arr: &[OsString]) -> OsString { - let mut rendered = Vec::new(); - - rendered.extend(b"[ "); - - for el in arr { - rendered.extend(render_nix_string(el).as_os_str().as_bytes()); - rendered.extend(b" "); - } - - rendered.extend(b"]"); - - OsString::from_vec(rendered) -} - -fn main() -> std::io::Result<()> { - let mut nix_args = Vec::new(); - - let mut args = std::env::args_os().into_iter(); - let mut in_args = true; - - let mut argv: Vec<OsString> = Vec::new(); - - // skip argv[0] - args.next(); - - loop { - let arg = match args.next() { - Some(a) => a, - None => break, - }; - - if !arg.to_str().map(|s| s.starts_with("-")).unwrap_or(false) { - in_args = false; - } - - if in_args { - match(arg.to_str()) { - Some("--arg") | Some("--argstr") => { - nix_args.push(arg); - nix_args.push(args.next().unwrap()); - nix_args.push(args.next().unwrap()); - Ok(()) - } - _ => Err(Error::new(ErrorKind::Other, "unknown argument")), - }? - } else { - argv.push(arg); - } - } - - if argv.len() < 1 { - Err(Error::new(ErrorKind::Other, "missing argv")) - } else { - let cd = std::env::current_dir()?.into_os_string(); - - nix_args.push(OsString::from("--arg")); - nix_args.push(OsString::from("currentDir")); - nix_args.push(cd); - - nix_args.push(OsString::from("--arg")); - nix_args.push(OsString::from("argv")); - nix_args.push(render_nix_list(&argv[..])); - - nix_args.push(OsString::from("--eval")); - nix_args.push(OsString::from("--json")); - - nix_args.push(argv[0].clone()); - - let run = Command::new("nix-instantiate") - .args(nix_args) - .output()?; - - match serde_json::from_slice(&run.stdout[..]) { - Ok(Value::String(s)) => Ok(print!("{}", s)), - Ok(_) => Err(Error::new(ErrorKind::Other, "output must be a string")), - _ => { - std::io::stderr().write_all(&run.stderr[..]); - Err(Error::new(ErrorKind::Other, "internal nix error")) - }, - } - } -} |