Skip to content

Commit

Permalink
Support custom shell in nix-shell/nix run
Browse files Browse the repository at this point in the history
* Use `$NIX_SHELL_INTERACTIVE_SHELL` (if present) as interactive shell for `nix-shell`
* Use `$NIX_RUN_INTERACTIVE_SHELL` (if present) as interactive shell for `nix run`

If `--run`, `--command` or `-c` are given, then bash is still used.

One could also consider those environment variables to be arbitrary
default commands that are executed when `nix-shell`/`nix run` are ran
interactive and without a command. However, I think the most common
use case (by far) is to set them to a shell, hence the name
`[...]_INTERACTIVE_SHELL`.

Tests:

I was unsuccessful adding tests to *tests/nix-shell.sh*. Any
non-interactive test doesn't trigger the feature since it's only
triggered in interactive shells.

Previous work:

Issue #419 (nix-shell ignoring SHELL enviroment variable) proposed to
use `$SHELL` as interactive shell for `nix-shell`. This is of course
not desirable if people depend on `nix-shell` always using bash. With
this change however, the feature is optional since it uses previously
unused environment variables.
  • Loading branch information
haslersn committed Feb 16, 2019
1 parent e58a714 commit 19d1ef5
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 4 deletions.
6 changes: 5 additions & 1 deletion doc/manual/command-ref/nix-shell.xml
Expand Up @@ -109,7 +109,11 @@ also <xref linkend="sec-common-options" />.</phrase></para>
<literal>return</literal> at the end; e.g. <literal>--command
"echo Hello; return"</literal> will print <literal>Hello</literal>
and then drop you into the interactive shell. This can be useful
for doing any additional initialisation.</para></listitem>
for doing any additional initialisation. If ran interactive and
none of <option>--run</option> and <option>--command</option> are
used but <envar>NIX_SHELL_INTERACTIVE_SHELL</envar> is set, then
<literal>--command "$NIX_SHELL_INTERACTIVE_SHELL"</literal> is
implied.</para></listitem>

</varlistentry>

Expand Down
6 changes: 5 additions & 1 deletion src/nix-build/nix-build.cc
Expand Up @@ -113,6 +113,7 @@ static void _main(int argc, char * * argv)
if (std::regex_search(lines.front(), std::regex("^#!"))) {
lines.pop_front();
inShebang = true;
interactive = false;
for (int i = 2; i < argc; ++i)
savedArgs.push_back(argv[i]);
args.clear();
Expand Down Expand Up @@ -193,7 +194,6 @@ static void _main(int argc, char * * argv)

else if (inShebang && *arg == "-i") {
auto interpreter = getArg(*arg, arg, end);
interactive = false;
auto execArgs = "";

// Überhack to support Perl. Perl examines the shebang and
Expand Down Expand Up @@ -403,6 +403,10 @@ static void _main(int argc, char * * argv)

restoreAffinity();

if (interactive && envCommand.empty()) {
envCommand = "[ ! -z \"$NIX_SHELL_INTERACTIVE_SHELL\" ] && \"$NIX_SHELL_INTERACTIVE_SHELL\"\nexit";
}

/* Run a shell using the derivation's environment. For
convenience, source $stdenv/setup to setup additional
environment variables and shell functions. Also don't
Expand Down
10 changes: 8 additions & 2 deletions src/nix/run.cc
Expand Up @@ -21,7 +21,7 @@ std::string chrootHelperName = "__run_in_chroot";

struct CmdRun : InstallablesCommand
{
std::vector<std::string> command = { "bash" };
std::vector<std::string> command;
StringSet keep, unset;
bool ignoreEnvironment = false;

Expand All @@ -30,7 +30,8 @@ struct CmdRun : InstallablesCommand
mkFlag()
.longName("command")
.shortName('c')
.description("command and arguments to be executed; defaults to 'bash'")
.description("command and arguments to be executed; defaults to "
"\"$NIX_RUN_INTERACTIVE_SHELL\" if set, otherwise to 'bash'")
.labels({"command", "args"})
.arity(ArityAny)
.handler([&](std::vector<std::string> ss) {
Expand Down Expand Up @@ -147,6 +148,11 @@ struct CmdRun : InstallablesCommand

setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1);

if (command.empty()) {
auto interactiveShell = getenv("NIX_RUN_INTERACTIVE_SHELL");
command = { interactiveShell ? interactiveShell : "bash" };
}

std::string cmd = *command.begin();
Strings args;
for (auto & arg : command) args.push_back(arg);
Expand Down

0 comments on commit 19d1ef5

Please sign in to comment.