commit 1bed13111be2954e418f3cf43f30944ea5b82055 (HEAD, refs/remotes/origin/master) Merge: 0a361fd91ab b0cbd5590b2 Author: Stefan Kangas Date: Fri Feb 24 06:30:11 2023 +0100 Merge from origin/emacs-29 b0cbd5590b2 Eglot: simplify inlay hints implementation with jit-lock 91e24c5b5a6 Eglot: update inlay hints on window configuration changes 79fead1709f ; Fix a typo in a doc string in c-ts-common.el (bug#61736). a0b273ef300 ; Clarify documentation of 'file-modes-number-to-symbolic' 5c2be6a2632 ; Fix recently-added doc strings in eglot.el e3be0dbf85c Eglot: display completion label when safe 5286111ea1f Improve documentation of VC commands, including in Dired 990f4027131 * doc/emacs/maintaining.texi: More mentions of marked fil... commit b0cbd5590b238fa9001e3f07b7035704ef976722 (refs/remotes/origin/emacs-29) Author: João Távora Date: Thu Feb 23 23:51:09 2023 +0000 Eglot: simplify inlay hints implementation with jit-lock This implementation is much simpler than the one based on windows-scroll-functions. It's also supposedly safer, as long as jit-lock guarantees refontification of affected regions. It's not _trivially_ simple though, as simply adding 'eglot--update-hints-1' to jit-lock-functions, while possible, is going to request inlay hints from the LSP server for many small regions of the buffer, depending on what jit-lock thinks is best. So we keep coalescing these into a larger region until the time is suitable for a more bandwidth-efficient request. To do this, we use a jit-lock implementation detail, jit-lock-context-unfontify-pos, which is a proxy for knowing that the jit-lock-context-timer has run. Not sure how brittle it is, but it seems to work reasonably. We also get rid of the previous "get hints for entire buffer" implementation. * doc/misc/eglot.texi (Eglot Variables): Remove mention to deleted eglot-lazy-inlay-hints. * lisp/progmodes/eglot.el (eglot-lazy-inlay-hints) (eglot--inlay-hints-after-scroll) (eglot--inlay-hints-fully) (eglot--inlay-hints-lazily): Remove. (eglot--update-hints): Add function. (eglot-inlay-hints-mode): Simplify. diff --git a/doc/misc/eglot.texi b/doc/misc/eglot.texi index 38c6adaf131..eed9744b9f0 100644 --- a/doc/misc/eglot.texi +++ b/doc/misc/eglot.texi @@ -883,14 +883,6 @@ Eglot Variables (define-key eglot-mode-map (kbd "") 'xref-find-definitions) @end lisp -@item eglot-lazy-inlay-hints -This variable controls the operation and performance of LSP Inlay -Hints (@pxref{Eglot Features}). If non-@code{nil}, it specifies how -much time to wait after a window is displayed or scrolled before -requesting hints for that visible portion of a given buffer. If -@code{nil}, inlay hints are always requested for the whole buffer, -even for parts of it not currently visible. - @end vtable Additional variables, which are relevant for customizing the server diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index eea8be6d1aa..9d722047b47 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -3489,32 +3489,39 @@ eglot-type-hint-face (defface eglot-parameter-hint-face '((t (:inherit eglot-inlay-hint-face))) "Face used for parameter inlay hint overlays.") -(defcustom eglot-lazy-inlay-hints 0.3 - "If non-nil, restrict LSP inlay hints to visible portion of the buffer. - -Value is a number specifying how many seconds to wait after a -window has been (re)scrolled before requesting new inlay hints -for the now-visible portion of the buffer shown in the window. - -If nil, then inlay hints are requested for the entire buffer. -This could be slow. - -This value is only meaningful if the minor mode -`eglot-inlay-hints-mode' is turned on in a buffer." - :type 'number - :version "29.1") - -(defun eglot--inlay-hints-fully () - (eglot--widening (eglot--update-hints-1 (point-min) (point-max)))) - -(cl-defun eglot--inlay-hints-lazily (&optional (buffer (current-buffer))) - (eglot--when-live-buffer buffer - (when eglot--managed-mode - (dolist (window (get-buffer-window-list nil nil 'visible)) - (eglot--update-hints-1 (window-start window) (window-end window)))))) +(defvar-local eglot--outstanding-inlay-hints-region (cons nil nil) + "Jit-lock-calculated (FROM . TO) region with potentially outdated hints") + +(defvar-local eglot--outstanding-inlay-regions-timer nil + "Helper timer for `eglot--update-hints'") + +(defun eglot--update-hints (from to) + "Jit-lock function for Eglot inlay hints." + (cl-symbol-macrolet ((region eglot--outstanding-inlay-hints-region) + (timer eglot--outstanding-inlay-regions-timer)) + (setcar region (min (or (car region) (point-max)) from)) + (setcdr region (max (or (cdr region) (point-min)) to)) + ;; HACK: We're relying on knowledge of jit-lock internals here. The + ;; condition comparing `jit-lock-context-unfontify-pos' to + ;; `point-max' is a heuristic for telling whether this call to + ;; `jit-lock-functions' happens after `jit-lock-context-timer' has + ;; just run. Only after this delay should we start the smoothing + ;; timer that will eventually call `eglot--update-hints-1' with the + ;; coalesced region. I wish we didn't need the timer, but sometimes + ;; a lot of "non-contextual" calls come in all at once and do verify + ;; the condition. Notice it is a 0 second timer though, so we're + ;; not introducing any more delay over jit-lock's timers. + (when (= jit-lock-context-unfontify-pos (point-max)) + (if timer (cancel-timer timer)) + (setq timer (run-at-time + 0 nil + (lambda () + (eglot--update-hints-1 (max (car region) (point-min)) + (min (cdr region) (point-max))) + (setq region (cons nil nil) timer nil))))))) (defun eglot--update-hints-1 (from to) - "Request LSP inlay hints and annotate current buffer from FROM to TO." + "Do most work for `eglot--update-hints', including LSP request." (let* ((buf (current-buffer)) (paint-hint (eglot--lambda ((InlayHint) position kind label paddingLeft paddingRight) @@ -3545,67 +3552,16 @@ eglot--update-hints-1 (mapc paint-hint hints)))) :deferred 'eglot--update-hints-1))) -(defun eglot--inlay-hints-after-scroll (window display-start) - (cl-macrolet ((wsetq (sym val) `(set-window-parameter window ',sym ,val)) - (wgetq (sym) `(window-parameter window ',sym))) - (let ((buf (window-buffer window)) - (timer (wgetq eglot--inlay-hints-timer)) - (last-display-start (wgetq eglot--last-inlay-hint-display-start))) - (when (and eglot-lazy-inlay-hints - ;; FIXME: If `window' is _not_ the selected window, - ;; then for some unknown reason probably related to - ;; the overlays added later to the buffer, the scroll - ;; function will be called indefinitely. Not sure if - ;; an Emacs bug, but prevent useless duplicate calls - ;; by saving and examining `display-start' fixes it. - (not (eql last-display-start display-start))) - (when timer (cancel-timer timer)) - (wsetq eglot--last-inlay-hint-display-start - display-start) - (wsetq eglot--inlay-hints-timer - (run-at-time - eglot-lazy-inlay-hints - nil (lambda () - (eglot--when-live-buffer buf - (when (eq buf (window-buffer window)) - (eglot--update-hints-1 (window-start window) - (window-end window)) - (wsetq eglot--inlay-hints-timer nil)))))))))) - -(defun eglot--inlay-hints-after-window-config-change () - (eglot--update-hints-1 (window-start) (window-end))) - (define-minor-mode eglot-inlay-hints-mode "Minor mode for annotating buffers with LSP server's inlay hints." :global nil (cond (eglot-inlay-hints-mode - (cond - ((not (eglot--server-capable :inlayHintProvider)) + (if (eglot--server-capable :inlayHintProvider) + (jit-lock-register #'eglot--update-hints 'contextual) (eglot--warn - "No :inlayHintProvider support. Inlay hints will not work.")) - (eglot-lazy-inlay-hints - (add-hook 'eglot--document-changed-hook - #'eglot--inlay-hints-lazily t t) - (add-hook 'window-scroll-functions - #'eglot--inlay-hints-after-scroll nil t) - (add-hook 'window-configuration-change-hook - #'eglot--inlay-hints-after-window-config-change nil t) - ;; Maybe there isn't a window yet for current buffer, - ;; so `run-at-time' ensures this runs after redisplay. - (run-at-time 0 nil #'eglot--inlay-hints-lazily)) - (t - (add-hook 'eglot--document-changed-hook - #'eglot--inlay-hints-fully nil t) - (eglot--inlay-hints-fully)))) + "No :inlayHintProvider support. Inlay hints will not work."))) (t - (remove-hook 'window-configuration-change-hook - #'eglot--inlay-hints-after-window-config-change) - (remove-hook 'eglot--document-changed-hook - #'eglot--inlay-hints-lazily t) - (remove-hook 'eglot--document-changed-hook - #'eglot--inlay-hints-fully t) - (remove-hook 'window-scroll-functions - #'eglot--inlay-hints-after-scroll t) + (jit-lock-unregister #'eglot--update-hints) (remove-overlays nil nil 'eglot--inlay-hint t)))) commit 0a361fd91abfc34cffad61fcc552a7cd64126f12 Author: Jim Porter Date: Thu Feb 23 15:13:38 2023 -0800 ; Return t or nil for 'test-completion' of Eshell user references * lisp/eshell/em-dirs.el (eshell-complete-user-reference): Simply call 'test-completion' when ACTION is 'lambda'; don't modify the result. diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el index b47bd12c0f0..eb679b80cb5 100644 --- a/lisp/eshell/em-dirs.el +++ b/lisp/eshell/em-dirs.el @@ -290,10 +290,10 @@ eshell-complete-user-reference (throw 'pcomplete-completions ;; Provide a programmed completion table. This works ;; just like completing over the list of names, except - ;; it always returns the completed string, never `t'. - ;; That's because this is only completing a directory - ;; name, and so the completion isn't actually finished - ;; yet. + ;; it always returns the completed string for + ;; `try-completion', never `t'. That's because this is + ;; only completing a directory name, and so the + ;; completion isn't actually finished yet. (lambda (string pred action) (pcase action ('nil ; try-completion @@ -302,8 +302,7 @@ eshell-complete-user-reference ('t ; all-completions (all-completions string names pred)) ('lambda ; test-completion - (let ((result (test-completion string names pred))) - (if (eq result t) string result))) + (test-completion string names pred)) ('metadata '(metadata (category . file))) (`(boundaries . ,suffix) commit da002af4116247ce63dcba414bc059457f6074e4 Author: Jim Porter Date: Thu Feb 23 14:14:01 2023 -0800 ; Remove commented-out leftover from the last commit * lisp/eshell/em-dirs.el (eshell-complete-user-reference): Remove commented code. diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el index 62d37e8f9fe..b47bd12c0f0 100644 --- a/lisp/eshell/em-dirs.el +++ b/lisp/eshell/em-dirs.el @@ -282,7 +282,6 @@ eshell-complete-user-reference (when (string-match "\\`~[a-z]*\\'" arg) (setq pcomplete-stub (substring arg 1) pcomplete-last-completion-raw t) - ;; pcomplete-exit-function #'eshell-complete-user-ref--exit) (eshell-read-user-names) (let ((names (pcomplete-uniquify-list (mapcar (lambda (user) commit 9d48c9844bf6b27fede6fe8f864e6dfb6909586b Author: Jim Porter Date: Wed Feb 1 17:48:47 2023 -0800 Don't add a space after the trailing slash when completing ~USER in Eshell This provides a programmed completion function that works similarly to ~USER completion in 'completion-file-name-table'. * lisp/eshell/em-dirs.el (eshell-complete-user-reference): Throw a programmed completion function. * test/lisp/eshell/em-cmpl-tests.el (em-cmpl-test/user-ref-completion): Update test. diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el index 0d02b64b084..62d37e8f9fe 100644 --- a/lisp/eshell/em-dirs.el +++ b/lisp/eshell/em-dirs.el @@ -281,15 +281,34 @@ eshell-complete-user-reference (let ((arg (pcomplete-actual-arg))) (when (string-match "\\`~[a-z]*\\'" arg) (setq pcomplete-stub (substring arg 1) - pcomplete-last-completion-raw t) - (throw 'pcomplete-completions - (progn - (eshell-read-user-names) - (pcomplete-uniquify-list - (mapcar - (lambda (user) - (file-name-as-directory (cdr user))) - eshell-user-names))))))) + pcomplete-last-completion-raw t) + ;; pcomplete-exit-function #'eshell-complete-user-ref--exit) + (eshell-read-user-names) + (let ((names (pcomplete-uniquify-list + (mapcar (lambda (user) + (file-name-as-directory (cdr user))) + eshell-user-names)))) + (throw 'pcomplete-completions + ;; Provide a programmed completion table. This works + ;; just like completing over the list of names, except + ;; it always returns the completed string, never `t'. + ;; That's because this is only completing a directory + ;; name, and so the completion isn't actually finished + ;; yet. + (lambda (string pred action) + (pcase action + ('nil ; try-completion + (let ((result (try-completion string names pred))) + (if (eq result t) string result))) + ('t ; all-completions + (all-completions string names pred)) + ('lambda ; test-completion + (let ((result (test-completion string names pred))) + (if (eq result t) string result))) + ('metadata + '(metadata (category . file))) + (`(boundaries . ,suffix) + `(boundaries 0 . ,(string-search "/" suffix)))))))))) (defun eshell/pwd (&rest _args) "Change output from `pwd' to be cleaner." diff --git a/test/lisp/eshell/em-cmpl-tests.el b/test/lisp/eshell/em-cmpl-tests.el index 1f8c571c44c..ecab7332822 100644 --- a/test/lisp/eshell/em-cmpl-tests.el +++ b/test/lisp/eshell/em-cmpl-tests.el @@ -218,15 +218,14 @@ em-cmpl-test/variable-assign-completion "VAR=file.txt "))))) (ert-deftest em-cmpl-test/user-ref-completion () - "Test completeion of user references like \"~user\". + "Test completion of user references like \"~user\". See ." (unwind-protect (with-temp-eshell (cl-letf (((symbol-function 'eshell-read-user-names) (lambda () (setq eshell-user-names '((1234 . "user")))))) - ;; FIXME: Should this really add a space at the end? (should (equal (eshell-insert-and-complete "echo ~us") - "echo ~user/ ")))) + "echo ~user/")))) ;; Clear the cached user names we set above. (setq eshell-user-names nil))) commit 4b364a990a06cd73b553fdc9e9a65bc7398dbea6 Author: Jim Porter Date: Wed Feb 1 17:48:43 2023 -0800 Add support for completing quoted variables in Eshell like $'FOO' This also adds the ability for Pcomplete handlers to set their own exit functions that will get called as appropriate. * lisp/pcomplete.el (pcomplete-default-exit-function): New function. (pcomplete-exit-function): New variable... (pcomplete-completions-at-point): ... let-bind and use it. * lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments): Handle quoted variables. We also build the 'posns' list from right-to-left now. * lisp/eshell/esh-var.el (eshell-envvar-names): Ensure that variable aliases are included in this list. (eshell-complete-variable-reference): Handle quoted variables and set the exit function on the completions. (eshell-variables-list): Simplify. We now add the trailing slash for directories in the exit function inside 'eshell-complete-variable-reference'. * test/lisp/eshell/em-cmpl-tests.el (em-cmpl-test/quoted-variable-ref-completion) (em-cmpl-test/variable-ref-completion/directory): New tests. diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el index 5625c53dc9b..5dfd10d6e4c 100644 --- a/lisp/eshell/em-cmpl.el +++ b/lisp/eshell/em-cmpl.el @@ -317,8 +317,7 @@ eshell-complete-parse-arguments (eshell--pcomplete-insert-tab)) (let ((end (point-marker)) (begin (save-excursion (beginning-of-line) (point))) - (posns (list t)) - args delim) + args posns delim) (when (and pcomplete-allow-modifications (memq this-command '(pcomplete-expand pcomplete-expand-and-complete))) @@ -333,18 +332,22 @@ eshell-complete-parse-arguments (cond ((member (car delim) '("{" "${" "$<")) (setq begin (1+ (cadr delim)) args (eshell-parse-arguments begin end))) + ((member (car delim) '("$'" "$\"")) + ;; Add the (incomplete) argument to our arguments, and + ;; note its position. + (setq args (append (nth 2 delim) (list (car delim)))) + (push (- (nth 1 delim) 2) posns)) ((member (car delim) '("(" "$(")) (throw 'pcompleted (elisp-completion-at-point))) (t (eshell--pcomplete-insert-tab)))) (when (get-text-property (1- end) 'comment) (eshell--pcomplete-insert-tab)) - (let ((pos begin)) - (while (< pos end) - (if (get-text-property pos 'arg-begin) - (nconc posns (list pos))) - (setq pos (1+ pos)))) - (setq posns (cdr posns)) + (let ((pos (1- end))) + (while (>= pos begin) + (when (get-text-property pos 'arg-begin) + (push pos posns)) + (setq pos (1- pos)))) (cl-assert (= (length args) (length posns))) (let ((a args) (i 0) new-start) (while a diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index a5bfbf4254d..0031324b537 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -434,9 +434,14 @@ eshell-insert-envvar (defun eshell-envvar-names (&optional environment) "Return a list of currently visible environment variable names." - (mapcar (lambda (x) - (substring x 0 (string-search "=" x))) - (or environment process-environment))) + (delete-dups + (append + ;; Real environment variables + (mapcar (lambda (x) + (substring x 0 (string-search "=" x))) + (or environment process-environment)) + ;; Eshell variable aliases + (mapcar #'car eshell-variable-aliases-list)))) (defun eshell-environment-variables () "Return a `process-environment', fully updated. @@ -820,33 +825,40 @@ eshell-complete-variable-reference (let ((arg (pcomplete-actual-arg))) (when (string-match (rx "$" (? (or "#" "@")) - (? (group (regexp eshell-variable-name-regexp))) - string-end) + (? (or (group-n 1 (regexp eshell-variable-name-regexp) + string-end) + (seq (group-n 2 (or "'" "\"")) + (group-n 1 (+ anychar)))))) arg) (setq pcomplete-stub (substring arg (match-beginning 1))) + (let ((delimiter (match-string 2 arg))) + ;; When finished with completion, insert the trailing + ;; delimiter, if any, and add a trailing slash if the variable + ;; refers to a directory. + (add-function + :before-until (var pcomplete-exit-function) + (lambda (variable status) + (when (eq status 'finished) + (when delimiter + (if (looking-at (regexp-quote delimiter)) + (goto-char (match-end 0)) + (insert delimiter))) + (let ((non-essential t) + (value (eshell-get-variable variable))) + (when (and (stringp value) (file-directory-p value)) + (insert "/") + ;; Tell Pcomplete not to insert its own termination + ;; string. + t)))))) (throw 'pcomplete-completions (eshell-variables-list))))) (defun eshell-variables-list () "Generate list of applicable variables." - (let ((argname pcomplete-stub) - completions) - (dolist (alias eshell-variable-aliases-list) - (if (string-match (concat "^" argname) (car alias)) - (setq completions (cons (car alias) completions)))) + (let ((argname pcomplete-stub)) (sort - (append - (mapcar - (lambda (varname) - (let ((value (eshell-get-variable varname))) - (if (and value - (stringp value) - (file-directory-p value)) - (concat varname "/") - varname))) - (eshell-envvar-names (eshell-environment-variables))) - (all-completions argname obarray 'boundp) - completions) - 'string-lessp))) + (append (eshell-envvar-names) + (all-completions argname obarray #'boundp)) + #'string-lessp))) (defun eshell-complete-variable-assignment () "If there is a variable assignment, allow completion of entries." diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el index 1ca7a213361..36f68f1af57 100644 --- a/lisp/pcomplete.el +++ b/lisp/pcomplete.el @@ -362,6 +362,32 @@ pcomplete-norm-func ;;; User Functions: +(defun pcomplete-default-exit-function (_s status) + "The default exit function to use in `pcomplete-completions-at-point'. +This just adds `pcomplete-termination-string' after the +completion if STATUS is `finished'." + (unless (zerop (length pcomplete-termination-string)) + (when (eq status 'finished) + (if (looking-at + (regexp-quote pcomplete-termination-string)) + (goto-char (match-end 0)) + (insert pcomplete-termination-string))))) + +(defvar pcomplete-exit-function #'pcomplete-default-exit-function + "The exit function to call in `pcomplete-completions-at-point'. + +This variable is let-bound in `pcomplete-completions-at-point', +so you can modify or advise it in order to adjust the behavior +for a specific completion. For example, you might do the +following in a `pcomplete-try-first-hook' function to insert a +trailing slash after a completion: + + (add-function + :before (var pcomplete-exit-function) + (lambda (_ status) + (when (eq status \\='finished) + (insert \"/\"))))") + ;;; Alternative front-end using the standard completion facilities. ;; The way pcomplete-parse-arguments and pcomplete-stub work only @@ -406,6 +432,7 @@ pcomplete-completions-at-point (if pcomplete-allow-modifications buffer-read-only t)) pcomplete-seen pcomplete-norm-func pcomplete-args pcomplete-last pcomplete-index + (pcomplete-exit-function pcomplete-exit-function) (pcomplete-autolist pcomplete-autolist) (pcomplete-suffix-list pcomplete-suffix-list) ;; Apparently the vars above are global vars modified by @@ -494,16 +521,7 @@ pcomplete-completions-at-point (get-text-property 0 'pcomplete-help cand))) :predicate pred :exit-function - ;; If completion is finished, add a terminating space. - ;; We used to also do this if STATUS is `sole', but - ;; that does not work right when completion cycling. - (unless (zerop (length pcomplete-termination-string)) - (lambda (_s status) - (when (eq status 'finished) - (if (looking-at - (regexp-quote pcomplete-termination-string)) - (goto-char (match-end 0)) - (insert pcomplete-termination-string))))))))))) + pcomplete-exit-function)))))) ;; I don't think such commands are usable before first setting up buffer-local ;; variables to parse args, so there's no point autoloading it. diff --git a/test/lisp/eshell/em-cmpl-tests.el b/test/lisp/eshell/em-cmpl-tests.el index 12a156fbb38..1f8c571c44c 100644 --- a/test/lisp/eshell/em-cmpl-tests.el +++ b/test/lisp/eshell/em-cmpl-tests.el @@ -183,6 +183,31 @@ em-cmpl-test/variable-ref-completion (should (equal (eshell-insert-and-complete "echo $system-nam") "echo $system-name ")))) +(ert-deftest em-cmpl-test/quoted-variable-ref-completion () + "Test completion of variable references like \"$'var'\". +See ." + (with-temp-eshell + (should (equal (eshell-insert-and-complete "echo $'system-nam") + "echo $'system-name' "))) + (with-temp-eshell + (should (equal (eshell-insert-and-complete "echo $\"system-nam") + "echo $\"system-name\" ")))) + +(ert-deftest em-cmpl-test/variable-ref-completion/directory () + "Test completion of variable references that expand to directories. +See ." + (with-temp-eshell + (should (equal (eshell-insert-and-complete "echo $PW") + "echo $PWD/"))) + (with-temp-eshell + (let ((minibuffer-message-timeout 0) + (inhibit-message t)) + (should (equal (eshell-insert-and-complete "echo $PWD") + "echo $PWD/")))) + (with-temp-eshell + (should (equal (eshell-insert-and-complete "echo $'PW") + "echo $'PWD'/")))) + (ert-deftest em-cmpl-test/variable-assign-completion () "Test completion of variable assignments like \"var=value\". See ." commit 2f110132d735b3a3db0c4ee29f2a7d49ff2525be Author: Jim Porter Date: Wed Feb 1 17:48:37 2023 -0800 ; Throw strings as the values for 'eshell-incomplete' This lets us distinguish between cases like "'foo" and "$'foo". * lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments): Use strings when checking the delimiter. * lisp/eshell/em-glob.el (eshell-parse-glob-chars): * lisp/eshell/em-pred.el (eshell-parse-arg-modifier): * lisp/eshell/esh-arg.el (eshell-parse-backslash) (eshell-parse-literal-quote, eshell-parse-double-quote) (eshell-parse-special-reference): * lisp/eshell/esh-cmd.el (eshell-parse-subcommand-argument) (eshell-parse-lisp-argument): * lisp/eshell/esh-var (eshell-parse-variable-ref) (eshell-parse-indices): Throw strings instead of characters. * lisp/eshell/esh-mode.el (eshell-parse-command-input): Print delimiter as a string. diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el index af8ac4278f1..5625c53dc9b 100644 --- a/lisp/eshell/em-cmpl.el +++ b/lisp/eshell/em-cmpl.el @@ -330,10 +330,10 @@ eshell-complete-parse-arguments (catch 'eshell-incomplete (ignore (setq args (eshell-parse-arguments begin end))))) - (cond ((memq (car delim) '(?\{ ?\<)) + (cond ((member (car delim) '("{" "${" "$<")) (setq begin (1+ (cadr delim)) args (eshell-parse-arguments begin end))) - ((eq (car delim) ?\() + ((member (car delim) '("(" "$(")) (throw 'pcompleted (elisp-completion-at-point))) (t (eshell--pcomplete-insert-tab)))) diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el index c7360fb246e..8a2ba13b2ad 100644 --- a/lisp/eshell/em-glob.el +++ b/lisp/eshell/em-glob.el @@ -171,7 +171,7 @@ eshell-parse-glob-chars (end (eshell-find-delimiter delim (if (eq delim ?\[) ?\] ?\))))) (if (not end) - (throw 'eshell-incomplete delim) + (throw 'eshell-incomplete (char-to-string delim)) (if (and (eshell-using-module 'eshell-pred) (eshell-arg-delimiter (1+ end))) (ignore (goto-char here)) diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el index 14fa27aba06..2ccca092b86 100644 --- a/lisp/eshell/em-pred.el +++ b/lisp/eshell/em-pred.el @@ -293,7 +293,7 @@ eshell-parse-arg-modifier (forward-char) (let ((end (eshell-find-delimiter ?\( ?\)))) (if (not end) - (throw 'eshell-incomplete ?\() + (throw 'eshell-incomplete "(") (when (eshell-arg-delimiter (1+ end)) (save-restriction (narrow-to-region (point) end) diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el index 6c882471aee..cb0b2e0938c 100644 --- a/lisp/eshell/esh-arg.el +++ b/lisp/eshell/esh-arg.el @@ -421,7 +421,7 @@ eshell-parse-backslash after are both returned." (when (eq (char-after) ?\\) (when (eshell-looking-at-backslash-return (point)) - (throw 'eshell-incomplete ?\\)) + (throw 'eshell-incomplete "\\")) (forward-char 2) ; Move one char past the backslash. (let ((special-chars (if eshell-current-quoted eshell-special-chars-inside-quoting @@ -447,7 +447,7 @@ eshell-parse-literal-quote (if (eq (char-after) ?\') (let ((end (eshell-find-delimiter ?\' ?\'))) (if (not end) - (throw 'eshell-incomplete ?\') + (throw 'eshell-incomplete "'") (let ((string (buffer-substring-no-properties (1+ (point)) end))) (goto-char (1+ end)) (while (string-match "''" string) @@ -460,7 +460,7 @@ eshell-parse-double-quote (let* ((end (eshell-find-delimiter ?\" ?\" nil nil t)) (eshell-current-quoted t)) (if (not end) - (throw 'eshell-incomplete ?\") + (throw 'eshell-incomplete "\"") (prog1 (save-restriction (forward-char) @@ -514,7 +514,7 @@ eshell-parse-special-reference t)) ;; buffer-p is non-nil by default. (end (eshell-find-delimiter ?\< ?\>))) (when (not end) - (throw 'eshell-incomplete ?\<)) + (throw 'eshell-incomplete "#<")) (if (eshell-arg-delimiter (1+ end)) (prog1 (list (if buffer-p 'get-buffer-create 'get-process) diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index efc46f10c96..d609711402a 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -681,7 +681,7 @@ eshell-parse-subcommand-argument (not (eq (char-after (1+ (point))) ?\})))) (let ((end (eshell-find-delimiter ?\{ ?\}))) (if (not end) - (throw 'eshell-incomplete ?\{) + (throw 'eshell-incomplete "{") (when (eshell-arg-delimiter (1+ end)) (prog1 `(eshell-as-subcommand @@ -698,7 +698,7 @@ eshell-parse-lisp-argument (condition-case nil (read (current-buffer)) (end-of-file - (throw 'eshell-incomplete ?\())))) + (throw 'eshell-incomplete "("))))) (if (eshell-arg-delimiter) `(eshell-command-to-value (eshell-lisp-command (quote ,obj))) diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el index b3cde472713..0c381dbb86a 100644 --- a/lisp/eshell/esh-mode.el +++ b/lisp/eshell/esh-mode.el @@ -580,7 +580,7 @@ eshell-parse-command-input (setq command (eshell-parse-command (cons beg end) args t))))) (ignore - (message "Expecting completion of delimiter %c ..." + (message "Expecting completion of delimiter %s ..." (if (listp delim) (car delim) delim))) diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index 60aab92b33e..a5bfbf4254d 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -503,7 +503,7 @@ eshell-parse-variable-ref ((eq (char-after) ?{) (let ((end (eshell-find-delimiter ?\{ ?\}))) (if (not end) - (throw 'eshell-incomplete ?\{) + (throw 'eshell-incomplete "${") (forward-char) (prog1 `(eshell-apply-indices @@ -527,7 +527,7 @@ eshell-parse-variable-ref ((eq (char-after) ?\<) (let ((end (eshell-find-delimiter ?\< ?\>))) (if (not end) - (throw 'eshell-incomplete ?\<) + (throw 'eshell-incomplete "$<") (let* ((temp (make-temp-file temporary-file-directory)) (cmd (concat (buffer-substring (1+ (point)) end) " > " temp))) @@ -560,15 +560,19 @@ eshell-parse-variable-ref (current-buffer))))) indices ,eshell-current-quoted) (end-of-file - (throw 'eshell-incomplete ?\()))) + (throw 'eshell-incomplete "$(")))) ((looking-at (rx-to-string `(or "'" ,(if eshell-current-quoted "\\\"" "\"")))) (eshell-with-temp-command (or (eshell-unescape-inner-double-quote (point-max)) (cons (point) (point-max))) - (let ((name (if (eq (char-after) ?\') - (eshell-parse-literal-quote) - (eshell-parse-double-quote)))) + (let (name) + (when-let ((delim + (catch 'eshell-incomplete + (ignore (setq name (if (eq (char-after) ?\') + (eshell-parse-literal-quote) + (eshell-parse-double-quote))))))) + (throw 'eshell-incomplete (concat "$" delim))) (when name `(eshell-get-variable ,(eval name) indices ,eshell-current-quoted))))) ((assoc (char-to-string (char-after)) @@ -597,7 +601,7 @@ eshell-parse-indices (while (eq (char-after) ?\[) (let ((end (eshell-find-delimiter ?\[ ?\]))) (if (not end) - (throw 'eshell-incomplete ?\[) + (throw 'eshell-incomplete "[") (forward-char) (eshell-with-temp-command (or (eshell-unescape-inner-double-quote end) (cons (point) end)) commit 91e24c5b5a69495bcd706a5287c05bb5fd282700 Author: João Távora Date: Thu Feb 23 19:18:41 2023 +0000 Eglot: update inlay hints on window configuration changes * lisp/progmodes/eglot.el (eglot--inlay-hints-after-window-config-change): New helper. (eglot-inlay-hints-mode): Use it. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 7b4251a1242..eea8be6d1aa 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -3572,6 +3572,9 @@ eglot--inlay-hints-after-scroll (window-end window)) (wsetq eglot--inlay-hints-timer nil)))))))))) +(defun eglot--inlay-hints-after-window-config-change () + (eglot--update-hints-1 (window-start) (window-end))) + (define-minor-mode eglot-inlay-hints-mode "Minor mode for annotating buffers with LSP server's inlay hints." :global nil @@ -3585,6 +3588,8 @@ eglot-inlay-hints-mode #'eglot--inlay-hints-lazily t t) (add-hook 'window-scroll-functions #'eglot--inlay-hints-after-scroll nil t) + (add-hook 'window-configuration-change-hook + #'eglot--inlay-hints-after-window-config-change nil t) ;; Maybe there isn't a window yet for current buffer, ;; so `run-at-time' ensures this runs after redisplay. (run-at-time 0 nil #'eglot--inlay-hints-lazily)) @@ -3593,6 +3598,8 @@ eglot-inlay-hints-mode #'eglot--inlay-hints-fully nil t) (eglot--inlay-hints-fully)))) (t + (remove-hook 'window-configuration-change-hook + #'eglot--inlay-hints-after-window-config-change) (remove-hook 'eglot--document-changed-hook #'eglot--inlay-hints-lazily t) (remove-hook 'eglot--document-changed-hook commit 79fead1709f8913b6e529c5f4734fcd0c08129c3 Author: Daniel Martín Date: Thu Feb 23 18:30:36 2023 +0100 ; Fix a typo in a doc string in c-ts-common.el (bug#61736). diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index 8262e6261d4..72df65a2287 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -268,7 +268,7 @@ c-ts-common-indent-offset statement indent functions to work.") (defvar c-ts-common-indent-type-regexp-alist nil - "An alist of of node type regexps. + "An alist of node type regexps. Each key in the alist is one of `if', `else', `do', `while', `for', `block', `close-bracket'. Each value in the alist commit a0b273ef300adabac0cb656fcc3657ebaf6ed528 Author: Eli Zaretskii Date: Thu Feb 23 17:45:52 2023 +0200 ; Clarify documentation of 'file-modes-number-to-symbolic' * doc/lispref/files.texi (Changing Files): * lisp/files.el (file-modes-number-to-symbolic): Clarify the confusion with "symbolic" forms of file modes. (Bug#61709) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 5062b1697b5..f8781d4895b 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -1985,7 +1985,11 @@ Changing Files @defun file-modes-number-to-symbolic modes This function converts a numeric file mode specification in -@var{modes} into the equivalent symbolic form. +@var{modes} into the equivalent string form. The string which this +function returns is in the same format produced by the shell command +@kbd{ls -l} and by @code{file-attributes}, @emph{not} the symbolic +form accepted by @code{file-modes-symbolic-to-number} and the +@command{chmod} shell command. @end defun @defun set-file-times filename &optional time flag diff --git a/lisp/files.el b/lisp/files.el index 57e01340359..db3f348c4b5 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -8391,11 +8391,14 @@ file-modes-rights-to-number num-rights)) (defun file-modes-number-to-symbolic (mode &optional filetype) - "Return a string describing a file's MODE. + "Return a description of a file's MODE as a string of 10 letters and dashes. +The returned string is like the mode description produced by \"ls -l\". For instance, if MODE is #o700, then it produces `-rwx------'. -FILETYPE if provided should be a character denoting the type of file, -such as `?d' for a directory, or `?l' for a symbolic link and will override -the leading `-' char." +Note that this is NOT the same as the \"chmod\" style symbolic description +accepted by `file-modes-symbolic-to-number'. +FILETYPE, if provided, should be a character denoting the type of file, +such as `?d' for a directory, or `?l' for a symbolic link, and will override +the leading `-' character." (string (or filetype (pcase (ash mode -12) commit 5c2be6a2632052b39b49899d1b19df2942ac6453 Author: Eli Zaretskii Date: Thu Feb 23 17:18:28 2023 +0200 ; Fix recently-added doc strings in eglot.el * lisp/progmodes/eglot.el (eglot-lazy-inlay-hints) (eglot-inlay-hints-mode): Doc fixes. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 7d61f6ad78e..7b4251a1242 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -3490,17 +3490,17 @@ eglot-parameter-hint-face "Face used for parameter inlay hint overlays.") (defcustom eglot-lazy-inlay-hints 0.3 - "If non-nil, restrict LSP inlay hints to visible portion of buffer. + "If non-nil, restrict LSP inlay hints to visible portion of the buffer. -Value is number specifying how many seconds to wait after a +Value is a number specifying how many seconds to wait after a window has been (re)scrolled before requesting new inlay hints -for the visible region of the window being manipulated. +for the now-visible portion of the buffer shown in the window. If nil, then inlay hints are requested for the entire buffer. +This could be slow. This value is only meaningful if the minor mode -`eglot-inlay-hints-mode' is true. -" +`eglot-inlay-hints-mode' is turned on in a buffer." :type 'number :version "29.1") @@ -3573,7 +3573,7 @@ eglot--inlay-hints-after-scroll (wsetq eglot--inlay-hints-timer nil)))))))))) (define-minor-mode eglot-inlay-hints-mode - "Minor mode annotating buffer with LSP inlay hints." + "Minor mode for annotating buffers with LSP server's inlay hints." :global nil (cond (eglot-inlay-hints-mode (cond commit 6411a9af03a4eb1a82db47a9642b11ba7edaaaf0 Author: andrés ramírez Date: Thu Feb 23 15:59:20 2023 +0100 Additional change for Bug#61432 * lisp/emulation/viper-cmd.el (viper-set-mode-vars-for): Check 'viper-enable-minibuffer-faces' before enabling minibuffer overlays. diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el index ee96d8efac6..2a37c383f81 100644 --- a/lisp/emulation/viper-cmd.el +++ b/lisp/emulation/viper-cmd.el @@ -574,7 +574,7 @@ viper-set-mode-vars-for ((memq state '(insert-state replace-state)) viper-minibuffer-insert-face)))) - (if (viper-is-in-minibuffer) + (if (and (viper-is-in-minibuffer) viper-enable-minibuffer-faces) (viper-set-minibuffer-overlay)) ) commit e3be0dbf85c729447776d361ba56ada6b92f0149 Author: João Távora Date: Thu Feb 23 13:58:38 2023 +0000 Eglot: display completion label when safe Originally reported in https://github.com/joaotavora/eglot/discussions/1141 by "Mintsoup". Eglot doesn't always show the LSP :label property of a CompletionItem in the completion candidates. That is because label is sometimes not what should be inserted in the buffer in the end, the :insertText property supercedes it. But the label is usually more suitable for display nevertheless and if the LSP CompletionItem contains either a snippet or a textEdit, it's safe to display the label, since :exit-function will guarantee that a suitable buffer insertion is performed. This change reflects that awareness that when a textEdit is available, it's acceptable to show the label. * lisp/progmodes/eglot.el (eglot-completion-at-point): Adjust. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index df755dfa43a..7d61f6ad78e 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2824,16 +2824,20 @@ eglot-completion-at-point (mapcar (jsonrpc-lambda (&rest item &key label insertText insertTextFormat - &allow-other-keys) + textEdit &allow-other-keys) (let ((proxy - (cond ((and (eql insertTextFormat 2) - (eglot--snippet-expansion-fn)) + ;; Snippet or textEdit, it's safe to + ;; display/insert the label since + ;; it'll be adjusted. If no usable + ;; insertText at all, label is best, + ;; too. + (cond ((or (and (eql insertTextFormat 2) + (eglot--snippet-expansion-fn)) + textEdit + (null insertText) + (string-empty-p insertText)) (string-trim-left label)) - ((and insertText - (not (string-empty-p insertText))) - insertText) - (t - (string-trim-left label))))) + (t insertText)))) (unless (zerop (length proxy)) (put-text-property 0 1 'eglot--lsp-item item proxy)) proxy)) commit 5286111ea1fe442d861cd4a940d86db3fd832139 Author: Eli Zaretskii Date: Thu Feb 23 14:26:06 2023 +0200 Improve documentation of VC commands, including in Dired * doc/emacs/dired.texi (Operating on Files): * doc/emacs/maintaining.texi (VC Change Log, VC Directory Mode) (Version Control, Basic VC Editing): Document VC command invocation from Dired buffers. Improve documentation of vc-log commands. * lisp/dired-aux.el (dired-vc-next-action): * lisp/vc/vc.el (vc-print-log, vc-log-search, vc-log-mergebase) (vc-log-view-type, vc-print-root-log, vc-next-action): Doc fixes. diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index 3f2c8d4afdf..77c4e09c826 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -715,6 +715,10 @@ Operating on Files Certain other Dired commands, such as @kbd{!} and the @samp{%} commands, use the same conventions to decide which files to work on. + In addition to Dired commands described here, you can also invoke +Version Control (VC) commands on one or more files shown in a Dired +buffer. @xref{Version Control}. + @vindex dired-dwim-target @cindex two directories (in Dired) Commands which ask for a destination directory, such as those which diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 8aee3380b71..f5bbc4d65c0 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -94,6 +94,20 @@ Version Control different version control system, or remove it from version control entirely. +@cindex VC commands, in Dired buffers +@cindex filesets, VC, in Dired buffers + VC is also enabled automatically in Dired buffers (@pxref{Dired}) +showing directories whose files are controlled by a VCS@. All VC +commands described in this section can be invoked from any Dired +buffer showing a directory with VC-controlled files; any files that +are marked in a Dired buffer (@pxref{Marks vs Flags}) are considered +to belong to the current fileset, and VC commands operate on the files +in this fileset. This allows you to construct VC filesets including +any files you want, regardless of their VC state. (If no files are +marked when a VC command is invoked from a Dired buffer, the file +shown on the current line in the buffer is considered the only file in +the fileset.) + @menu * Introduction to VC:: How version control works in general. * VC Mode Line:: How the mode line shows version control status. @@ -471,9 +485,10 @@ Basic VC Editing type VC commands in a buffer visiting a version-controlled file, the VC fileset is simply that one file. When you type them in a VC Directory buffer, and some files in it are marked, the VC fileset -consists of the marked files (@pxref{VC Directory Mode}). The VC -fileset also consists of the marked files in a Dired buffer -(@pxref{Dired}). +consists of the marked files (@pxref{VC Directory Mode}). Likewise, +when you invoke a VC command from a Dired buffer, the VC fileset +consists of the marked files (@pxref{Marks vs Flags}), defaulting to +the file shown on the current line if no files are marked. On modern changeset-based version control systems (@pxref{VCS Changesets}), VC commands handle multi-file VC filesets as a group. @@ -497,7 +512,9 @@ Basic VC Editing control system, or committing it, or unlocking it, or merging changes into it. The precise actions are described in detail in the following subsections. You can use @kbd{C-x v v} either in a file-visiting -buffer, in a Dired buffer, or in a VC Directory buffer. +buffer, in a Dired buffer, or in a VC Directory buffer; in the latter +two cases the command operates on the fileset consisting of the marked +files. Note that VC filesets are distinct from the named filesets used for viewing and visiting files in functional groups @@ -1002,16 +1019,25 @@ VC Change Log @findex vc-print-log @kbd{C-x v l} (@code{vc-print-log}) displays a buffer named @file{*vc-change-log*}, showing the history of changes made to the -current file, including who made the changes, the dates, and the log -entry for each change (these are the same log entries you would enter -via the @file{*vc-log*} buffer; @pxref{Log Buffer}). Point is -centered at the revision of the file currently being visited. With a -prefix argument, the command prompts for the revision to center on, -and the maximum number of revisions to display. - - If you call @kbd{C-x v l} from a VC Directory buffer (@pxref{VC -Directory Mode}) or a Dired buffer (@pxref{Dired}), it applies to the -file listed on the current line or to all the marked files. +current fileset in the long form, including who made the changes, the +dates, and the log entry for each change (these are the same log +entries you would enter via the @file{*vc-log*} buffer; @pxref{Log +Buffer}). When invoked from a buffer visiting a file, the current +fileset consists of that single file, and point in the displayed +@file{*vc-change-log*} buffer is centered at the revision of that +file. When invoked from a VC Directory buffer (@pxref{VC Directory +Mode}) or from a Dired buffer (@pxref{Dired}), the fileset consists of +all the marked files, defaulting to the file shown on the current line +in the directory buffer if no file is marked. + + If the fileset includes one or more directories, the resulting +@file{*vc-change-log*} buffer shows a short log of changes (one line +for each change), if the VC backend supports that; otherwise it shows +the log in the long form. + + With a prefix argument, the command prompts for the revision to +center on in the @file{*vc-change-log*} buffer and for the maximum +number of revisions to display. @kindex C-x v L @findex vc-print-root-log @@ -1217,6 +1243,11 @@ VC Directory Mode PCL-CVS, pcl-cvs, PCL-CVS---The Emacs Front-End to CVS}. @end ifnottex + You can also invoke VC commands from Dired buffers (@pxref{Dired}). +In that case, any VC command you invoke considers the marked files as +the current fileset (@pxref{Basic VC Editing}), defaulting to the file +on the current line if no files are marked. + @menu * Buffer: VC Directory Buffer. What the buffer looks like and means. * Commands: VC Directory Commands. Commands to use in a VC directory buffer. diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index c390017e190..fc3f6f4f04d 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -3741,12 +3741,21 @@ dired-show-file-type ;;;###autoload (defun dired-vc-next-action (verbose) - "Do the next version control operation on marked files/directories. -When only files are marked then call `vc-next-action' with the -same value of the VERBOSE argument. -When also directories are marked then call `vc-dir' and mark -the same files/directories in the VC-Dir buffer that were marked -in the Dired buffer." + "Do the next logical version control operation on marked files/directories. +The VC control operation will operate on a fileset which includes +the marked files/directories. If no files/directories are marked, the +fileset will include the single file/directory shown on the current line. + +If only regular files are in the fileset, call `vc-next-action' with +the same value of the VERBOSE argument (interactively, the prefix +argument). + +If one or more directories are in the fileset, start `vc-dir' in the root +directory of the repository that includes the current directory, with +the same files/directories marked in the VC-Directory buffer that were +marked in the original Dired buffer. If the current directory doesn't +belong to a VCS repository, prompt for a repository directory. In this +case, the VERBOSE argument is ignored." (interactive "P") (let* ((marked-files (dired-get-marked-files nil nil nil nil t)) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 4ba62c0b3c7..0e3519e2e5c 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -1239,7 +1239,11 @@ vc-next-action When using this command to register a new file (or files), it will automatically deduce which VC repository to register it -with, using the most specific one." +with, using the most specific one. + +If VERBOSE is non-nil (interactively, the prefix argument), +you can specify a VC backend or (for centralized VCS only) +the revision ID or branch ID." (interactive "P") (let* ((vc-fileset (vc-deduce-fileset nil t 'state-model-only-files)) (backend (car vc-fileset)) @@ -2696,7 +2700,16 @@ vc-print-log-internal is-start-revision limit type))))) (defvar vc-log-view-type nil - "Set this to differentiate the different types of logs.") + "Set this to record the type of VC log shown in the current buffer. +Supported values are: + + `short' -- short log form, one line for each commit + `long' -- long log form, including full log message and author + `with-diff' -- log including diffs + `log-outgoing' -- log of changes to be pushed to upstream + `log-incoming' -- log of changes to be brought by pulling from upstream + `log-search' -- log entries matching a pattern; shown in long format + `mergebase' -- log created by `vc-log-mergebase'.") (put 'vc-log-view-type 'permanent-local t) (defvar vc-sentinel-movepoint) @@ -2753,13 +2766,20 @@ vc-incoming-outgoing-internal ;;;###autoload (defun vc-print-log (&optional working-revision limit) - "List the change log of the current fileset in a window. -If WORKING-REVISION is non-nil, leave point at that revision. + "Show in another window the VC change history of the current fileset. +If WORKING-REVISION is non-nil, it should be a revision ID; position +point in the change history buffer at that revision. If LIMIT is non-nil, it should be a number specifying the maximum number of revisions to show; the default is `vc-log-show-limit'. When called interactively with a prefix argument, prompt for -WORKING-REVISION and LIMIT." +WORKING-REVISION and LIMIT. + +This shows a short log (one line for each commit) if the current +fileset includes directories and the VC backend supports that; +otherwise it shows the detailed log of each commit, which includes +the full log message and the author. Additional control of the +shown log style is available via `vc-log-short-style'." (interactive (cond (current-prefix-arg @@ -2784,14 +2804,14 @@ vc-print-log ;;;###autoload (defun vc-print-root-log (&optional limit revision) - "List the revision history for the current VC controlled tree in a window. + "Show in another window VC change history of the current VC controlled tree. If LIMIT is non-nil, it should be a number specifying the maximum number of revisions to show; the default is `vc-log-show-limit'. -When called interactively with a prefix argument, prompt for LIMIT. -When the prefix argument is a number, use it as LIMIT. +When called interactively with a prefix argument, prompt for LIMIT, but +if the prefix argument is a number, use it as LIMIT. A special case is when the prefix argument is 1: in this case -the command asks for the ID of a revision, and shows that revision -with its diffs (if the underlying VCS supports that)." +the command prompts for the ID of a revision, and shows that revision +with its diffs (if the underlying VCS backend supports that)." (interactive (cond ((eq current-prefix-arg 1) @@ -2875,15 +2895,17 @@ vc-log-outgoing ;;;###autoload (defun vc-log-search (pattern) - "Search the log of changes for PATTERN. + "Search the VC log of changes for PATTERN and show log of matching changes. PATTERN is usually interpreted as a regular expression. However, its exact semantics is up to the backend's log search command; some can only match fixed strings. -Display all entries that match log messages in long format. -With a prefix argument, ask for a command to run that will output -log entries." +This command displays in long format all the changes whose log messages +match PATTERN. + +With a prefix argument, the command asks for a shell command to run that +will output log entries, and displays those log entries instead." (interactive (list (unless current-prefix-arg (read-regexp "Search log with pattern: ")))) (let ((backend (vc-deduce-backend))) @@ -2894,8 +2916,8 @@ vc-log-search ;;;###autoload (defun vc-log-mergebase (_files rev1 rev2) - "Show a log of changes between the merge base of REV1 and REV2 revisions. -The merge base is a common ancestor between REV1 and REV2 revisions." + "Show a log of changes between the merge base of revisions REV1 and REV2. +The merge base is a common ancestor of revisions REV1 and REV2." (interactive (vc-diff-build-argument-list-internal (or (ignore-errors (vc-deduce-fileset t)) commit 990f4027131e4ff7d83db23d82de0d47f64d288e Author: Juri Linkov Date: Thu Feb 23 10:23:41 2023 +0200 * doc/emacs/maintaining.texi: More mentions of marked files in Dired. (Basic VC Editing, Old Revisions, VC Change Log): Add more mentions of ability to include the marked files to the VC fileset in Dired (bug#61712). diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 5191bb2918d..8aee3380b71 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -471,7 +471,9 @@ Basic VC Editing type VC commands in a buffer visiting a version-controlled file, the VC fileset is simply that one file. When you type them in a VC Directory buffer, and some files in it are marked, the VC fileset -consists of the marked files (@pxref{VC Directory Mode}). +consists of the marked files (@pxref{VC Directory Mode}). The VC +fileset also consists of the marked files in a Dired buffer +(@pxref{Dired}). On modern changeset-based version control systems (@pxref{VCS Changesets}), VC commands handle multi-file VC filesets as a group. @@ -840,7 +842,7 @@ Old Revisions If you invoke @kbd{C-x v =} or @kbd{C-u C-x v =} from a Dired buffer (@pxref{Dired}), the file listed on the current line is treated as the -current VC fileset. +current VC fileset. The VC fileset can also include several marked files. @ifnottex @findex vc-ediff @@ -1009,7 +1011,7 @@ VC Change Log If you call @kbd{C-x v l} from a VC Directory buffer (@pxref{VC Directory Mode}) or a Dired buffer (@pxref{Dired}), it applies to the -file listed on the current line. +file listed on the current line or to all the marked files. @kindex C-x v L @findex vc-print-root-log