From: Lars Ingebrigtsen Date: Wed, 1 Sep 2021 10:13:19 +0000 (+0200) Subject: Add new macro `with-existing-directory' X-Git-Tag: emacs-28.0.90~1235 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=6a6de68dafd27238577e92a7a79e97f3f1a6e381;p=emacs.git Add new macro `with-existing-directory' * doc/lispref/files.texi (Testing Accessibility): Document it. * lisp/subr.el (with-existing-directory): New macro (bug#32004). --- diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 266501d46d0..d1045704527 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -936,6 +936,16 @@ file in @file{/foo/} will give an error: @end example @end defun +@defmac with-existing-directory body@dots{} +This macro ensures that @code{default-directory} is bound to an +existing directory before executing @var{body}. If +@code{default-directory} already exists, that's preferred, and +otherwise some other directory is used. This macro can be useful, for +instance, when calling an external command that requires that it's +running in a directory that exists. The chosen directory is not +guaranteed to be writable. +@end defmac + @defun access-file filename string If you can read @var{filename} this function returns @code{nil}; otherwise it signals an error diff --git a/etc/NEWS b/etc/NEWS index 0e1edd648d0..6f6b8e108fe 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -3422,6 +3422,11 @@ The former is now declared obsolete. * Lisp Changes in Emacs 28.1 ++++ +*** New macro 'with-existing-directory'. +This macro binds 'default-directory' to some other existing directory +if 'default-directory' doesn't exist, and then executes the body forms. + +++ *** New function 'file-name-concat'. This appends file name components to a directory name and returns the diff --git a/lisp/subr.el b/lisp/subr.el index 0a31ef2b29f..7426dcce50f 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4593,6 +4593,19 @@ MODES is as for `set-default-file-modes'." ,@body) (set-default-file-modes ,umask))))) +(defmacro with-existing-directory (&rest body) + "Execute BODY with `default-directory' bound to an existing directory. +If `default-directory' is already an existing directory, it's not changed." + (declare (indent 0) (debug t)) + `(let ((default-directory (seq-find (lambda (dir) + (and dir + (file-exists-p dir))) + (list default-directory + (expand-file-name "~/") + (getenv "TMPDIR") + "/tmp/") + "/"))) + ,@body)) ;;; Matching and match data. diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index 21b8a27858e..c1f8225ec8a 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -740,5 +740,13 @@ See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19350." 1)) (should (equal (buffer-string) "new bar zot foobar")))) +(ert-deftest test-with-existing-directory () + (let ((dir (make-temp-name "/tmp/not-exist-"))) + (let ((default-directory dir)) + (should-not (file-exists-p default-directory))) + (with-existing-directory + (should-not (equal dir default-directory)) + (should (file-exists-p default-directory))))) + (provide 'subr-tests) ;;; subr-tests.el ends here