From: Michael Albinus Date: Sun, 5 Aug 2018 09:45:22 +0000 (+0200) Subject: Rework "async" toggling of file visiting commands X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=33363e5f6232616dbcddf0a31a25d33b0347f160;p=emacs.git Rework "async" toggling of file visiting commands * doc/emacs/files.texi (Visiting): * doc/lispref/files.texi (Visiting Functions): * etc/NEWS: Use 'execute-file-commands-asynchronously' rather than 'find-file-asynchronously'. * lisp/files.el (universal-async-argument): New defun. Bind it to "C-x &". (find-file, find-file-other-window, find-file-other-frame) (find-file-existing, find-alternate-file-other-window) (find-alternate-file, find-file-literally): Adapt docstring. (execute-file-commands-asynchronously): Rename from `find-file-asynchronously'. (find-file-read-args, find-alternate-file-other-window) (find-alternate-file): Use it. --- diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 46e64c2a270..a11d8b94a9a 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -229,14 +229,14 @@ actually contains wildcard characters. You can disable the wildcard feature by customizing @code{find-file-wildcards}. @cindex visiting files asynchronously -@vindex find-file-asynchronously +@vindex execute-file-commands-asynchronously Sometimes, it is handy to visit a file asynchronously. This means, while loading the file into its buffer Emacs keeps responsive, and you can continue to edit other files, or call commands. This is -controlled by the user option @code{find-file-asynchronously}. If -this option is @code{nil} (the default), visiting a file is performed -synchronously. A regexp value let files, which name matches the -regexp, being visited asynchronously, and synchronously otherwise. +controlled by the user option @code{execute-file-commands-asynchronously}. +If this option is @code{nil} (the default), visiting a file is +performed synchronously. A regexp value let files, which name matches +the regexp, being visited asynchronously, and synchronously otherwise. The value @code{t} forces asynchronous visiting of files unconditionally. @@ -245,16 +245,16 @@ If you want to visit all remote files asynchronously, you should set @example @group (customize-set-variable - 'find-file-asynchronously tramp-file-name-regexp + 'execute-file-commands-asynchronously tramp-file-name-regexp "Visit remote files asynchronously") @end group @end example - With a prefix argument @kbd{C-u}, the meaning of -@code{find-file-asynchronously} will be reverted. If this user option -is @code{nil}, visiting a file is performed asynchronously. Contrary, -if this user option is non-@code{nil}, visiting a file is performed -synchronously. + With the key sequence @kbd{C-x &} prior the file visiting command, +the meaning of @code{execute-file-commands-asynchronously} will be +reverted. If this user option is @code{nil}, visiting a file is +performed asynchronously. Contrary, if this user option is +non-@code{nil}, visiting a file is performed synchronously. @kindex C-x C-v @findex find-alternate-file diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 9faa47b4553..4cb2605edfa 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -118,8 +118,8 @@ interactive call, then @code{find-file} expands wildcard characters in If @var{async} is non-@code{nil}, the file will be loaded into the buffer asynchronously. Interactively, this is indicated by either -setting user option @code{find-file-asynchronously} to non-@code{nil}, -or by a prefix argument. +setting user option @code{execute-file-commands-asynchronously} to +non-@code{nil}, or by the key sequence @kbd{C-x &} prior the command. When @code{find-file} is called interactively, it prompts for @var{filename} in the minibuffer. @@ -228,12 +228,12 @@ the @code{find-file} commands ignore their @var{wildcards} argument and never treat wildcard characters specially. @end defopt -@defopt find-file-asynchronously +@defopt execute-file-commands-asynchronously If this variable is non-@code{nil}, a file will be visited asynchronously when called interactively. If it is a regular expression, it must match the file name to be visited. This behavior -is toggled by a prefix argument to the interactive call of the file -visiting command. +is toggled by the key sequence @kbd{C-x &} prior to the interactive +call of the file visiting command. @end defopt @defopt find-file-hook diff --git a/etc/NEWS b/etc/NEWS index 8d18d3ea926..ea363c4b626 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -13,7 +13,7 @@ See files NEWS.26, NEWS.25, ..., NEWS.18, and NEWS.1-17 for changes in older Emacs versions. You can narrow news to a specific version by calling 'view-emacs-news' -with a prefix argument or by typing C-u C-h C-n. +with a prefix argument or by typing 'C-u C-h C-n'. Temporary note: +++ indicates that all necessary documentation updates are complete. @@ -211,12 +211,12 @@ navigation and editing of large files. +++ ** Files can be visited asynchronously. -If the new user option 'find-file-asynchronously' has a proper non-nil -value, interactive file visiting commands load the file asynchronously -into the respective buffer. I.e., Emacs is still responsive while -loading the files, which is useful especially for remote files. See -the node "(emacs) Visiting" in the user manual for the supported -commands. +If the new user option 'execute-file-commands-asynchronously' has a +proper non-nil value, interactive file visiting commands load the file +asynchronously into the respective buffer. I.e., Emacs is still +responsive while loading the files, which is useful especially for +remote files. See the node "(emacs) Visiting" in the user manual for +the supported commands. * Changes in Specialized Modes and Packages in Emacs 27.1 diff --git a/lisp/files.el b/lisp/files.el index 195694a7b67..fae79006055 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -1576,14 +1576,56 @@ rather than FUN itself, to `minibuffer-setup-hook'." ,@body) (remove-hook 'minibuffer-setup-hook ,hook))))) +(defun universal-async-argument (async) + "Execute an interactive command using the ASYNC argument. +For file visiting and saving commands, this toggles the meaning +of `execute-file-commands-asynchronously'." + (interactive + (list (and (featurep 'threads) (not execute-file-commands-asynchronously)))) + (let* ((execute-file-commands-asynchronously async) + (keyseq (read-key-sequence nil)) + (cmd (key-binding keyseq)) + prefix) + ;; `read-key-sequence' ignores quit, so make an explicit check. + (if (equal last-input-event (nth 3 (current-input-mode))) + (keyboard-quit)) + (when (memq cmd '(universal-argument digit-argument)) + (call-interactively cmd) + + ;; Process keys bound in `universal-argument-map'. + (while (progn + (setq keyseq (read-key-sequence nil t) + cmd (key-binding keyseq t)) + (not (eq cmd 'universal-argument-other-key))) + (let ((current-prefix-arg prefix-arg) + ;; Have to bind `last-command-event' here so that + ;; `digit-argument', for instance, can compute the + ;; `prefix-arg'. + (last-command-event (aref keyseq 0))) + (call-interactively cmd))) + + ;; This is the final call to `universal-argument-other-key', which + ;; sets the final `prefix-arg'. + (let ((current-prefix-arg prefix-arg)) + (call-interactively cmd)) + + ;; Read the command to execute with the given `prefix-arg'. + (setq prefix prefix-arg + keyseq (read-key-sequence nil t) + cmd (key-binding keyseq))) + + (let ((current-prefix-arg prefix)) + (message "") + (call-interactively cmd)))) + +(define-key ctl-x-map "&" 'universal-async-argument) + (defun find-file-read-args (prompt mustmatch &optional wildcards) "Return the interactive spec ( ). If WILDCARDS is non-nil, return the spec ( t )." (let ((filename (read-file-name prompt nil default-directory mustmatch)) - (async (and (xor find-file-asynchronously current-prefix-arg) - (featurep 'threads)))) - (when (and async (stringp find-file-asynchronously)) - (setq async (string-match-p find-file-asynchronously filename))) + (async (and (featurep 'threads) execute-file-commands-asynchronously))) + (when (stringp async) (setq async (string-match-p async filename))) (if wildcards `(,filename t ,async) `(,filename ,async)))) (defmacro find-file-with-threads (filename async &rest body) @@ -1623,9 +1665,10 @@ expand wildcards (if any) and visit multiple files. You can suppress wildcard expansion by setting `find-file-wildcards' to nil. If ASYNC is non-nil, the file will be loaded into the buffer -asynchronously. Interactively, this is indicated by either -setting `find-file-asynchronously' to non-nil, or by a prefix -argument. +asynchronously. Interactively, this is indicated by setting +`execute-file-commands-asynchronously' to a proper non-nil value. +This behavior can be toggled by the key sequence \\[universal-async-argument] +prior the command invocation. To visit a file without any kind of conversion and without automatically choosing a major mode, use \\[find-file-literally]." @@ -1660,9 +1703,10 @@ Interactively, or if WILDCARDS is non-nil in a call from Lisp, expand wildcards (if any) and visit multiple files. If ASYNC is non-nil, the file will be loaded into the buffer -asynchronously. Interactively, this is indicated by either -setting `find-file-asynchronously' to non-nil, or by a prefix -argument." +asynchronously. Interactively, this is indicated by setting +`execute-file-commands-asynchronously' to a proper non-nil value. +This behavior can be toggled by the key sequence \\[universal-async-argument] +prior the command invocation." (interactive (find-file-read-args "Find file in other window: " (confirm-nonexistent-file-or-buffer) t)) @@ -1698,9 +1742,10 @@ Interactively, or if WILDCARDS is non-nil in a call from Lisp, expand wildcards (if any) and visit multiple files. If ASYNC is non-nil, the file will be loaded into the buffer -asynchronously. Interactively, this is indicated by either -setting `find-file-asynchronously' to non-nil, or by a prefix -argument." +asynchronously. Interactively, this is indicated by setting +`execute-file-commands-asynchronously' to a proper non-nil value. +This behavior can be toggled by the key sequence \\[universal-async-argument] +prior the command invocation." (interactive (find-file-read-args "Find file in other frame: " (confirm-nonexistent-file-or-buffer) t)) @@ -1720,9 +1765,10 @@ Like \\[find-file], but only allow a file that exists, and do not allow file names with wildcards. If ASYNC is non-nil, the file will be loaded into the buffer -asynchronously. Interactively, this is indicated by either -setting `find-file-asynchronously' to non-nil, or by a prefix -argument." +asynchronously. Interactively, this is indicated by setting +`execute-file-commands-asynchronously' to a proper non-nil value. +This behavior can be toggled by the key sequence \\[universal-async-argument] +prior the command invocation." (interactive (find-file-read-args "Find existing file: " t)) (if (and (not (called-interactively-p 'interactive)) @@ -1779,9 +1825,10 @@ Interactively, or if WILDCARDS is non-nil in a call from Lisp, expand wildcards (if any) and replace the file with multiple files. If ASYNC is non-nil, the file will be loaded into the buffer -asynchronously. Interactively, this is indicated by either -setting `find-file-asynchronously' to non-nil, or by a prefix -argument." +asynchronously. Interactively, this is indicated by setting +`execute-file-commands-asynchronously' to a proper non-nil value. +This behavior can be toggled by the key sequence \\[universal-async-argument] +prior the command invocation." (interactive (save-selected-window (other-window 1) @@ -1794,8 +1841,9 @@ argument." (list (read-file-name "Find alternate file: " file-dir nil (confirm-nonexistent-file-or-buffer) file-name) - t (and (xor find-file-asynchronously current-prefix-arg) - (featurep 'threads)))))) + t + (and (featurep 'threads) execute-file-commands-asynchronously))))) + (when (stringp async) (setq async (string-match-p async filename))) (if (one-window-p) (find-file-other-window filename wildcards async) (save-selected-window @@ -1822,9 +1870,10 @@ Interactively, or if WILDCARDS is non-nil in a call from Lisp, expand wildcards (if any) and replace the file with multiple files. If ASYNC is non-nil, the file will be loaded into the buffer -asynchronously. Interactively, this is indicated by either -setting `find-file-asynchronously' to non-nil, or by a prefix -argument. +asynchronously. Interactively, this is indicated by setting +`execute-file-commands-asynchronously' to a proper non-nil value. +This behavior can be toggled by the key sequence \\[universal-async-argument] +prior the command invocation. If the current buffer is an indirect buffer, or the base buffer for one or more indirect buffers, the other buffer(s) are not @@ -1839,8 +1888,8 @@ killed." (list (read-file-name "Find alternate file: " file-dir nil (confirm-nonexistent-file-or-buffer) file-name) - t (and (xor find-file-asynchronously current-prefix-arg) - (featurep 'threads))))) + t (and (featurep 'threads) execute-file-commands-asynchronously)))) + (when (stringp async) (setq async (string-match-p async filename))) (unless (run-hook-with-args-until-failure 'kill-buffer-query-functions) (user-error "Aborted")) (and (buffer-modified-p) buffer-file-name @@ -2069,12 +2118,12 @@ suppresses this warning." :version "21.1" :type 'boolean) -(defcustom find-file-asynchronously nil +(defcustom execute-file-commands-asynchronously nil "Non-nil means visit file asynchronously when called interactively. If it is a regular expression, it must match the file name to be -visited. This behavior is toggled by a prefix argument to the -interactive call." - :group 'files +visited. This behavior is toggled by the key sequence \\[universal-async-argument] +prior the command invocation." +:group 'files :version "27.1" :type '(choice boolean regexp)) @@ -2496,9 +2545,10 @@ If Emacs already has a buffer which is visiting the file, this command asks you whether to visit it literally instead. If ASYNC is non-nil, the file will be loaded into the buffer -asynchronously. Interactively, this is indicated by either -setting `find-file-asynchronously' to non-nil, or by a prefix -argument. +asynchronously. Interactively, this is indicated by setting +`execute-file-commands-asynchronously' to a proper non-nil value. +This behavior can be toggled by the key sequence \\[universal-async-argument] +prior the command invocation. In non-interactive use, the value is the buffer where the file is visited literally. If the file was visited in a buffer before diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index 59c66e77bb4..21ea764989b 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -814,7 +814,7 @@ In the latter case, VC mode is deactivated for this buffer." ;; Run it asynchronously. (make-thread (lambda () - ;; Wait, until the file visitng function tells us so. + ;; Wait, until the file visiting function tells us so. (with-mutex vc-mutex) (vc-file-clearprops buffer-file-name) ;; FIXME: Why use a hook? Why pass it buffer-file-name?