Skip to content

add antiquotations to paths#5066

Merged
edolstra merged 6 commits intoNixOS:masterfrom
Radvendii:master
Sep 1, 2021
Merged

add antiquotations to paths#5066
edolstra merged 6 commits intoNixOS:masterfrom
Radvendii:master

Conversation

@Radvendii
Copy link
Contributor

@Radvendii Radvendii commented Jul 29, 2021

This enables you to write something like

let
   foo = "foo";
in
  ./${foo}/bar.nix

Without this one has to write

./. + "/${foo}/bar.nix"

Which is less ergonomic. The other intuitive approaches

"${./.}/${foo}/bar.nix"

and

./. + "/" + foo + "bar.nix"

Are semantically different, and usually not what one wants. Adding this syntax provides an obvious, and usually correct way of accessing paths that depend on a variable.

This also affects HPATHs e.g. ~/${foo}/bar

It does not affect SPATHs e.g. <nixpkgs/${foo}> is not valid, even with this PR.

I couldn't figure out any way to do SPATHs without changing the lex of things like 3<a.${foo}, which is currently a valid lex. In theory anything that ends in > would be an error anyways, but in order to find that out one needs to parse the whole expression, including arbitrary nix code in the antiquotation. Given that flakes don't support SPATHs anyways, this seems like a minor sacrifice.

This change shouldn't affect anything that currently passes the lexer. All the tests pass without modification, and the generated nixpkgs derivations are identical.

@Radvendii Radvendii marked this pull request as draft July 29, 2021 16:32
@Radvendii Radvendii marked this pull request as ready for review August 6, 2021 11:54
@edolstra
Copy link
Member

LGTM, can you add some documentation about this to doc/manual/src/expressions/language-values.md?

I don't think this changes the way any program would behave, but it's a
cleaner internal representation.
@Radvendii
Copy link
Contributor Author

The failure on ubuntu seems to be due to some unrelated issue with recursive nix and network connection? I could be misinterpreting that though.

@edolstra edolstra merged commit 7ee639f into NixOS:master Sep 1, 2021
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/tweag-nix-dev-update-17/15037/1

@cstrahan
Copy link
Contributor

cstrahan commented Mar 18, 2022

@Radvendii

Note that this assertion in the docs is wrong:

a.${foo}/b.${bar} is a syntactically valid division operation.

nix-repl> x = { foo = arg: arg; }

nix-repl> foo = "foo"

nix-repl> bar = "bar"

nix-repl> x.${foo}/x.${bar}
/x.bar

The x.${foo} gets parsed as an attribute selection, to which /x.${bar} (which evaluates as an /x.bar path) is applied.

This is actually how my https://github.com/cstrahan/tree-sitter-nix grammar parses this as well, so I don't really mind -- I think it's a reasonable parse, after all. I think it makes sense that the second /x. would be lexed as the start of a path -- trying to tweak the lexer and/or parser to treat this as division would be kinda gross, IMO.

I discovered this while adding another test case (inspired by the docs):

====================
division not mistaken for paths (2)
====================

a.${foo}/b.${bar}

---

(source_expression
    (binary
        (select
            (identifier)
            (attrpath
            (interpolation
                (identifier))))
        (select
            (identifier)
            (attrpath
            (interpolation
                (identifier))))))

turns out, the actual parse looks like:

(source_expression
    (app
        (select
            (identifier)
            (attrpath
            (interpolation
                (identifier))))
        (path
            (path_fragment)
            (interpolation
                (identifier)))))

@Radvendii
Copy link
Contributor Author

@cstrahan Oh, you're totally right. It doesn't get parsed as a single path, but it also does not get parsed as a division.

I'm not sure exactly how to clarify that in the docs without introducing more confusion.

Unfortunately, I think what makes the most sense is indeed to parse a.${foo}/b.${bar} as a single path, but this wouldn't be backwards compatible. I guess we could say that:

-    Antiquotation is supported in any paths except those in angle brackets.
-    `./${foo}-${bar}.nix` is a more convenient way of writing 
-    `./. + "/" + foo + "-" + bar + ".nix"` or `./. + "/${foo}-${bar}.nix"`. At
-    least one slash must appear *before* any antiquotations for this to be
-    recognized as a path. `a.${foo}/b.${bar}` is a syntactically valid division
-    operation. `./a.${foo}/b.${bar}` is a path.
+    Antiquotation is supported in any paths except those in angle brackets.
+    `./${foo}-${bar}.nix` is a more convenient way of writing 
+    `./. + "/" + foo + "-" + bar + ".nix"` or `./. + "/${foo}-${bar}.nix"`. At
+    least one slash must appear *before* any antiquotations for this to be
+    recognized as a path. For backward compatibility, `a.${foo}/bar` is 
+    parsed as `a.${foo}` applied to the path `/bar`. To make a single path,
+    you can always prepend a slash: `/a.${foo}/bar`.

tvlbot pushed a commit to tvlfyi/nix that referenced this pull request Jan 6, 2026
Based on <NixOS#5066>.

Change-Id: I28757321e19e51a2d9fa1df85897e67eee63aabe
Reviewed-on: https://cl.tvl.fyi/c/depot/+/13922
Autosubmit: sterni <[email protected]>
Reviewed-by: tazjin <[email protected]>
Tested-by: BuildkiteCI
tvlbot pushed a commit to tvlfyi/nix that referenced this pull request Jan 6, 2026
From <NixOS#5066>.

Change-Id: I165a6a8301363fca0e25162786914ef989032e62
Reviewed-on: https://cl.tvl.fyi/c/depot/+/13923
Autosubmit: sterni <[email protected]>
Tested-by: BuildkiteCI
Reviewed-by: tazjin <[email protected]>
tvlbot pushed a commit to tvlfyi/nix that referenced this pull request Jan 6, 2026
I don't think this changes the way any program would behave, but it's a
cleaner internal representation.

From <NixOS#5066>.

Change-Id: Ifd8c4346b478b06f11e7cd27b89eba975d2a8b9e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/13924
Tested-by: BuildkiteCI
Autosubmit: sterni <[email protected]>
Reviewed-by: tazjin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants