nushell: $env does not apply in some situations where it should

Describe the bug

The following snippet is expected to set $env.config.table.mode = none for the scope of the do block:

# either this
do { $env.config.table.mode = none; ls }

# or this
with-env {config: {table: {mode: none}}} { ls }

In practice ls here is not working as expected, it does not use the ‘none’ configuration.

Replacing ls with print (ls) does print the expected results, but I don’t understand why.

Replacing ls with echo $env.config.table.mode does print the expected result (none).

In addition, but not exactly related: The output of table --help for table --list does not tell you where/how you can use the results from table --list. Especially since I just wanted to test it ad-hoc and not actually change my config.nu (The mode setting there looks pretty obvious, but I didn’t even look there)

How to reproduce

  1. Run do { $env.config.table.mode = none; ls }
  2. See the outputted table is not shown in the expected mode/theme.

Expected behavior

I expect nu to use the set configuration inside the do block.

Screenshots

No response

Configuration

key value
version 0.84.0
branch
commit_hash
build_os linux-x86_64
build_target x86_64-unknown-linux-gnu
rust_version rustc 1.71.0 (8ede3aae2 2023-07-12)
rust_channel stable-x86_64-unknown-linux-gnu
cargo_version cargo 1.71.0 (cfd3bbd8f 2023-06-08)
build_time 2023-08-26 17:04:51 +03:00
build_rust_channel release
allocator standard
features default, sqlite, trash, which, zip
installed_plugins

Additional context

No response

About this issue

  • Original URL
  • State: closed
  • Created 10 months ago
  • Comments: 23 (16 by maintainers)

Most upvoted comments

No worries @JordanllHarper. I unassigned you. Thanks for trying!

OK, let’s close this. The get_config() or changing the config in general are other topics.

Alright, this is not as simple as it seems. Commands in nushell don’t print things to stdout, like in other shells; they’re just functions and all they do return is data. The data itself is only printed to stdout when it reaches the repl, so something like.

do { ls; ls; ls; () } 

Won’t actually print anything, as the return of the do statement is (), and the ls commands are just being unused.

This behavior of nushell manifests itself in do { $env.config.table.mode = none; ls }, because the ls command is not really printing anything, just returning the data. The table command runs after the closure finishes executing and after the do returns, so by the time the implicit table command executes, the environment variable no longer exists. This is not exactly a bug, just something very non intuitive. As a workaround, one can do something like

do { $env.config.table.mode = none; ls | table }

which will convert the ls data to a table string while the environment variable is still set, returning the expected output.

I think the best thing to do in this situation is to document this ‘gotcha’ in the Pipelines section of the nushell book.

Would a PR documenting this note be welcome?

After some debugging I’m starting to suspect that the display_output hook is just not honoring any $env modifications, I’ll confirm it once I get home

Okay been giving this a go and I can’t find the issue with this. I think it might be something to do with the do command but as a newcomer to the project I can’t be sure. Wondering if I can pass this on to someone else?