This extends the calling convention for nint in a non-breaking way: If the called script returns an attribute set instead of a string the following is done: * If the attributes `stdout` and/or `stderr` exist, their content (which must be a string currently) is written to the respective output. * If the attribute `exit` exists, nint will exit with the given exit code. Must be a number that can be converted to an `i32`. If it's missing, nint will exit without indicating an error. Change-Id: I209cf178fee3d970fdea3b26e4049e944af47457 Reviewed-on: https://cl.tvl.fyi/c/depot/+/3547 Tested-by: BuildkiteCI Reviewed-by: tazjin <mail@tazj.in>
		
			
				
	
	
		
			93 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # 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 must either be
 | |
| 
 | |
|   * A string which is rendered to `stdout`.
 | |
| 
 | |
|   * An attribute set with the following optional attributes:
 | |
| 
 | |
|     * `stdout`: A string that's rendered to `stdout`
 | |
|     * `stderr`: A string that's rendered to `stderr`
 | |
|     * `exit`: A number which is used as an exit code.
 | |
|       If missing, nint always exits with 0 (or equivalent).
 | |
| 
 | |
| ## 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"
 | |
| ```
 |