emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/git-commit f0296148a6 2/2: Support acting on entries in re


From: ELPA Syncer
Subject: [nongnu] elpa/git-commit f0296148a6 2/2: Support acting on entries in repolist buffers
Date: Sun, 20 Feb 2022 12:58:01 -0500 (EST)

branch: elpa/git-commit
commit f0296148a64f8058f920e3ae90c418087c966344
Author: Jonas Bernoulli <jonas@bernoul.li>
Commit: Jonas Bernoulli <jonas@bernoul.li>

    Support acting on entries in repolist buffers
    
    Closes #4453.
---
 docs/magit.org      | 28 ++++++++++++++++
 docs/magit.texi     | 35 ++++++++++++++++++++
 lisp/magit-repos.el | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 156 insertions(+)

diff --git a/docs/magit.org b/docs/magit.org
index c671c67590..bd0d5ccd18 100644
--- a/docs/magit.org
+++ b/docs/magit.org
@@ -2494,6 +2494,7 @@ buffers.
   and set ~:pad-right~ to 0.  ~+~ is substituted for numbers higher
   than 9.
 
+#+texinfo: @noindent
 The following functions can be added to the above option:
 
 - Function: magit-repolist-column-ident ::
@@ -2559,6 +2560,33 @@ The following functions can be added to the above option:
   This function inserts the number of commits in the current branch
   but not its push branch.
 
+#+texinfo: @noindent
+The following commands are available in repolist buffers:
+
+- Key: RET (magit-repolist-status) ::
+
+  This command shows the status for the repository at point.
+
+- Key: m (magit-repolist-mark) ::
+
+  This command marks the repository at point.
+
+- Key: u (magit-repolist-unmark) ::
+
+  This command unmarks the repository at point.
+
+- Key: f (magit-repolist-fetch) ::
+
+  This command fetches all marked repositories.  If no repositories
+  are marked, then it offers to fetch all displayed repositories.
+
+- Key: 5 (magit-repolist-find-file-other-frame) ::
+
+  This command reads a relative file-name (without completion) and
+  opens the respective file in each marked repository in a new frame.
+  If no repositories are marked, then it offers to do this for all
+  displayed repositories.
+
 ** Logging
 
 The status buffer contains logs for the unpushed and unpulled commits,
diff --git a/docs/magit.texi b/docs/magit.texi
index 6e3d787dd4..0a8028fbb5 100644
--- a/docs/magit.texi
+++ b/docs/magit.texi
@@ -3108,6 +3108,7 @@ and set @code{:pad-right} to 0.  @code{+} is substituted 
for numbers higher
 than 9.
 @end defopt
 
+@noindent
 The following functions can be added to the above option:
 
 @defun magit-repolist-column-ident
@@ -3178,6 +3179,40 @@ This function inserts the number of commits in the 
current branch
 but not its push branch.
 @end defun
 
+@noindent
+The following commands are available in repolist buffers:
+
+@table @asis
+@item @kbd{@key{RET}} (@code{magit-repolist-status})
+@kindex RET
+@findex magit-repolist-status
+This command shows the status for the repository at point.
+
+@item @kbd{m} (@code{magit-repolist-mark})
+@kindex m
+@findex magit-repolist-mark
+This command marks the repository at point.
+
+@item @kbd{u} (@code{magit-repolist-unmark})
+@kindex u
+@findex magit-repolist-unmark
+This command unmarks the repository at point.
+
+@item @kbd{f} (@code{magit-repolist-fetch})
+@kindex f
+@findex magit-repolist-fetch
+This command fetches all marked repositories.  If no repositories
+are marked, then it offers to fetch all displayed repositories.
+
+@item @kbd{5} (@code{magit-repolist-find-file-other-frame})
+@kindex 5
+@findex magit-repolist-find-file-other-frame
+This command reads a relative file-name (without completion) and
+opens the respective file in each marked repository in a new frame.
+If no repositories are marked, then it offers to do this for all
+displayed repositories.
+@end table
+
 @node Logging
 @section Logging
 
diff --git a/lisp/magit-repos.el b/lisp/magit-repos.el
index 8997a1a9ff..684c838d73 100644
--- a/lisp/magit-repos.el
+++ b/lisp/magit-repos.el
@@ -156,12 +156,105 @@ repositories are displayed."
       (magit-status-setup-buffer (expand-file-name it))
     (user-error "There is no repository at point")))
 
+(defun magit-repolist-mark ()
+  "Mark a repository and move to the next line."
+  (interactive)
+  (magit-repolist--ensure-padding)
+  (tabulated-list-put-tag "*" t))
+
+(defun magit-repolist-unmark ()
+  "Unmark a repository and move to the next line."
+  (interactive)
+  (tabulated-list-put-tag " " t))
+
+(defun magit-repolist-fetch (repos)
+  "Fetch all marked or listed repositories."
+  (interactive (list (magit-repolist--get-repos ?*)))
+  (run-hooks 'magit-credential-hook)
+  (magit-repolist--mapc (apply-partially #'magit-run-git "remote" "update")
+                        repos "Fetching in %s..."))
+
+(defun magit-repolist-find-file-other-frame (repos file)
+  "Find a file in all marked or listed repositories."
+  (interactive (list (magit-repolist--get-repos ?*)
+                     (read-string "Find file in repositories: ")))
+  (magit-repolist--mapc (apply-partially #'find-file-other-frame file) repos))
+
+(defun magit-repolist--ensure-padding ()
+  "Set `tabulated-list-padding' to 2, unless that is already non-zero."
+  (when (zerop tabulated-list-padding)
+    (setq tabulated-list-padding 2)
+    (tabulated-list-init-header)
+    (tabulated-list-print t)))
+
+(defun magit-repolist--get-repos (&optional char)
+  "Return marked repositories or `all' if none are marked.
+If optional CHAR is non-nil, then only return repositories
+marked with that character.  If no repositories are marked
+then ask whether to act on all repositories instead."
+  (or (magit-repolist--marked-repos char)
+      (if (magit-confirm 'repolist-all
+            "Nothing selected.  Act on ALL displayed repositories")
+          'all
+        (user-error "Abort"))))
+
+(defun magit-repolist--marked-repos (&optional char)
+  "Return marked repositories.
+If optional CHAR is non-nil, then only return repositories
+marked with that character."
+  (let (c list)
+    (save-excursion
+      (goto-char (point-min))
+      (while (not (eobp))
+        (setq c (char-after))
+        (unless (eq c ?\s)
+          (if char
+              (when (eq c char)
+                (push (tabulated-list-get-id) list))
+            (push (cons c (tabulated-list-get-id)) list)))
+        (forward-line)))
+    list))
+
+(defun magit-repolist--mapc (fn repos &optional msg)
+  "Apply FN to each directory in REPOS for side effects only.
+If REPOS is the symbol `all', then call FN for all displayed
+repositories.  When FN is called, `default-directory' is bound to
+the top-level directory of the current repository.  If optional
+MSG is non-nil then that is displayed around each call to FN.
+If it contains \"%s\" then the directory is substituted for that."
+  (when (eq repos 'all)
+    (setq repos nil)
+    (save-excursion
+      (goto-char (point-min))
+      (while (not (eobp))
+        (push (tabulated-list-get-id) repos)
+        (forward-line)))
+    (setq repos (nreverse repos)))
+  (let ((base default-directory)
+        (len (length repos))
+        (i 0))
+    (mapc (lambda (repo)
+            (let ((default-directory
+                   (file-name-as-directory (expand-file-name repo base))))
+              (if msg
+                  (let ((msg (concat (format "(%s/%s) " (cl-incf i) len)
+                                     (format msg default-directory))))
+                    (message msg)
+                    (funcall fn)
+                    (message (concat msg "done")))
+                (funcall fn))))
+          repos)))
+
 ;;;; Mode
 
 (defvar magit-repolist-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map tabulated-list-mode-map)
     (define-key map (kbd "C-m") 'magit-repolist-status)
+    (define-key map (kbd "m")   'magit-repolist-mark)
+    (define-key map (kbd "u")   'magit-repolist-unmark)
+    (define-key map (kbd "f")   'magit-repolist-fetch)
+    (define-key map (kbd "5")   'magit-repolist-find-file-other-frame)
     map)
   "Local keymap for Magit-Repolist mode buffers.")
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]