Skip to content

Commit

Permalink
Fix nushell with --nom, make shell bits templated (#62)
Browse files Browse the repository at this point in the history
The nu template uses the executable very differently from others, so it
ends up trying weird things like `which nix-your-shell --nom`, which
fails because `which` doesn't understand `--nom`.

The other shell templates are also broken as shell _scripts_, because
they rely on the `nix-your-shell` -> `nix-your-shell $shell`
substitution.

Fix everything by using a real template engine.
  • Loading branch information
K900 authored Mar 18, 2024
1 parent f2af0f9 commit 6265214
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 37 deletions.
40 changes: 40 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ calm_io = "0.1.1"
camino = "1.1.4"
clap = { version = "4.3.4", features = ["derive", "wrap_help", "env"] }
color-eyre = "0.6.2"
minijinja = { version = "1.0.12", features = ["json"] }
shell-words = "1.1.0"
tracing = { version = "0.1.39", features = ["attributes"] }
tracing-subscriber = { version = "0.3.17", features = ["env-filter", "registry"] }
Expand Down
4 changes: 2 additions & 2 deletions data/env.fish → data/env.fish.j2
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
# nix-your-shell | source

function nix-shell --description "Start an interactive shell based on a Nix expression"
nix-your-shell nix-shell -- $argv
{{ executable }} {{ extra_args | join(" ") }} fish nix-shell -- $argv
end

function nix --description "Reproducible and declarative configuration management"
nix-your-shell nix -- $argv
{{ executable }} {{ extra_args | join(" ") }} fish nix -- $argv
end
9 changes: 7 additions & 2 deletions data/env.nu → data/env.nu.j2
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
# nix-your-shell nu | save nix-your-shell.nu

def _nix_your_shell (command: string, args: list<string>) {
if not (which nix-your-shell | is-empty) {
if not (which {{ executable }} | is-empty) {
{%- if extra_args %}
{#- If you squint hard enough, JSON lists are just Nu lists #}
let args = {{ extra_args | tojson }} ++ ["--"] ++ $args
{%- else %}
let args = ["--"] ++ $args
run-external nix-your-shell $command ...$args
{%- endif %}
run-external {{ executable }} $command ...$args
} else {
run-external $command ...$args
}
Expand Down
4 changes: 2 additions & 2 deletions data/env.sh → data/env.sh.j2
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
# nix-your-shell | source /dev/stdin

function nix-shell () {
nix-your-shell nix-shell -- "$@"
{{ executable }} {{ extra_args | join(" ") }} {{ shell }} nix-shell -- "$@"
}

function nix () {
nix-your-shell nix -- "$@"
{{ executable }} {{ extra_args | join(" ") }} {{ shell }} nix -- "$@"
}
5 changes: 0 additions & 5 deletions data/env.xsh

This file was deleted.

5 changes: 5 additions & 0 deletions data/env.xsh.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# If you see this output, you probably forgot to pipe it into `source`:
# nix-your-shell | source

aliases['nix-shell'] = '{{ executable }} {{ extra_args | join(" ") }} xonsh nix-shell -- @($args)'
aliases['nix'] = '{{ executable }} {{ extra_args | join(" ") }} xonsh nix -- @($args)'
44 changes: 18 additions & 26 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,21 @@ fn main() -> eyre::Result<()> {

match opts.command.unwrap_or_default() {
Command::Env => {
let mut shell_code = match shell.kind {
let template = match shell.kind {
ShellKind::Zsh | ShellKind::Bash => {
include_str!("../data/env.sh")
include_str!("../data/env.sh.j2")
}

ShellKind::Fish => {
include_str!("../data/env.fish")
include_str!("../data/env.fish.j2")
}

ShellKind::Nushell => {
include_str!("../data/env.nu")
include_str!("../data/env.nu.j2")
}

ShellKind::Xonsh => {
include_str!("../data/env.xsh")
include_str!("../data/env.xsh.j2")
}

ShellKind::Other(shell) => {
Expand All @@ -116,31 +116,23 @@ fn main() -> eyre::Result<()> {
))
.note("Supported shells are: `zsh`, `fish`, `nushell`, `xonsh`, and `bash`")
}
}
.to_owned();

// Do some string replacements to reflect the arguments passed to `nix-your-shell` in
// the generated code.
//
// We could make this a bit "cleaner" with an actual templating language, but it's nice
// that the snippets in `../data/` are valid code and not templates.

let mut shell_args = shell_words::quote(shell.path.as_str());

if opts.nom {
shell_args += " --nom";
}

shell_code =
shell_code.replace("nix-your-shell", &format!("nix-your-shell {}", shell_args));
};

let current_exe =
current_exe().wrap_err("Unable to determine absolute path of `nix-your-shell`")?;
if opts.absolute || !executable_is_on_path(&current_exe)? {
shell_code = shell_code.replace("nix-your-shell", current_exe.as_str());
}

let _ = println!("{shell_code}");
let formatted = minijinja::render!(
template,
executable => if opts.absolute || !executable_is_on_path(&current_exe)? {
current_exe.as_str()
} else {
"nix-your-shell"
},
extra_args => if opts.nom { vec!["--nom"] } else { vec![] },
shell => shell.path.as_str(),
);

let _ = println!("{formatted}");
Ok(())
}

Expand Down

0 comments on commit 6265214

Please sign in to comment.