PowerShell in Emacs Shell Mode on Windows
I recently decided to give native Emacs on Windows another go. Since I use Windows for some of the classes I teach, I have tried to like WSL2. Microsoft implements Wayland in a very non-standard way that does not really work, and even after applying a fix (not from Microsoft even if they have known for months that their default distro doesn't work with WSLg, but from users in the GitHub bug report), I had trouble with the Emacs window freezing after having locked my screen and unlocked it. I do this at every break during the day, and there are 7 of those every day, so this has to work. So I thought I would try to go native again with the Windows version of Emacs and just use what I need right now and gradually fix or work around the issues that needs fixing. For now, I need Shell Mode to work, so I have looked at that first.
By default, you get cmd.exe in Shell mode on Windows. I had some trouble finding good documentation of how to set it up with PowerShell. Some suggest just setting PowerShell to explicit-shell-file-name, but that only partially worked since it gave me an error that PowerShell was invoked with a wrong argument. A lot of people pointed to someone on the Microsoft blogs that set up PowerShell in Shell mode, but in a way that removed the prompt. He had made an Elisp workaround to get the prompt back, but it seemed like there should be an easier way. The trouble is that comint mode, the mode shell mode is built on, sends -i by default to the shells it interacts with as an argument. I tried a couple of things and it turns out the solution is really simple.
(use-package shell :config (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on) (add-to-list 'comint-output-filter-functions 'ansi-color-process-output) (add-hook 'comint-output-filter-functions 'comint-osc-process-output) (setq explicit-shell-file-name "C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe") (setq explicit-powershell.exe-args '("")) (add-hook 'shell-mode-hook (lambda() (company-mode 0))))
In the code block above, I turn on ansi-color since PowerShell can work with those. I tell Emacs to run PowerShell and give it the arguments "" (ie, nothing) which remove the default -i argument, but adds nothing else. And now I have PowerShell in Shell mode. The last line is useful to me because I have turned on company globally, but I don't want it in shell mode.