Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve path value documentation #10560

Merged
merged 3 commits into from
May 6, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
57 changes: 34 additions & 23 deletions doc/manual/src/language/values.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,39 +92,50 @@

- <a id="type-path" href="#type-path">Path</a>

*Paths*, e.g., `/bin/sh` or `./builder.sh`. A path must contain at
least one slash to be recognised as such. For instance, `builder.sh`
is not a path: it's parsed as an expression that selects the
attribute `sh` from the variable `builder`. If the file name is
relative, i.e., if it does not begin with a slash, it is made
absolute at parse time relative to the [base directory](@docroot@/glossary.md#gloss-base-directory).
For instance, if a Nix expression in
`/foo/bar/bla.nix` refers to `../xyzzy/fnord.nix`, the absolute path
is `/foo/xyzzy/fnord.nix`.

If the first component of a path is a `~`, it is interpreted as if
the rest of the path were relative to the user's home directory.
e.g. `~/foo` would be equivalent to `/home/edolstra/foo` for a user
whose home directory is `/home/edolstra`.

For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` in the base directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.

Note that the Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
*Paths* are distinct from strings and can be expressed by path literals such as `./builder.sh`.

Paths are suitable for referring to local files, and are often preferable over strings.
- Path values do not contain trailing slashes, `.` and `..`, as they are resolved when evaluating a path literal.
- Path literals are automatically resolved relative to their [base directory](@docroot@/glossary.md#gloss-base-directory).
- The files referred to by path values are automatically copied into the Nix store when used in a string interpolation or concatenation.
- Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.

This is hypothetical from the perspective of the Nix language

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users really do get to enjoy autocompletion in the repl already.

I don't know, should I be writing a guide "How to pick a Nix value representation for local files"?
That'd be quite absurd.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this one's low impact, feel free to ignore then.


A path literal must contain at least one slash to be recognised as such.
For instance, `builder.sh` is not a path:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

@roberth roberth Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would disrupt the flow for something that isn't even an example of a path.
Worse, when scanning the text, "Example: builder.sh" under Paths, that would suggest that it is a path.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I'm generally skeptical of this conversational tone that meanders between facts and counterfactuals. It would take me way too much time to unravel this with concrete suggestions for that text, so I don't know. See the other comment on using parts from nix.dev.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, let's postpone that then.

it's parsed as an expression that selects the attribute `sh` from the variable `builder`.

Path literals may also refer to absolute paths by starting with a slash.

> **Note**
>
> Absolute paths make expressions less portable.
> In the case where a function translates a path literal into an absolute path string for a configuration file, it is recommended to write a string literal instead.
> This avoids some confusion about whether files at that location will be used during evaluation.
> It also avoids unintentional situations where some function might try to copy everything at the location into the store.

If the first component of a path is a `~`, it is interpreted such that the rest of the path were relative to the user's home directory.
For example, `~/foo` would be equivalent to `/home/edolstra/foo` for a user whose home directory is `/home/edolstra`.
Path literals that start with `~` are not allowed in [pure](@docroot@/command-ref/conf-file.md#conf-pure-eval) evaluation.

Paths can be used in [string interpolation] and string concatenation.
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` from the same directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.

Note that the Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make a proper highlight

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What makes a highlight proper?
Note that this was in the original text.

For example, assume you used a file path in an interpolated string during a `nix repl` session.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make a proper example

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not rewriting everything, sorry.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewriting everything blows up the scope of the PR.
Our priority should be to get improvements merged.

Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents.
Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents. Use `:r` to reset the repl as needed.

[store path]: @docroot@/glossary.md#gloss-store-path

Paths can include [string interpolation] and can themselves be [interpolated in other expressions].
Path literals can also include [string interpolation], besides being [interpolated into other expressions].

[interpolated in other expressions]: ./string-interpolation.md#interpolated-expressions
[interpolated into other expressions]: ./string-interpolation.md#interpolated-expressions

At least one slash (`/`) must appear *before* any interpolated expression for the result to be recognized as a path.

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

[Lookup paths](./constructs/lookup-path.md) such as `<nixpkgs>` resolve to path values.
[Lookup path](./constructs/lookup-path.md) literals such as `<nixpkgs>` also resolve to path values.

- <a id="type-boolean" href="#type-boolean">Boolean</a>

Expand Down