@thufschmitt drafted this set of proposals based on 2024-01-15 Nix team meeting minutes #115, and it was edited by maintainers. Posting it here to continue the discussion in the open.
This is a Wiki post that anyone can edit to add alternatives and considerations (or just fix typos)
#1: global --file
argument
Current semantics: If the command-line contains --file foo.nix
, then all the installables are interpreted as attribute paths in foo.nix
(+ auto-calling as needed).
Same for --expr someNixExpression
.
Advantages
- No change
- Lightweight when using several packages from the same file or expression (
--file '<nixpkgs>' hello gcc firefox
)
Drawbacks
- Doesnât allow mixing the source: If some installables come from a file/expr, then all the installables must come from that file/expr
- Not really intuitive
#2: âstatefulâ --file
and --flake
modifiers
--file foo.nix
on the command-line causes all the subsequent arguments to be interpreted as attribute paths in foo.nix
, until another option (--
-ed argument is encountered). Likewise for --expr someNixExpression
. A third flag --flake
is added for consistency and to negate the effect of a previous --file
or --expr
.
Advantages
- Partially backwards-compatible:
--file '<nixpkgs>' hello gcc firefox
keeps the same meaning - Rather terse in most cases
- Adds some symmetry between the flake and non-flake installables
- Can combine e.g.
--expr
and--flake
in one invocation. Could be relevant for possible--apply
or--let
flags (scripts)
Drawbacks
- Stateful cli parsing. Both annoying to implement and hard to reason about for the user (cf
find
)- @roberth: why?
- @fricklerhandwerk: Itâs actually fairly easy to implement and potential for confusion is low. Itâs even easy to document:
--<type> <source> [<attr>]...
where the sequence of attrs is terminated by--<flag>
or EOL
- The symmetry between flake and non-flake installables is only superficial because they are still handled quite differently
- @roberth: I suppose
--flake
uses the registry as its ârootâ,--expr
uses an expression as its root- @fricklerhandwerk: the registry is just a set of aliases for full flake references (which are the actual root), so not really different from channels if we finally abandon the global registry idea.
- @roberth: I suppose
#3: Double hash separator
Interprets foo.nix##hello
as getting the hello
attribute from the file foo.nix
.
Advantages
- Terse
- Puts the file installables (nearly) at the same level as flakes
Drawbacks
- Hard to discover and document
- Confusing (âwhy do I need one hash here and two there?â)
- Doesnât work for expr installables
#4: one-shot --file
modifier
Make --expr
a 2-arguments flag: --expr foo.nix hello
is the installable corresponding to the value at path hello
in foo.nix
(similar to #2, but allowing only a single attribute path).
Advantages
- Simple and stupid
- Partially compatible with the current behavior (similar to #2, but more restricted)
- Conservative choice: can be made more flexible later if deemed worth it
Drawbacks
- Verbose when getting several installables from a single file/expression
#5: URI-like prefixes
URI-like in the sense of having a âtypeâ, followed by a colon, followed by a payload of sorts. Attribute syntax is #
, except for expr:
, which uses the expression language for this purpose. expr:
can return multiple installables by returning a list.
Example: nix build expr:'(import ./. {}).foo' file:./docs.nix#docsHtml flake:nixpkgs#hello
Advantages
- Each argument is self-contained; parsing not dependent on preceding options
- No ambiguity as to whether e.g.
--expr
affects one or many upcoming args - Single strings are easy to pass around in bash, without breaking whitespace
- Also easy to accept them in options such as
--arg <name> <installable>
- File syntax can use
#
without ambiguity
Drawbacks
- Similarity to flakerefs might be confusing.
- Make them disjoint?
- e.g.
expr:
,nixfile:
,flake:
are not flakerefs
- e.g.
- Make them disjoint?
- Itâs yet another language within the command line arguments
Open questions
-
How will these interact with possible
--apply
/--let
flags? Currently--apply
is likebuiltins.map
, but that is not suitable for heterogenous inputs. Example use case: image generation with three inputs: a NixOS configuration, an image builder, and parameters for the image, such as disk size, format version, etc. -
Rename âinstallablesâ? Some arguments that we now call âinstallablesâ are arguably not installable. Examples: a flake, a store path thatâs a tarball file, a
.drv
file. Furthermore, âinstallableâ distorts the meaning of information retrieval commands that need precise meaning, such as path-info. We might want to name them for their role in the system, which is not as a âdomain objectâ but merely as an âapplicationâ syntax for referencing things.- Reference: We do have flakerefs, but there can also be references to other things
- Coordinate: For an unambiguous term (horizontal for dependency order, vertical for attributes)
- Source: Where something comes from.
- Source reference: A pointer to where something comes from
- Perhaps not input: too overloaded along with derivation inputs, flake inputs
Alternatively, we may want to use specialized terms that refer to the domain object type instead of their syntax, which then gives a clue about how the domain objects are automatically converted to match the commandâs expected type
- store paths
- packages
- expressions