diff options
| author | Philipp Stephani | 2018-12-17 21:47:46 +0100 |
|---|---|---|
| committer | Philipp Stephani | 2018-12-22 22:10:48 +0100 |
| commit | 039be4e02513e03ae465efae5694bd4e28a74dbe (patch) | |
| tree | 34d43f419b279e7f652ef592332f2021b5eedc66 | |
| parent | b41789f31f2355f6de8c15bbbc10cd6bf3dfe61e (diff) | |
| download | emacs-039be4e02513e03ae465efae5694bd4e28a74dbe.tar.gz emacs-039be4e02513e03ae465efae5694bd4e28a74dbe.zip | |
Add file name handler support for 'make-process' (Bug#28691)
* src/process.c (Fmake_process): Add new keyword argument
':file-handler'.
(syms_of_process) <make-process, :file-handler>: Define new symbols.
* lisp/files.el (file-name-non-special): Add support for
'make-process'.
* test/src/process-tests.el (make-process/file-handler/found)
(make-process/file-handler/not-found)
(make-process/file-handler/disable): New unit tests.
(process-tests--file-handler): New helper function.
* test/lisp/files-tests.el
(files-tests-file-name-non-special-make-process): New unit test.
* doc/lispref/files.texi (Magic File Names): Document that
'make-process' can invoke file name handlers.
* doc/lispref/processes.texi (Asynchronous Processes): Document
':file-handlers' argument to 'make-process'.
* etc/NEWS (Lisp Changes in Emacs 27.1): Mention new
:file-handler argument for 'make-process'.
| -rw-r--r-- | doc/lispref/files.texi | 2 | ||||
| -rw-r--r-- | doc/lispref/processes.texi | 10 | ||||
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/files.el | 11 | ||||
| -rw-r--r-- | src/process.c | 17 | ||||
| -rw-r--r-- | test/lisp/files-tests.el | 10 | ||||
| -rw-r--r-- | test/src/process-tests.el | 49 |
7 files changed, 100 insertions, 4 deletions
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 5b428b6205d..d929978b6ea 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi | |||
| @@ -3171,6 +3171,7 @@ first, before handlers for jobs such as remote file access. | |||
| 3171 | @code{make-directory}, | 3171 | @code{make-directory}, |
| 3172 | @code{make-directory-internal}, | 3172 | @code{make-directory-internal}, |
| 3173 | @code{make-nearby-temp-file}, | 3173 | @code{make-nearby-temp-file}, |
| 3174 | @code{make-process}, | ||
| 3174 | @code{make-symbolic-link},@* | 3175 | @code{make-symbolic-link},@* |
| 3175 | @code{process-file}, | 3176 | @code{process-file}, |
| 3176 | @code{rename-file}, @code{set-file-acl}, @code{set-file-modes}, | 3177 | @code{rename-file}, @code{set-file-acl}, @code{set-file-modes}, |
| @@ -3227,6 +3228,7 @@ first, before handlers for jobs such as remote file access. | |||
| 3227 | @code{make-auto-save-file-name}, | 3228 | @code{make-auto-save-file-name}, |
| 3228 | @code{make-direc@discretionary{}{}{}tory}, | 3229 | @code{make-direc@discretionary{}{}{}tory}, |
| 3229 | @code{make-direc@discretionary{}{}{}tory-internal}, | 3230 | @code{make-direc@discretionary{}{}{}tory-internal}, |
| 3231 | @code{make-process}, | ||
| 3230 | @code{make-symbolic-link}, | 3232 | @code{make-symbolic-link}, |
| 3231 | @code{process-file}, | 3233 | @code{process-file}, |
| 3232 | @code{rename-file}, @code{set-file-acl}, @code{set-file-modes}, | 3234 | @code{rename-file}, @code{set-file-acl}, @code{set-file-modes}, |
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 402691c6bcf..d72f5b880a2 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi | |||
| @@ -696,6 +696,12 @@ non-@code{nil} value should be either a buffer or a pipe process | |||
| 696 | created with @code{make-pipe-process}, described below. If | 696 | created with @code{make-pipe-process}, described below. If |
| 697 | @var{stderr} is @code{nil}, standard error is mixed with standard | 697 | @var{stderr} is @code{nil}, standard error is mixed with standard |
| 698 | output, and both are sent to @var{buffer} or @var{filter}. | 698 | output, and both are sent to @var{buffer} or @var{filter}. |
| 699 | |||
| 700 | @item :file-handler @var{file-handler} | ||
| 701 | If @var{file-handler} is non-@code{nil}, then look for a file name | ||
| 702 | handler for the current buffer's @code{default-directory}, and invoke | ||
| 703 | that file handler to make the process. If there is no such handler, | ||
| 704 | proceed as if @var{file-handler} were @code{nil}. | ||
| 699 | @end table | 705 | @end table |
| 700 | 706 | ||
| 701 | The original argument list, modified with the actual connection | 707 | The original argument list, modified with the actual connection |
| @@ -704,8 +710,8 @@ information, is available via the @code{process-contact} function. | |||
| 704 | The current working directory of the subprocess is set to the current | 710 | The current working directory of the subprocess is set to the current |
| 705 | buffer's value of @code{default-directory} if that is local (as | 711 | buffer's value of @code{default-directory} if that is local (as |
| 706 | determined by `unhandled-file-name-directory'), or "~" otherwise. If | 712 | determined by `unhandled-file-name-directory'), or "~" otherwise. If |
| 707 | you want to run a process in a remote directory use | 713 | you want to run a process in a remote directory, pass |
| 708 | @code{start-file-process}. | 714 | @code{:file-handler t} to @code{make-process}. |
| 709 | @end defun | 715 | @end defun |
| 710 | 716 | ||
| 711 | @defun make-pipe-process &rest args | 717 | @defun make-pipe-process &rest args |
| @@ -1428,6 +1428,11 @@ un-obsoleting it. | |||
| 1428 | +++ | 1428 | +++ |
| 1429 | ** New function 'group-name' returns a group name corresponding to GID. | 1429 | ** New function 'group-name' returns a group name corresponding to GID. |
| 1430 | 1430 | ||
| 1431 | ** 'make-process' now takes a keyword argument ':file-handler'; if | ||
| 1432 | that is non-nil, it will look for a file name handler for the current | ||
| 1433 | buffer's 'default-directory' and invoke that file handler to make the | ||
| 1434 | process. That way 'make-process' can start remote processes. | ||
| 1435 | |||
| 1431 | 1436 | ||
| 1432 | * Changes in Emacs 27.1 on Non-Free Operating Systems | 1437 | * Changes in Emacs 27.1 on Non-Free Operating Systems |
| 1433 | 1438 | ||
diff --git a/lisp/files.el b/lisp/files.el index fb6cf0193a9..448df62710c 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -7103,7 +7103,8 @@ only these files will be asked to be saved." | |||
| 7103 | (default-directory | 7103 | (default-directory |
| 7104 | (if (memq operation | 7104 | (if (memq operation |
| 7105 | '(insert-directory process-file start-file-process | 7105 | '(insert-directory process-file start-file-process |
| 7106 | shell-command temporary-file-directory)) | 7106 | make-process shell-command |
| 7107 | temporary-file-directory)) | ||
| 7107 | (directory-file-name | 7108 | (directory-file-name |
| 7108 | (expand-file-name | 7109 | (expand-file-name |
| 7109 | (unhandled-file-name-directory default-directory))) | 7110 | (unhandled-file-name-directory default-directory))) |
| @@ -7151,7 +7152,13 @@ only these files will be asked to be saved." | |||
| 7151 | ;; These file-notify-* operations take a | 7152 | ;; These file-notify-* operations take a |
| 7152 | ;; descriptor. | 7153 | ;; descriptor. |
| 7153 | (file-notify-rm-watch) | 7154 | (file-notify-rm-watch) |
| 7154 | (file-notify-valid-p))) | 7155 | (file-notify-valid-p) |
| 7156 | ;; `make-process' uses keyword arguments and | ||
| 7157 | ;; doesn't mangle its filenames in any way. | ||
| 7158 | ;; It already strips /: from the binary | ||
| 7159 | ;; filename, so we don't have to do this | ||
| 7160 | ;; here. | ||
| 7161 | (make-process))) | ||
| 7155 | ;; For all other operations, treat the first | 7162 | ;; For all other operations, treat the first |
| 7156 | ;; argument only as the file name. | 7163 | ;; argument only as the file name. |
| 7157 | '(nil 0)))) | 7164 | '(nil 0)))) |
diff --git a/src/process.c b/src/process.c index 8e0b2349f9d..5895f77446b 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -1661,6 +1661,11 @@ to the standard error of subprocess. Specifying this implies | |||
| 1661 | `:connection-type' is set to `pipe'. If STDERR is nil, standard error | 1661 | `:connection-type' is set to `pipe'. If STDERR is nil, standard error |
| 1662 | is mixed with standard output and sent to BUFFER or FILTER. | 1662 | is mixed with standard output and sent to BUFFER or FILTER. |
| 1663 | 1663 | ||
| 1664 | :file-handler FILE-HANDLER -- If FILE-HANDLER is non-nil, then look | ||
| 1665 | for a file name handler for the current buffer's `default-directory' | ||
| 1666 | and invoke that file handler to make the process. If there is no | ||
| 1667 | such handler, proceed as if FILE-HANDLER were nil. | ||
| 1668 | |||
| 1664 | usage: (make-process &rest ARGS) */) | 1669 | usage: (make-process &rest ARGS) */) |
| 1665 | (ptrdiff_t nargs, Lisp_Object *args) | 1670 | (ptrdiff_t nargs, Lisp_Object *args) |
| 1666 | { | 1671 | { |
| @@ -1674,6 +1679,15 @@ usage: (make-process &rest ARGS) */) | |||
| 1674 | /* Save arguments for process-contact and clone-process. */ | 1679 | /* Save arguments for process-contact and clone-process. */ |
| 1675 | contact = Flist (nargs, args); | 1680 | contact = Flist (nargs, args); |
| 1676 | 1681 | ||
| 1682 | if (!NILP (Fplist_get (contact, QCfile_handler))) | ||
| 1683 | { | ||
| 1684 | Lisp_Object file_handler | ||
| 1685 | = Ffind_file_name_handler (BVAR (current_buffer, directory), | ||
| 1686 | Qmake_process); | ||
| 1687 | if (!NILP (file_handler)) | ||
| 1688 | return CALLN (Fapply, file_handler, Qmake_process, contact); | ||
| 1689 | } | ||
| 1690 | |||
| 1677 | buffer = Fplist_get (contact, QCbuffer); | 1691 | buffer = Fplist_get (contact, QCbuffer); |
| 1678 | if (!NILP (buffer)) | 1692 | if (!NILP (buffer)) |
| 1679 | buffer = Fget_buffer_create (buffer); | 1693 | buffer = Fget_buffer_create (buffer); |
| @@ -8098,6 +8112,8 @@ init_process_emacs (int sockfd) | |||
| 8098 | void | 8112 | void |
| 8099 | syms_of_process (void) | 8113 | syms_of_process (void) |
| 8100 | { | 8114 | { |
| 8115 | DEFSYM (Qmake_process, "make-process"); | ||
| 8116 | |||
| 8101 | #ifdef subprocesses | 8117 | #ifdef subprocesses |
| 8102 | 8118 | ||
| 8103 | DEFSYM (Qprocessp, "processp"); | 8119 | DEFSYM (Qprocessp, "processp"); |
| @@ -8138,6 +8154,7 @@ syms_of_process (void) | |||
| 8138 | DEFSYM (Qreal, "real"); | 8154 | DEFSYM (Qreal, "real"); |
| 8139 | DEFSYM (Qnetwork, "network"); | 8155 | DEFSYM (Qnetwork, "network"); |
| 8140 | DEFSYM (Qserial, "serial"); | 8156 | DEFSYM (Qserial, "serial"); |
| 8157 | DEFSYM (QCfile_handler, ":file-handler"); | ||
| 8141 | DEFSYM (QCbuffer, ":buffer"); | 8158 | DEFSYM (QCbuffer, ":buffer"); |
| 8142 | DEFSYM (QChost, ":host"); | 8159 | DEFSYM (QChost, ":host"); |
| 8143 | DEFSYM (QCservice, ":service"); | 8160 | DEFSYM (QCservice, ":service"); |
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index 3b192ee8727..9d827e865d9 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el | |||
| @@ -1109,6 +1109,16 @@ unquoted file names." | |||
| 1109 | (with-temp-buffer | 1109 | (with-temp-buffer |
| 1110 | (write-region nil nil nospecial nil :visit)))) | 1110 | (write-region nil nil nospecial nil :visit)))) |
| 1111 | 1111 | ||
| 1112 | (ert-deftest files-tests-file-name-non-special-make-process () | ||
| 1113 | "Check that the ‘:file-handler’ argument of ‘make-process’ | ||
| 1114 | works as expected if the default directory is quoted." | ||
| 1115 | (let ((default-directory (file-name-quote invocation-directory)) | ||
| 1116 | (program (file-name-quote | ||
| 1117 | (expand-file-name invocation-name invocation-directory)))) | ||
| 1118 | (should (processp (make-process :name "name" | ||
| 1119 | :command (list program "--version") | ||
| 1120 | :file-handler t))))) | ||
| 1121 | |||
| 1112 | (ert-deftest files-tests--insert-directory-wildcard-in-dir-p () | 1122 | (ert-deftest files-tests--insert-directory-wildcard-in-dir-p () |
| 1113 | (let ((alist (list (cons "/home/user/*/.txt" (cons "/home/user/" "*/.txt")) | 1123 | (let ((alist (list (cons "/home/user/*/.txt" (cons "/home/user/" "*/.txt")) |
| 1114 | (cons "/home/user/.txt" nil) | 1124 | (cons "/home/user/.txt" nil) |
diff --git a/test/src/process-tests.el b/test/src/process-tests.el index 551b34ff371..af5bc737574 100644 --- a/test/src/process-tests.el +++ b/test/src/process-tests.el | |||
| @@ -215,5 +215,54 @@ | |||
| 215 | (string-to-list "stdout\n") | 215 | (string-to-list "stdout\n") |
| 216 | (string-to-list "stderr\n")))))) | 216 | (string-to-list "stderr\n")))))) |
| 217 | 217 | ||
| 218 | (ert-deftest make-process/file-handler/found () | ||
| 219 | "Check that the ‘:file-handler’ argument of ‘make-process’ | ||
| 220 | works as expected if a file handler is found." | ||
| 221 | (let ((file-handler-calls 0)) | ||
| 222 | (cl-flet ((file-handler | ||
| 223 | (&rest args) | ||
| 224 | (should (equal default-directory "test-handler:/dir/")) | ||
| 225 | (should (equal args '(make-process :name "name" | ||
| 226 | :command ("/some/binary") | ||
| 227 | :file-handler t))) | ||
| 228 | (cl-incf file-handler-calls) | ||
| 229 | 'fake-process)) | ||
| 230 | (let ((file-name-handler-alist (list (cons (rx bos "test-handler:") | ||
| 231 | #'file-handler))) | ||
| 232 | (default-directory "test-handler:/dir/")) | ||
| 233 | (should (eq (make-process :name "name" | ||
| 234 | :command '("/some/binary") | ||
| 235 | :file-handler t) | ||
| 236 | 'fake-process)) | ||
| 237 | (should (= file-handler-calls 1)))))) | ||
| 238 | |||
| 239 | (ert-deftest make-process/file-handler/not-found () | ||
| 240 | "Check that the ‘:file-handler’ argument of ‘make-process’ | ||
| 241 | works as expected if no file handler is found." | ||
| 242 | (let ((file-name-handler-alist ()) | ||
| 243 | (default-directory invocation-directory) | ||
| 244 | (program (expand-file-name invocation-name invocation-directory))) | ||
| 245 | (should (processp (make-process :name "name" | ||
| 246 | :command (list program "--version") | ||
| 247 | :file-handler t))))) | ||
| 248 | |||
| 249 | (ert-deftest make-process/file-handler/disable () | ||
| 250 | "Check ‘make-process’ works as expected if it shouldn’t use the | ||
| 251 | file handler." | ||
| 252 | (let ((file-name-handler-alist (list (cons (rx bos "test-handler:") | ||
| 253 | #'process-tests--file-handler))) | ||
| 254 | (default-directory "test-handler:/dir/") | ||
| 255 | (program (expand-file-name invocation-name invocation-directory))) | ||
| 256 | (should (processp (make-process :name "name" | ||
| 257 | :command (list program "--version")))))) | ||
| 258 | |||
| 259 | (defun process-tests--file-handler (operation &rest _args) | ||
| 260 | (cl-ecase operation | ||
| 261 | (unhandled-file-name-directory "/") | ||
| 262 | (make-process (ert-fail "file handler called unexpectedly")))) | ||
| 263 | |||
| 264 | (put #'process-tests--file-handler 'operations | ||
| 265 | '(unhandled-file-name-directory make-process)) | ||
| 266 | |||
| 218 | (provide 'process-tests) | 267 | (provide 'process-tests) |
| 219 | ;; process-tests.el ends here. | 268 | ;; process-tests.el ends here. |