feat(cli): add doom.ps1 for Windows users

c9acdb7 removes doom.cmd because it was broken in most cases. This adds
doom.ps1; an alternative script for Windows+Powershell users, which
properly initializes the state it needs. Naturally, it requires
Powershell 3+ be installed on your systems, but it can be invoked from
either cmd.exe or PowerShell.exe.

This is the first powershell script I've ever written, so I expect edge
cases (for one, shell commands passed to `exit!` will need to be guarded
against the environment).

This also requires emacs.exe be your $PATH, however, unless you set
$EMACS to its path first. E.g.

  $env:EMACS = "C:\Program Files\Emacs\emacs-29.4\bin\emacs.exe"

That said, if you use WSL2, you're still far better off using the bash
script (bin/doom).

Ref: c9acdb72a4
This commit is contained in:
Henrik Lissner 2024-09-07 00:41:16 -04:00
parent 9753bfb775
commit 8d2cf32fef
No known key found for this signature in database
GPG key ID: B60957CA074D39A3
3 changed files with 80 additions and 20 deletions

38
bin/doom.ps1 Normal file
View file

@ -0,0 +1,38 @@
# bin/doom.ps1
if (!(Get-Command -Erroraction silentlycontinue emacs.exe)) {
echo "Couldn't find emacs.exe in your $PATH."
exit 1
}
$doom = "$PSScriptRoot/doom"
$emacs = if ($env:EMACS) { $env:EMACS } else { (Get-Command emacs.exe).Path }
$emacsargs = "-q", "--no-site-file", "--batch"
$oldemacsdir = $env:EMACSDIR
try {
$env:EMACSDIR = if (-not $env:EMACSDIR) { (get-item $PSScriptRoot).parent.FullName } else { $env:EMACSDIR }
$env:__DOOMSH = if (-not $env:__DOOMSH) { "ps1" } else { $env:__DOOMSH }
$env:__DOOMPID = if (-not $env:__DOOMPID) { $PID } else { $env:__DOOMPID }
$env:__DOOMSTEP = if (-not $env:__DOOMSTEP) { 0 } else { $env:__DOOMSTEP }
$cols = (Get-Host).UI.RawUI.WindowSize.Width
$lines = (Get-Host).UI.RawUI.WindowSize.Height
$env:__DOOMGEOM = if (-not $env:__DOOMGEOM) { "$cols`x$lines" } else { $env:__DOOMGEOM }
# $env:__DOOMGPIPE = if (-not $env:__DOOMGPIPE) { $env:__DOOMPIPE } else { $env:__DOOMGPIPE }
# $env:__DOOMPIPE = ""
& $emacs $emacsargs --load "$doom" -- --no-color $args
$exit = $LASTEXITCODE
} finally {
$env:EMACSDIR = $oldemacsdir
Remove-Item Env:\__DOOMSH
Remove-Item Env:\__DOOMPID
Remove-Item Env:\__DOOMSTEP
Remove-Item Env:\__DOOMGEOM
}
if ($exit -eq 254) {
& pwsh "$env:TMPDIR\doom.$($env:__DOOMPID).$($env:__DOOMSTEP).ps1" $PSCommandPath $args
$exit = $LASTEXITCODE
}
exit $exit

View file

@ -57,6 +57,7 @@ if [ ! -f "$EMACSDIR/early-init.el" ]; then
fi >&2 fi >&2
# Some state that Doom's CLI framework needs to know about the terminal. Read # Some state that Doom's CLI framework needs to know about the terminal. Read
# the comments at the top of bin/doom for explanations. # the comments at the top of bin/doom for explanations.
export __DOOMSH="${__DOOMSH:-sh}"
export __DOOMPID="${__DOOMPID:-$$}" export __DOOMPID="${__DOOMPID:-$$}"
export __DOOMSTEP="${__DOOMSTEP:-0}" export __DOOMSTEP="${__DOOMSTEP:-0}"
export __DOOMGEOM="${__DOOMGEOM:-$(tput cols 2>/dev/null)x$(tput lines 2>/dev/null)}" export __DOOMGEOM="${__DOOMGEOM:-$(tput cols 2>/dev/null)x$(tput lines 2>/dev/null)}"

View file

@ -1121,8 +1121,9 @@ Emacs' batch library lacks an implementation of the exec system call."
(error "__DOOMSTEP envvar missing; extended `exit!' functionality will not work")) (error "__DOOMSTEP envvar missing; extended `exit!' functionality will not work"))
(let* ((pid (doom-cli-context-pid context)) (let* ((pid (doom-cli-context-pid context))
(step (doom-cli-context-step context)) (step (doom-cli-context-step context))
(shtype (or (getenv "__DOOMSH") "sh"))
(context-file (format (doom-path temporary-file-directory "doom.%s.%s.context") pid step)) (context-file (format (doom-path temporary-file-directory "doom.%s.%s.context") pid step))
(script-file (format (doom-path temporary-file-directory "doom.%s.%s.sh") pid step)) (script-file (format (doom-path temporary-file-directory "doom.%s.%s.%s") pid step shtype))
(command (if (listp args) (combine-and-quote-strings (remq nil args)) args)) (command (if (listp args) (combine-and-quote-strings (remq nil args)) args))
(persistent-files (persistent-files
(combine-and-quote-strings (delq nil (list script-file context-file)))) (combine-and-quote-strings (delq nil (list script-file context-file))))
@ -1154,24 +1155,40 @@ Emacs' batch library lacks an implementation of the exec system call."
newcontext)) newcontext))
(doom-log "restart: writing post-script to %s" script-file) (doom-log "restart: writing post-script to %s" script-file)
(doom-file-write (doom-file-write
script-file `("#!/usr/bin/env sh\n" script-file
"trap _doomcleanup EXIT\n" (let ((envvars `(("DOOMPROFILE" . ,(ignore-errors (doom-profile->id doom-profile)))
"_doomcleanup() {\n rm -f " ,persistent-files "\n}\n" ("EMACSDIR" . ,doom-emacs-dir)
"_doomrun() {\n " ,command "\n}\n" ("DOOMDIR" . ,doom-user-dir)
,(string-join persisted-env " \\\n") ("DEBUG" . ,(if init-file-debug "1"))
,(cl-loop for (envvar . val) ("__DOOMPID" . ,(number-to-string (doom-cli-context-pid context)))
in `(("DOOMPROFILE" . ,(ignore-errors (doom-profile->id doom-profile))) ("__DOOMSTEP" . ,(number-to-string (doom-cli-context-step context)))
("EMACSDIR" . ,doom-emacs-dir) ("__DOOMGEOM" . ,(number-to-string (doom-cli-context-step context)))
("DOOMDIR" . ,doom-user-dir) ("__DOOMCONTEXT" . ,context-file))))
("DEBUG" . ,(if init-file-debug "1")) (pcase-exhaustive shtype
("__DOOMSTEP" . ,(number-to-string (doom-cli-context-step context))) ("sh" `("#!/usr/bin/env sh\n"
("__DOOMCONTEXT" . ,context-file)) "trap _doomcleanup EXIT\n"
if val "_doomcleanup() {\n rm -f " ,persistent-files "\n}\n"
concat (format "%s=%s \\\n" envvar (shell-quote-argument val))) "_doomrun() {\n " ,command "\n}\n"
,(format "PATH=\"%s%s$PATH\" \\\n" ,(string-join persisted-env " \\\n")
(doom-path doom-emacs-dir "bin") ,(cl-loop for (envvar . val) in envvars
path-separator) if val
"_doomrun \"$@\"\n"))) concat (format "%s=%s \\\n" envvar (shell-quote-argument val)))
,(format "PATH=\"%s%s$PATH\" \\\n"
(doom-path doom-emacs-dir "bin")
path-separator)
"_doomrun \"$@\"\n"))
("ps1" `("try {\n"
,(cl-loop for (envvar . val) in envvars
if val
concat (format " $__%s = $env:%s; $env:%s = %s\\\n " envvar envvar envvar (shell-quote-argument val)))
,command
"\n} finally {\n"
,(cl-loop for file in persistent-files
concat (format " Remote-Item -Path %S\n " file))
,(cl-loop for (envvar . val) in envvars
if val
concat (format " $env:%s = $__%s\\\n " envvar envvar))
"\n}"))))))
(doom-log "_doomrun: %s %s" (string-join persisted-env " ") command) (doom-log "_doomrun: %s %s" (string-join persisted-env " ") command)
(doom-log "_doomcleanup: %s" persistent-files) (doom-log "_doomcleanup: %s" persistent-files)
;; Error code 254 is special: it indicates to the caller that the ;; Error code 254 is special: it indicates to the caller that the
@ -1268,7 +1285,11 @@ Arguments don't have to be switches either."
ARGS are options passed to less. If DOOMPAGER is set, ARGS are ignored." ARGS are options passed to less. If DOOMPAGER is set, ARGS are ignored."
(let ((pager (or doom-cli-pager (getenv "DOOMPAGER")))) (let ((pager (or doom-cli-pager (getenv "DOOMPAGER"))))
(cond ((null (or pager (executable-find "less"))) (cond ((equal (getenv "__DOOMSH") "ps1")
;; Pager isn't supported in powershell
(doom-cli--exit 0 context))
((null (or pager (executable-find "less")))
(user-error "No pager set or available") (user-error "No pager set or available")
(doom-cli--exit 1 context)) (doom-cli--exit 1 context))