GNU bug report logs - #77430
compilation-start should remember shell-file-name

Previous Next

Package: emacs;

Reported by: Siyuan Chen <chansey97 <at> gmail.com>

Date: Tue, 1 Apr 2025 13:43:06 UTC

Severity: normal

Done: Eli Zaretskii <eliz <at> gnu.org>

Bug is archived. No further changes may be made.

Full log


Message #28 received at 77430-done <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Siyuan Chen <chansey97 <at> gmail.com>
Cc: 77430-done <at> debbugs.gnu.org
Subject: Re: bug#77430: compilation-start should remember shell-file-name
Date: Sat, 19 Apr 2025 16:48:57 +0300
> From: Siyuan Chen <chansey97 <at> gmail.com>
> Date: Fri, 4 Apr 2025 16:15:06 +0800
> Cc: 77430 <at> debbugs.gnu.org
> 
> > Sorry, I don't understand: are you saying that you cannot arrange for
> the buffer-local value of shell-file-name to point to Bash and stay
> that way for the subsequent commands?  If you need to use
> with-current-buffer or something similar, it should be easy no?
> 
> The original problem is not about `compile' but `recompile', i.e. press 'g' in the *compilation* buffer. The
> *compilation* buffer doesn't know anything about the last shell-file-name, so it uses cmdproxy by default. 
> 
> Anyway, this is no longer a problem now, see below.
> 
> > I think this is the cleanest solution for problems like this on
> Windows, since you don't really want to override shell-file-name, you
> just want to invoke the commands via Bash.
> 
> Your method really inspired me. Thank you so much! 
> 
> Based on it, I've redesigned my compilation workflow. Basically, whenever users invoke
> `sc-haskell-projectile-stack-compile' (a tailored compile command integrated with projectile), it firstly
> generates two files in the Haskell project folder: 
> 
> .emacs_stack_launch.bat
> ```
> set MSYSTEM=MINGW32
> "c:/Users/Chansey/AppData/Local/Programs/stack/x86_64-windows/msys2-20230526/usr/bin/bash" --login
> "e:/my-haskell-project/.emacs_stack_launch_script.sh" %*
> ```
> 
> .emacs_stack_launch_script.sh
> ```
> export STACK_ROOT=/c/sr
> export
> PATH=/c/env/haskell/stack/v2.15.1:/c/Users/Chansey/AppData/Roaming/local/bin:/c/PROGRA~1/Git/cmd:$PATH
> 
> $*
> ```
> 
> then it calls (compile ".emacs_stack_launch.bat stack build").
> 
> This method is working great so far. Plus, the file generation brings several benefits:
> 
> 1. We can set local variables in .dir-locals (e.g. msys2-path, environment-variables) per project for
> fine-grained control over compilation.
> 
> 2. No need to tailored `recompile'. It just uses the last generated files. So it works pretty well when users
> press 'g' in the *compilation* buffer.
> 
> 3. Support all the compile commands and opts, like stack build, stack run, stack build --test, etc.
> 
> 4. Easy debugging with .emacs_stack_launch.bat and .emacs_stack_launch_script.sh. 
> 
> The code is something like this:
> 
> ```
> (defun sc-haskell-projectile-stack--run-project-cmd (command)
>   (let* ((default-directory (projectile-compilation-dir))
>          (command (projectile-read-command
>                    "Compile command: "
>                    (or projectile-project-compilation-cmd
>                        command))))
>     (sc-haskell-projectile-stack--gen-launch-file)
>     (sc-haskell-projectile-stack--gen-launch-script-file)
>     (compile (format "%s %s"
>                      ".emacs_stack_launch.bat"
>                      command)
>              projectile-compile-use-comint-mode)))
> 
> (defun sc-haskell-projectile-stack-compile ()
>   (sc-haskell-projectile-stack--run-project-cmd "stack build"))
> 
> (defun sc-haskell-projectile-stack-test ()
>   (sc-haskell-projectile-stack--run-project-cmd "stack build --test"))
> 
> (defun sc-haskell-projectile-stack-run ()
>   (sc-haskell-projectile-stack--run-project-cmd "stack run"))
> ```
> 
> Additionally, I also created a projectile-based shell command, which has to be different from projectile-based
> compile command.
> 
> ```
> (defun sc-haskell-projectile-stack-shell ()
>   (interactive)
>   (let ((current-prefix-arg 4)
>         (explicit-shell-file-name
>          (expand-file-name "usr/bin/bash" sc-haskell-projectile-stack-msys2-path))
>         (explicit-bash-args
>          '("--login" "--noediting" "-i")))
>     (sc-haskell-projectile-stack--gen-msys2-bashrc-init-file)
>     (with-environment-variables (("MSYSTEM" "MINGW32"))
>       (call-interactively 'projectile-run-shell))))
> ```
> 
> Unlike the previous method, this one still rebinds explicit-shell-file-name, otherwise we have to call "bash -
> -login --noediting -i" in the .emacs_stack_launch_script.sh, which would invoke bash twice — something I'd
> rather avoid (it still can work though).
> 
> My solution is to add a hook in .bashrc
> 
> ```
> if [ -f $HOME/.bashrc_init.sh ]; then
>     . $HOME/.bashrc_init.sh
>     rm $HOME/.bashrc_init.sh
> fi
> ```
> 
> Basically, whenever users invoke `sc-haskell-projectile-stack-shell, it generates .bashrc_init.sh in the msys2
> home USER folder. The commands in .bashrc_init.sh are similar to those in emacs_stack_launch_script and
> can, of course, be configured via .dir-locals.el. It might seem a bit unusual, but it works well so far. 
> 
> Just like to share my current design here — any suggestions would be greatly appreciated.

Thanks.

I guess we can close this bug now.




This bug report was last modified 34 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.