Subject: Re: bug#76007: 31.0.50; Interpreter not correctly found when using nix-shell.

From: Stefan Kangas <[email-masked]>
Date: Sun, 2 Feb 2025 08:49:36 -0500

Malcolm Purvis <[email-masked]> writes:

> In NixOS if you want to use a script that manages its own
> dependencies, you use a command called "nix-shell" or "nix shell"
> to launch the script.
>
> The start of such a script looks like:
>
> #! /usr/bin/env nix-shell
> #! nix-shell -i bash -p imagemagick cowsay
>
> or
>
> #! /usr/bin/env nix
> #! nix shell github:tomberek/-#perlWith.HTMLTokeParserSimple.LWP
>    --command perl -x
>
> The OS interpreter is nix-shell and nix-shell launches the real
> interpreter to execute the rest of the script.
>
> With these scripts, Emacs's current behaviour is as follows:
>
> - nix-shell is not interpreter-mode-alist so Emacs looks at the
>   file's
>  extension:
>
>  - If the file has an extension then the correct mode is used
>  - If the file does not have an extension then Fundamental mode is
>  used
>    regardless of the script's actual language.
>
> If the file is a shell script with the correct extension, sh-mode
> is used but sh-mode fails to guess the shell, leaving the variable
> sh-shell as 'nix-shell.
>
> In most cases this means that some shell features are not enabled,
> but otherwise it is possible to edit the script.
>
> However, lsp-mode's bash language support (lsp-bash.el) throws an
> error if sh-shell is not set to it's supported values ('sh and
> 'bash), and as a result nix bash scripts fail.
>
> The solution is to add a new regexp to
> auto-mode-interpreter-regexp that will detect a nix script and
> extract the real interpreter from the second line.  Nix shell can
> be invoked in a number of ways but this regexp matches the common
> forms.
>
>
> diff --git a/lisp/files.el b/lisp/files.el
> index 5ff40c335d7..1f3ac1431d2 100644
> --- a/lisp/files.el
> +++ b/lisp/files.el
> @@ -3389,6 +3389,7 @@ and `inhibit-local-variables-suffixes'.  If
>     "\\(?:[^ \t\n]+=[^ \t\n]*[ \t]+\\)*"
>     "\\)?"
>     "\\)?"
> +   "\\(?:\\(?:nix\\|nix-shell\\)\n#![
> \t]+\\(?:nix\\|nix-shell\\).*\\(?:-i\\|--command\\)[ \t]+\\)?"
>     ;; Group 2: interpreter.  "\\([^ \t\n]+\\)")
>    "Regexp matching interpreters, for file mode determination.
>
>
> Malcolm

Thanks for the bug report.

This looks to me like a bug in lsp-mode, or lsp-bash.el.  I recommend
reporting the bug to them first.