Skip to content

Commit e2b0edb

Browse files
committed
Support nushell (fixes #109)
1 parent fcc0944 commit e2b0edb

File tree

2 files changed

+64
-19
lines changed

2 files changed

+64
-19
lines changed

.github/workflows/test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
steps:
1212
- uses: purcell/setup-emacs@master
1313
with:
14-
version: 29.1
14+
version: 29.3
1515
- uses: actions/checkout@v2
1616
- name: Run tests
1717
run: make package-lint
@@ -21,7 +21,7 @@ jobs:
2121
strategy:
2222
matrix:
2323
emacs_version:
24-
- 24.1
24+
- 24.4
2525
- 24.5
2626
- 25.1
2727
- 25.3

exec-path-from-shell.el

+62-17
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
;; Keywords: unix, environment
77
;; URL: https://github.com/purcell/exec-path-from-shell
88
;; Package-Version: 2.1
9-
;; Package-Requires: ((emacs "24.1") (cl-lib "0.6"))
9+
;; Package-Requires: ((emacs "24.4"))
1010

1111
;; This file is not part of GNU Emacs.
1212

@@ -76,6 +76,7 @@
7676
;; Satisfy the byte compiler
7777
(eval-when-compile (require 'eshell))
7878
(require 'cl-lib)
79+
(require 'json)
7980

8081
(defgroup exec-path-from-shell nil
8182
"Make Emacs use shell-defined values for $PATH etc."
@@ -135,6 +136,10 @@ The default value denotes an interactive login shell."
135136
(when exec-path-from-shell-debug
136137
(apply 'message msg args)))
137138

139+
(defun exec-path-from-shell--nushell-p (shell)
140+
"Return non-nil if SHELL is nu."
141+
(string-match-p "nu$" shell))
142+
138143
(defun exec-path-from-shell--standard-shell-p (shell)
139144
"Return non-nil iff SHELL supports the standard ${VAR-default} syntax."
140145
(not (string-match-p "\\(fish\\|nu\\|t?csh\\)$" shell)))
@@ -188,29 +193,69 @@ shell-escaped, so they may contain $ etc."
188193
(match-string 1)
189194
(error "Expected printf output from shell, but got: %S" (buffer-string))))))
190195

196+
(defun exec-path-from-shell-getenvs--nushell (names)
197+
"Use nushell to get the value of env vars with the given NAMES.
198+
199+
Execute the shell according to `exec-path-from-shell-arguments'.
200+
The result is a list of (NAME . VALUE) pairs."
201+
(let* ((shell (exec-path-from-shell--shell))
202+
(expr (format "[ %s ] | to json"
203+
(string-join
204+
(mapcar (lambda (name)
205+
(format "$env.%s?" (exec-path-from-shell--double-quote name)))
206+
names)
207+
", ")))
208+
(shell-args (append exec-path-from-shell-arguments (list "-c" expr))))
209+
(with-temp-buffer
210+
(exec-path-from-shell--debug "Invoking shell %s with args %S" shell shell-args)
211+
(let ((exit-code (exec-path-from-shell--warn-duration
212+
(apply #'call-process shell nil t nil shell-args))))
213+
(exec-path-from-shell--debug "Shell printed: %S" (buffer-string))
214+
(unless (zerop exit-code)
215+
(error "Non-zero exit code from shell %s invoked with args %S. Output was:\n%S"
216+
shell shell-args (buffer-string))))
217+
(goto-char (point-min))
218+
(let ((json-array-type 'list)
219+
(json-null :null))
220+
(let ((values (json-read-array))
221+
result)
222+
(while values
223+
(let ((value (car values)))
224+
(push (cons (car names)
225+
(unless (eq :null value)
226+
(if (listp value)
227+
(string-join value path-separator)
228+
value)))
229+
result))
230+
(setq values (cdr values)
231+
names (cdr names)))
232+
result)))))
233+
191234
(defun exec-path-from-shell-getenvs (names)
192235
"Get the environment variables with NAMES from the user's shell.
193236
194237
Execute the shell according to `exec-path-from-shell-arguments'.
195238
The result is a list of (NAME . VALUE) pairs."
196239
(when (file-remote-p default-directory)
197240
(error "You cannot run exec-path-from-shell from a remote buffer (Tramp, etc.)"))
198-
(let* ((random-default (md5 (format "%s%s%s" (emacs-pid) (random) (current-time))))
199-
(dollar-names (mapcar (lambda (n) (format "${%s-%s}" n random-default)) names))
200-
(values (split-string (exec-path-from-shell-printf
201-
(mapconcat #'identity (make-list (length names) "%s") "\\000")
202-
dollar-names) "\0")))
203-
(let (result)
204-
(while names
205-
(prog1
206-
(let ((value (car values)))
207-
(push (cons (car names)
208-
(unless (string-equal random-default value)
209-
value))
210-
result))
211-
(setq values (cdr values)
212-
names (cdr names))))
213-
result)))
241+
(if (exec-path-from-shell--nushell-p)
242+
(exec-path-from-shell-getenvs--nushell names)
243+
(let* ((random-default (md5 (format "%s%s%s" (emacs-pid) (random) (current-time))))
244+
(dollar-names (mapcar (lambda (n) (format "${%s-%s}" n random-default)) names))
245+
(values (split-string (exec-path-from-shell-printf
246+
(mapconcat #'identity (make-list (length names) "%s") "\\000")
247+
dollar-names) "\0")))
248+
(let (result)
249+
(while names
250+
(prog1
251+
(let ((value (car values)))
252+
(push (cons (car names)
253+
(unless (string-equal random-default value)
254+
value))
255+
result))
256+
(setq values (cdr values)
257+
names (cdr names))))
258+
result))))
214259

215260
(defun exec-path-from-shell-getenv (name)
216261
"Get the environment variable NAME from the user's shell.

0 commit comments

Comments
 (0)