NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
12.29k stars 1.48k forks source link

Straightforward way to determine if inside a `nix shell` #6677

Open Benjamin-L opened 2 years ago

Benjamin-L commented 2 years ago

When using nix shell, there is no indication available to the shell environment that it is a shell. This results in poor UX, where I have to remember whether or not I've invoked nix shell in a given terminal, and if so, which packages I added.

The should, at the very least, be an environment variable like the old IN_NIX_SHELL for nix-shell. Ideally, I'd like some variant on IN_NIX_SHELL as well as something like NIX_SHELL_PACKAGES. With these, users can configure their shells to display this information as part of the prompt.

The older nix-shell command messed with the shell prompt directly. I'm not really a fan of that approach though, since it gives no flexibility to the user in how they want the context information to be displayed, and destroys any additional prompt configuration that the user has.


It's also totally possible that what I'm looking for already exists, and I just couldn't find documentation of it. If that's the case, sorry.

abathur commented 2 years ago

This is part of why I've kept my head in the sand on flakes and the new CLI. I put a bit of work into exposing this state in my prompt:

Screen Shot 2022-06-15 at 8 22 18 PM

From reading some past related discussions, I get the sense that the general concern is about keeping derivations and their builders and such from behaving differently:

I've wondered if it would be acceptable to just push more information about command invocation into the environment immediately before executing a --command or handing the shell over to the user. (I.e., instead of having some equivalent to IN_NIX_SHELL, storing the literal invocation so that we can tailor prompts and such as needed.

bjornfor commented 2 years ago

I sometimes nest nix shells (either nix-shell or nix shell), so I was thinking we could have a counter like $NIX_SHELL_LEVEL, similar to the standard $SHLVL.

jjant commented 1 year ago

Any updates on this?

mimoo commented 1 year ago

I'd be interested in this as well

gridbugs commented 1 year ago

Also interested in this!

MayRedwood commented 1 year ago

Also interested!

cumber commented 1 year ago

It'd be nice if there were a label for a shell available in a standard environment variable, too.

Shells you get from a nix develop almost always have $name that works reasonably well to identify the shell. I also use it to have different emacs daemons running in each shell (by setting the socketName) so they just automatically have the shell's $PATH available). But using $name like this feels a bit accidental, rather than intended.

If we had a standard NIX_SHELL_DESC (or whatever) variable, nix develop could put the name of the devShell or package in there (maybe with a standard prefix to disambiguate a nix shell with the same package), and nix shell could instead put the list of installables.

More complex cases like nix shell --expr <expr> or nix shell --file <path> would be a little trickier; maybe it's fine to just list the installables and put the --expr <expr> or --file <path> at the front, though it's likely to be getting a bit long for a prompt. Even just setting that variable to a default string would still mean you can use the presence of the variable to tell whether you're in a shell or not; maybe add a command-line option to override it so that users can explicitly provide a good label for shells that are too complex to auto-label. But I feel like nix develop and nix shell <handful of packages> are very common cases that it's relatively easy to come up with a useful label for.

nixos-discourse commented 1 year ago

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

https://discourse.nixos.org/t/custom-prompts-or-shell-depth-indicator-for-nix-shell-nix-develop/29942/1

eclairevoyant commented 10 months ago

@turbotimon -p and shell.nix are for nix-shell, not nix shell. And even otherwise it's offtopic here, this is discussing a specific requirement.

pmorch commented 5 months ago

The only times I run zsh (or bash) nested inside each other is for nix-shell, so I added this to my .zshrc so I can see the shell nesting depth:

if [ "$SHLVL" = 1 ] ; then
    SHELL_NESTING_DEPTH_STRING=""
else
    SHELL_NESTING_DEPTH_STRING="[$SHLVL]"
fi
# use PS1 instead of PROMPT for bash
export PROMPT='bla.bla'${SHELL_DEPTH_STRING}'bla.bla '
unset SHELL_DEPTH_STRING
nickkadutskyi commented 5 months ago

I am using these functions in zsh and in p10k prompt to show info related to Shell level, nix shell or nix develop shells or direnv applied environment:

  # Show Shell Level
  function prompt_shell_level() {
    if [[ $SHLVL -gt 1 ]]; then
      p10k segment -i '⚡' -f yellow -t "$SHLVL"
    fi
  }

  # Show If In Nix Shell
  function prompt_in_nix_shell() {
    if echo "$PATH" | grep -qc '/nix/store'; then
      p10k segment -i '📦' -f yellow -t "nix"
    fi
  }

  # Show Nix Development Shell Name
  function prompt_nix_dev_shell_name() {
    if [[ -n $IN_NIX_SHELL ]]; then
      p10k segment -i '📦' -f yellow -t $name
    fi
  }

  # Show if Direnv Active
  function prompt_in_direnv() {
    if [[ -n $DIRENV_ACTIVE ]]; then
      p10k segment -i '📂' -f yellow -t "direnv"
    fi
  }
satk0 commented 3 weeks ago

Yo Nixers, before I go to sleep, you can add this to your .bashrc to show you shell lvl separated by ":" before username:

PS1="${PS1//\\u/"$SHLVL:\\u"}"

It will make your bash terminal prompt look e.g. like this:

[2:satk0@nixos:/path/to/some/dir]$

, where 2 at the beginning is a shell lvl.