Skip to content

Resolve shell dynamically instead of hardcoding a NixOS store path - #1

Open
yottanami wants to merge 2 commits into
masterfrom
agent/18-fish-shell-path
Open

Resolve shell dynamically instead of hardcoding a NixOS store path#1
yottanami wants to merge 2 commits into
masterfrom
agent/18-fish-shell-path

Conversation

@yottanami

@yottanami yottanami commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Summary

explicit-shell-file-name was hardcoded to /run/current-system/sw/bin/fish in plugins/editor/core.el, a NixOS-only path, and fish isn't even in this package's own Nix closure (nix/package.nix's runtimeTools). Breaks M-x shell on any non-NixOS system, including a plain nix run elsewhere.

The rest of the package wires Nix-provided binaries in via PATH (nix/package.nix's makeWrapper + --prefix PATH), not baked-in store paths, so this resolves the shell the same idiomatic way instead of hardcoding a different path: prefer fish if it's actually on PATH (e.g. if someone adds it via extraRuntimeInputs), fall back to $SHELL (treating an empty-but-set $SHELL as unset, since that's non-nil/truthy in elisp), then bash, then /bin/sh.

Notes

Nix and Emacs are both available in this environment now, so this was actually run, not just read.

Test plan

  • nix flake check --no-build: all checks pass.
  • nix build .#noteditor: builds clean.
  • Ran the built ./result/bin/noteditor --batch and printed explicit-shell-file-name after init: resolves to /bin/bash, matching this environment's $SHELL. Confirms the fix works in the actual packaged product, not just an isolated snippet.
  • Ran the actual (or (executable-find "fish") ...) fallback chain in a real emacs --batch process across all four branches:
    • fish on PATH -> resolves to the fish store path.
    • normal $SHELL set, no fish -> resolves to $SHELL.
    • $SHELL="" (empty but set), no fish -> resolves to bash via executable-find (this caught a real bug in the first version of this fix: an empty string is non-nil in elisp, so a plain (getenv "SHELL") in the or chain accepted "" and skipped the bash/sh fallbacks entirely, leaving explicit-shell-file-name empty; fixed by treating empty as unset).
    • $SHELL truly unset, no fish -> resolves to bash via executable-find.
  • grep -rn "/run/current-system" --include="*.el" .: no hardcoded NixOS store paths remain anywhere in the elisp tree.

Closes Men-in-Black-5/ideas#18

@yottanami

Copy link
Copy Markdown
Owner Author

Reviewed. The change itself looks correct and well-scoped:

  • Balanced parens verified programmatically (not just eyeballed) across the whole file.
  • fish genuinely isn't referenced anywhere else in the repo — matches the "not in this package's Nix closure" claim.
  • No /run/current-system/... paths remain anywhere in the .el tree (satisfies that acceptance criterion).
  • The (or (executable-find "fish") (getenv "SHELL") (executable-find "bash") "/bin/sh") fallback chain is idiomatic and matches how the rest of the package wires Nix-provided tools in via PATH (cross-checked against nix/package.nix's makeWrapper --prefix PATH usage) rather than baked-in store paths.

That said, this is held rather than merged: no agent has nix/emacs available to actually run nix flake check or load the config, same as the PR itself flags. Per policy, changes that no agent can actually run/verify wait for the owner's explicit confirmation before merging, not static review alone — @yottanami, once you've loaded this (or run nix flake check) and confirmed M-x shell behaves, I'll merge.

explicit-shell-file-name was hardcoded to /run/current-system/sw/bin/fish,
which doesn't exist off NixOS and isn't even in this package's own Nix
closure. The rest of the package wires Nix-provided binaries in via PATH
(nix/package.nix's makeWrapper), not baked-in store paths, so resolve the
shell the same way: fish if it's on PATH, else $SHELL, else bash, else sh.
@yottanami
yottanami force-pushed the agent/18-fish-shell-path branch from c1b0883 to 2208a70 Compare July 29, 2026 11:58
An empty-but-set SHELL= (some minimal/broken login setups do this
rather than leaving it unset) is non-nil in elisp, so the previous
(or ... (getenv "SHELL") ...) accepted it as-is and skipped the
bash/sh fallbacks, leaving explicit-shell-file-name as the empty
string. Found by actually running the fallback chain in a real Emacs
batch process across all four branches (fish present, normal $SHELL,
empty $SHELL, truly unset $SHELL) rather than just reading the code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant