From 8d2cf32fef9a82e1b929dc22adec3235181d7b54 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 7 Sep 2024 00:41:16 -0400 Subject: [PATCH] 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: c9acdb72a4bd --- bin/doom.ps1 | 38 +++++++++++++++++++++++++++ bin/doomscript | 1 + lisp/doom-cli-lib.el | 61 +++++++++++++++++++++++++++++--------------- 3 files changed, 80 insertions(+), 20 deletions(-) create mode 100644 bin/doom.ps1 diff --git a/bin/doom.ps1 b/bin/doom.ps1 new file mode 100644 index 000000000..be190b2f8 --- /dev/null +++ b/bin/doom.ps1 @@ -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 diff --git a/bin/doomscript b/bin/doomscript index 490dbeb7d..2017a4c23 100755 --- a/bin/doomscript +++ b/bin/doomscript @@ -57,6 +57,7 @@ if [ ! -f "$EMACSDIR/early-init.el" ]; then fi >&2 # Some state that Doom's CLI framework needs to know about the terminal. Read # the comments at the top of bin/doom for explanations. +export __DOOMSH="${__DOOMSH:-sh}" export __DOOMPID="${__DOOMPID:-$$}" export __DOOMSTEP="${__DOOMSTEP:-0}" export __DOOMGEOM="${__DOOMGEOM:-$(tput cols 2>/dev/null)x$(tput lines 2>/dev/null)}" diff --git a/lisp/doom-cli-lib.el b/lisp/doom-cli-lib.el index 4cf8e44f5..55a62918f 100644 --- a/lisp/doom-cli-lib.el +++ b/lisp/doom-cli-lib.el @@ -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")) (let* ((pid (doom-cli-context-pid 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)) - (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)) (persistent-files (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)) (doom-log "restart: writing post-script to %s" script-file) (doom-file-write - script-file `("#!/usr/bin/env sh\n" - "trap _doomcleanup EXIT\n" - "_doomcleanup() {\n rm -f " ,persistent-files "\n}\n" - "_doomrun() {\n " ,command "\n}\n" - ,(string-join persisted-env " \\\n") - ,(cl-loop for (envvar . val) - in `(("DOOMPROFILE" . ,(ignore-errors (doom-profile->id doom-profile))) - ("EMACSDIR" . ,doom-emacs-dir) - ("DOOMDIR" . ,doom-user-dir) - ("DEBUG" . ,(if init-file-debug "1")) - ("__DOOMSTEP" . ,(number-to-string (doom-cli-context-step context))) - ("__DOOMCONTEXT" . ,context-file)) - if val - 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"))) + script-file + (let ((envvars `(("DOOMPROFILE" . ,(ignore-errors (doom-profile->id doom-profile))) + ("EMACSDIR" . ,doom-emacs-dir) + ("DOOMDIR" . ,doom-user-dir) + ("DEBUG" . ,(if init-file-debug "1")) + ("__DOOMPID" . ,(number-to-string (doom-cli-context-pid context))) + ("__DOOMSTEP" . ,(number-to-string (doom-cli-context-step context))) + ("__DOOMGEOM" . ,(number-to-string (doom-cli-context-step context))) + ("__DOOMCONTEXT" . ,context-file)))) + (pcase-exhaustive shtype + ("sh" `("#!/usr/bin/env sh\n" + "trap _doomcleanup EXIT\n" + "_doomcleanup() {\n rm -f " ,persistent-files "\n}\n" + "_doomrun() {\n " ,command "\n}\n" + ,(string-join persisted-env " \\\n") + ,(cl-loop for (envvar . val) in envvars + if val + 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 "_doomcleanup: %s" persistent-files) ;; 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." (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") (doom-cli--exit 1 context))