Skip to content

Add parse-time constant $NU_CURRENT_FILE #14305

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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

Bahex
Copy link
Contributor

@Bahex Bahex commented Nov 11, 2024

Addresses

The other approach:

Description

Adds $NU_CURRENT_FILE, a parse-time constant that is the absolute path of the source file containing it.

  • Useful for any script or module that makes use of non nuscript files.
  • Removes the need for $env.CURRENT_FILE and $env.FILE_PWD.
  • Can be used in modules, sourced files or scripts.
  • Requires changes in the parser

Examples

The following example is written with the assumption that path expand can not run during parse-time.

# ~/.config/nushell/scripts/foo.nu
const paths = {
    self: $NU_CURRENT_FILE,
    dir: ($NU_CURRENT_FILE | path dirname),
    sibling: ($NU_CURRENT_FILE | path basename -r "sibling")
    parent_dir: ($NU_CURRENT_FILE | path dirname --num-levels 2)
    cousin: ($NU_CURRENT_FILE | path dirname --num-levels 2 | path join "cousin")
}

export def main [] {
    $paths
}
> use foo.nu
> foo
╭────────────┬────────────────────────────────────────────╮
 self        /home/user/.config/nushell/scripts/foo.nu  
 dir         /home/user/.config/nushell/scripts         
 sibling     /home/user/.config/nushell/scripts/sibling 
 parent_dir  /home/user/.config/nushell                 
 cousin      /home/user/.config/nushell/cousin          
╰────────────┴────────────────────────────────────────────╯

Comparison with #14303

Pros

  • More intuitive, easier to understand at a glance and similar to the existing $env.CURRENT_FILE

Cons

  • Requires changes in the parser
  • Small scoping issues, as there is no way to un-define a variable or constant, other than overwriting it with null.

@sholderbach sholderbach added the const-eval Evaluation of const expressions at parse time if possible label Nov 11, 2024
@Bahex Bahex force-pushed the const-current-file branch from d2f709f to 8cf2f9b Compare November 17, 2024 11:03
@amtoine
Copy link
Member

amtoine commented Nov 20, 2024

an early review, i would make that constant upper case, i.e. $CURRENT_FILE, that's more the convention we have in Nushell so far afaik 😉

@kubouch
Copy link
Contributor

kubouch commented Nov 20, 2024

Maybe it would be better to name it NU_CURRENT_FILE to denote it's coming from Nushell.

@kubouch
Copy link
Contributor

kubouch commented Nov 20, 2024

Implementation seems good, could you add some tests for it? E.g., test that the file is set correctly in source/use/overlay use and also recovers

@132ikl
Copy link
Member

132ikl commented Nov 20, 2024

What about $nu.current-file instead of $current_file/$CURRENT_FILE? It seems similar to $nu.current-exe, and makes sense to put it there to me.

Edit: note from @devyn regarding this:

$nu is a real record value so I would probably not do that for every file idk
Every file would need a new value for $nu

@Bahex Bahex force-pushed the const-current-file branch from 8cf2f9b to 56e2261 Compare December 6, 2024 07:08
@Bahex Bahex changed the title Add parse-time constant $current_file Add parse-time constant $NU_CURRENT_FILE Dec 6, 2024
@Bahex
Copy link
Contributor Author

Bahex commented Dec 6, 2024

Renamed as suggested.

fdncred added a commit that referenced this pull request Dec 6, 2024
…time (#14303)

Alternative solution to:
- #12195 

The other approach:
- #14305

# Description
Adds ~`path const`~ `path self`, a parse-time only command for getting
the absolute path of the source file containing it, or any file relative
to the source file.

- Useful for any script or module that makes use of non nuscript files.
- Removes the need for `$env.CURRENT_FILE` and `$env.FILE_PWD`.
- Can be used in modules, sourced files or scripts.

# Examples

```nushell
# ~/.config/nushell/scripts/foo.nu
const paths = {
    self: (path self),
    dir: (path self .),
    sibling: (path self sibling),
    parent_dir: (path self ..),
    cousin: (path self ../cousin),
}

export def main [] {
    $paths
}
```

```nushell
> use foo.nu
> foo
╭────────────┬────────────────────────────────────────────╮
│ self       │ /home/user/.config/nushell/scripts/foo.nu  │
│ dir        │ /home/user/.config/nushell/scripts         │
│ sibling    │ /home/user/.config/nushell/scripts/sibling │
│ parent_dir │ /home/user/.config/nushell                 │
│ cousin     │ /home/user/.config/nushell/cousin          │
╰────────────┴────────────────────────────────────────────╯
```


Trying to run in a non-const context
```nushell
> path self
Error:   × this command can only run during parse-time
   ╭─[entry #1:1:1]
 1 │ path self 
   · ─────┬────
   ·      ╰── can't run after parse-time
   ╰────
  help: try assigning this command's output to a const variable
```

Trying to run in the REPL i.e. not in a file
```nushell
> const foo = path self
Error:   × Error: nu:🐚:file_not_found
  │ 
  │   × File not found
  │    ╭─[entry #3:1:13]
  │  1 │ const foo = path self
  │    ·             ─────┬────
  │    ·                  ╰── Couldn't find current file
  │    ╰────
  │ 
   ╭─[entry #3:1:13]
 1 │ const foo = path self
   ·             ─────┬────
   ·                  ╰── Encountered error during parse-time evaluation
   ╰────
```

# Comparison with #14305
## Pros
- Self contained implementation, does not require changes in the parser.
- More concise usage, especially with parent directories.

---------

Co-authored-by: Darren Schroeder <[email protected]>
@Bahex Bahex force-pushed the const-current-file branch from 56e2261 to 6fdfa70 Compare December 7, 2024 16:11
@kubouch
Copy link
Contributor

kubouch commented Dec 8, 2024

I think you can implement it easily by tracking where working_set.files.push/pop is used and set the const NU_CURRENT_FILE at those places. You could even make a helper that pushes/pops to the working_set.files and sets NU_CURRENT_FILE at the same time.

In the current version, the NU_CURRENT_FILE is not recovered after parsing a module block, and it's not necessary to set it for every block, like you do in parse_block().

@Bahex
Copy link
Contributor Author

Bahex commented Dec 11, 2024

Closing this, as path self makes this redundant.

Also bindings that don't follow the existing scoping rules and are scoped only to files (regardless of sourcing/importing) are pretty hard to do cleanly.

@Bahex Bahex closed this Dec 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
const-eval Evaluation of const expressions at parse time if possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants