VC-Dir next action: Offer to hide up-to-date items

* lisp/vc/vc-dir.el (vc-dir--up-to-date-states): New constant.
(vc-dir-hide-state): Use it.
(vc-dir--only-files-state-and-model): New function.
(vc-dir-root-next-action, vc-dir-deduce-fileset): Use it.
* lisp/vc/vc.el (vc-only-files-state-and-model): Improve error
message readability.
This commit is contained in:
Sean Whitton
2026-04-05 14:58:55 +01:00
parent 859e0622ae
commit af69eb2f27
2 changed files with 44 additions and 16 deletions

View File

@@ -1028,8 +1028,7 @@ is), this command is useful to check in all local changes at once."
(vc-buffer-overriding-fileset (vc-buffer-overriding-fileset
`(,vc-dir-backend `(,vc-dir-backend
(,default-directory) (,default-directory)
. ,(vc-only-files-state-and-model only-files-list . ,(vc-dir--only-files-state-and-model only-files-list))))
vc-dir-backend))))
(vc-next-action nil))) (vc-next-action nil)))
(defun vc-dir-clean-files () (defun vc-dir-clean-files ()
@@ -1531,6 +1530,8 @@ outside of VC) and one wants to do some operation on it."
(interactive "fShow file: ") (interactive "fShow file: ")
(vc-dir-update (list (list (file-relative-name file) (vc-state file))) (current-buffer))) (vc-dir-update (list (list (file-relative-name file) (vc-state file))) (current-buffer)))
(defconst vc-dir--up-to-date-states '(up-to-date ignored))
(defun vc-dir-hide-state (&optional state) (defun vc-dir-hide-state (&optional state)
"Hide items that are in STATE from display. "Hide items that are in STATE from display.
See `vc-state' for valid values of STATE. See `vc-state' for valid values of STATE.
@@ -1568,9 +1569,10 @@ state of item at point, if any."
(vc-dir-fileinfo->directory (ewoc-data next)))) (vc-dir-fileinfo->directory (ewoc-data next))))
;; Remove files in specified STATE. STATE can be a ;; Remove files in specified STATE. STATE can be a
;; symbol, a user-name, or nil. ;; symbol, a user-name, or nil.
(if state (let ((data-state (vc-dir-fileinfo->state data)))
(equal (vc-dir-fileinfo->state data) state) (if state
(memq (vc-dir-fileinfo->state data) '(up-to-date ignored)))) (equal data-state state)
(memq data-state vc-dir--up-to-date-states))))
(ewoc-delete vc-ewoc crt)) (ewoc-delete vc-ewoc crt))
(setq crt prev))))) (setq crt prev)))))
@@ -1588,22 +1590,46 @@ state of item at point, if any."
(declare-function vc-only-files-state-and-model "vc") (declare-function vc-only-files-state-and-model "vc")
(defun vc-dir--only-files-state-and-model (only-files-list)
"Call `vc-only-files-state-and-model' as appropriate for VC-Dir buffers.
Offer to call `vc-dir-hide-up-to-date' if that might be useful.
If we did, remove up-to-date items from ONLY-FILES-LIST before passing
to `vc-only-files-state-and-model'.
There's usually no action to be taken on `up-to-date' or `ignored'
files, but a new user may include these in their VC-Dir fileset without
realizing it. To avoid the user having to know in advance that what
they must do is invoke \\<vc-dir-mode-map>\\[vc-dir-hide-up-to-date] \
before \\[vc-next-action], offer to invoke `vc-dir-hide-up-to-date'
for them, and also filter ONLY-FILES-LIST so as not to include entries
in those states. Only do this if there are both up-to-date and
non-up-to-date files in ONLY-FILES-LIST (in case we add a VC next action
for `up-to-date' and/or `ignored' files at some point)."
(let (up-to-date other)
(dolist (entry only-files-list)
(push entry (if (memq (cdr entry) vc-dir--up-to-date-states)
up-to-date other)))
(vc-only-files-state-and-model
(if (or (null up-to-date) (null other)
(not (y-or-n-p "Clear up-to-date items before proceeding?")))
only-files-list
(vc-dir-hide-up-to-date)
other)
vc-dir-backend)))
(defun vc-dir-deduce-fileset (&optional state-model-only-files) (defun vc-dir-deduce-fileset (&optional state-model-only-files)
(let ((marked (vc-dir-marked-files)) (let (files only-files-list)
files only-files-list) (if-let* ((marked (vc-dir-marked-files)))
(if marked
(progn (progn
(setq files marked) (setq files marked)
(when state-model-only-files (when state-model-only-files
(setq only-files-list (vc-dir-marked-only-files-and-states)))) (setq only-files-list (vc-dir-marked-only-files-and-states))))
(let ((crt (vc-dir-current-file))) (setq files (list (vc-dir-current-file)))
(setq files (list crt)) (when state-model-only-files
(when state-model-only-files (setq only-files-list (vc-dir-child-files-and-states))))
(setq only-files-list (vc-dir-child-files-and-states)))))
(if state-model-only-files (if state-model-only-files
(cl-list* vc-dir-backend files (cl-list* vc-dir-backend files
(vc-only-files-state-and-model only-files-list (vc-dir--only-files-state-and-model only-files-list))
vc-dir-backend))
(list vc-dir-backend files)))) (list vc-dir-backend files))))
;;;###autoload ;;;###autoload

View File

@@ -1596,8 +1596,10 @@ Some files are unregistered; register them before checking in?"))
(cadr other-alist)))) (cadr other-alist))))
(error "\ (error "\
To apply VC operations to multiple files, the files must be in similar VC states. To apply VC operations to multiple files, the files must be in similar VC states.
%s in state %s clashes with %s in state %s" %s in state `%s' clashes with
(cadr first) (car first) (cadr second) (car second))))) %s in state `%s'"
(abbreviate-file-name (cadr first)) (car first)
(abbreviate-file-name (cadr second)) (car second)))))
(list files* state (list files* state
(and state (not (eq state 'unregistered)) (and state (not (eq state 'unregistered))
(vc-checkout-model backend files*))))) (vc-checkout-model backend files*)))))