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

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

[nongnu] elpa/git-commit 4727dcbe22 04/10: Refactor Imenu support


From: ELPA Syncer
Subject: [nongnu] elpa/git-commit 4727dcbe22 04/10: Refactor Imenu support
Date: Tue, 22 Feb 2022 08:58:19 -0500 (EST)

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

    Refactor Imenu support
    
    The old implementation was heavily inspired by Imenu's generic
    create-index function.  The new implementation takes advantage of
    our knowledge about the section hierarchy to accomplish the same
    thing using much less code.
---
 lisp/magit-diff.el    |   5 +-
 lisp/magit-imenu.el   | 151 --------------------------------------------------
 lisp/magit-log.el     |   8 +--
 lisp/magit-mode.el    |  49 ++++++++++++++++
 lisp/magit-process.el |   5 +-
 lisp/magit-reflog.el  |   3 +-
 lisp/magit-refs.el    |   3 +-
 lisp/magit-section.el |  21 -------
 lisp/magit-stash.el   |   3 +-
 lisp/magit-status.el  |   4 +-
 10 files changed, 60 insertions(+), 192 deletions(-)

diff --git a/lisp/magit-diff.el b/lisp/magit-diff.el
index 4549b12239..1306c4f270 100644
--- a/lisp/magit-diff.el
+++ b/lisp/magit-diff.el
@@ -1879,10 +1879,7 @@ Staging and applying changes is documented in info node
 \\{magit-diff-mode-map}"
   :group 'magit-diff
   (hack-dir-local-variables-non-file-buffer)
-  (setq imenu-prev-index-position-function
-        'magit-imenu--diff-prev-index-position-function)
-  (setq imenu-extract-index-name-function
-        'magit-imenu--diff-extract-index-name-function))
+  (setq magit--imenu-item-types 'file))
 
 (put 'magit-diff-mode 'magit-diff-default-arguments
      '("--stat" "--no-ext-diff"))
diff --git a/lisp/magit-imenu.el b/lisp/magit-imenu.el
index fad04deccf..a551fa3091 100644
--- a/lisp/magit-imenu.el
+++ b/lisp/magit-imenu.el
@@ -31,142 +31,11 @@
 ;; a programming major mode).  Selecting an item from this list moves
 ;; point to this item.
 
-;; magit-imenu.el adds Imenu support to every major mode in Magit.
-
 ;;; Code:
 
 (require 'magit)
 (require 'git-rebase)
 
-;;; Core
-
-(defun magit-imenu--index-function (entry-types menu-types)
-  "Return an alist of imenu entries in current buffer.
-
-ENTRY-TYPES is a list of section types to be selected through
-`imenu'.
-
-MENU-TYPES is a list of section types containing elements of
-ENTRY-TYPES.  Elements of MENU-TYPES are used to categorize
-elements of ENTRY-TYPES.
-
-This function is used as a helper for functions set as
-`imenu-create-index-function'."
-  ;; If `which-function-mode' is active, then the create-index
-  ;; function is called at the time the major-mode is being enabled.
-  ;; Modes that derive from `magit-mode' have not populated the buffer
-  ;; at that time yet, so we have to abort.
-  (when-let ((section (magit-current-section))
-             (entries (make-hash-table :test 'equal)))
-    (goto-char (point-max))
-    (unless (oref section parent)
-      (forward-line -1))
-    (while (magit-section--backward-find
-            (lambda ()
-              (let* ((section (magit-current-section))
-                     (type (oref section type))
-                     (parent (oref section parent))
-                     (parent-type (oref parent type)))
-                (and (memq type entry-types)
-                     (memq parent-type menu-types)))))
-      (let* ((section (magit-current-section))
-             (name (buffer-substring-no-properties
-                    (line-beginning-position)
-                    (line-end-position)))
-             (parent (oref section parent))
-             (parent-title (buffer-substring-no-properties
-                            (oref parent start)
-                            (1- (oref parent content)))))
-        (when (string-match " ([0-9]*)\\'" parent-title)
-          (setq parent-title (substring parent-title 0 (match-beginning 0))))
-        (puthash parent-title
-                 (cons (cons name (point))
-                       (gethash parent-title entries (list)))
-                 entries)))
-    (mapcar (lambda (menu-title)
-              (cons menu-title (gethash menu-title entries)))
-            (hash-table-keys entries))))
-
-;;; Log mode
-
-;;;###autoload
-(defun magit-imenu--log-prev-index-position-function ()
-  "Move point to previous line in current buffer.
-This function is used as a value for
-`imenu-prev-index-position-function'."
-  (magit-section--backward-find
-   (lambda ()
-     (-contains-p '(commit stash)
-                  (oref (magit-current-section) type)))))
-
-;;;###autoload
-(defun magit-imenu--log-extract-index-name-function ()
-  "Return imenu name for line at point.
-This function is used as a value for
-`imenu-extract-index-name-function'.  Point should be at the
-beginning of the line."
-  (save-match-data
-    (looking-at "\\([^ ]+\\)[ *|]+\\(.+\\)$")
-    (format "%s: %s"
-            (match-string-no-properties 1)
-            (match-string-no-properties 2))))
-
-;;; Diff mode
-
-;;;###autoload
-(defun magit-imenu--diff-prev-index-position-function ()
-  "Move point to previous file line in current buffer.
-This function is used as a value for
-`imenu-prev-index-position-function'."
-  (magit-section--backward-find
-   (lambda ()
-     (let ((section (magit-current-section)))
-       (and (magit-file-section-p section)
-            (not (equal (oref (oref section parent) type)
-                        'diffstat)))))))
-
-;;;###autoload
-(defun magit-imenu--diff-extract-index-name-function ()
-  "Return imenu name for line at point.
-This function is used as a value for
-`imenu-extract-index-name-function'.  Point should be at the
-beginning of the line."
-  (buffer-substring-no-properties (line-beginning-position)
-                                  (line-end-position)))
-
-;;; Status mode
-
-;;;###autoload
-(defun magit-imenu--status-create-index-function ()
-  "Return an alist of all imenu entries in current buffer.
-This function is used as a value for
-`imenu-create-index-function'."
-  (magit-imenu--index-function
-   '(file commit stash pullreq issue)
-   '(unpushed unstaged unpulled untracked staged stashes pullreqs issues)))
-
-;;; Refs mode
-
-;;;###autoload
-(defun magit-imenu--refs-create-index-function ()
-  "Return an alist of all imenu entries in current buffer.
-This function is used as a value for
-`imenu-create-index-function'."
-  (magit-imenu--index-function
-   '(branch commit tag)
-   '(local remote tags)))
-
-;;; Cherry mode
-
-;;;###autoload
-(defun magit-imenu--cherry-create-index-function ()
-  "Return an alist of all imenu entries in current buffer.
-This function is used as a value for
-`imenu-create-index-function'."
-  (magit-imenu--index-function
-   '(commit)
-   '(cherries)))
-
 ;;; Submodule list mode
 
 ;;;###autoload
@@ -206,26 +75,6 @@ beginning of the line."
             (elt entry 0)
             (elt entry (1- (length entry))))))
 
-;;; Process mode
-
-;;;###autoload
-(defun magit-imenu--process-prev-index-position-function ()
-  "Move point to previous process in magit-process buffer.
-This function is used as a value for
-`imenu-prev-index-position-function'."
-  (magit-section--backward-find
-   (lambda ()
-     (eq (oref (magit-current-section) type) 'process))))
-
-;;;###autoload
-(defun magit-imenu--process-extract-index-name-function ()
-  "Return imenu name for line at point.
-This function is used as a value for
-`imenu-extract-index-name-function'.  Point should be at the
-beginning of the line."
-  (buffer-substring-no-properties (line-beginning-position)
-                                  (line-end-position)))
-
 ;;; Rebase mode
 
 ;;;###autoload
diff --git a/lisp/magit-log.el b/lisp/magit-log.el
index 849578d8d5..32b8e38d92 100644
--- a/lisp/magit-log.el
+++ b/lisp/magit-log.el
@@ -1026,10 +1026,7 @@ Type \\[magit-reset] to reset `HEAD' to the commit at 
point.
 \\{magit-log-mode-map}"
   :group 'magit-log
   (hack-dir-local-variables-non-file-buffer)
-  (setq imenu-prev-index-position-function
-        'magit-imenu--log-prev-index-position-function)
-  (setq imenu-extract-index-name-function
-        'magit-imenu--log-extract-index-name-function))
+  (setq magit--imenu-item-types 'commit))
 
 (put 'magit-log-mode 'magit-log-default-arguments
      '("--graph" "-n256" "--decorate"))
@@ -1700,8 +1697,7 @@ Type \\[magit-cherry-pick] to apply the commit at point.
 \\{magit-cherry-mode-map}"
   :group 'magit-log
   (hack-dir-local-variables-non-file-buffer)
-  (setq imenu-create-index-function
-        'magit-imenu--cherry-create-index-function))
+  (setq magit--imenu-group-types 'cherries))
 
 (defun magit-cherry-setup-buffer (head upstream)
   (magit-setup-buffer #'magit-cherry-mode nil
diff --git a/lisp/magit-mode.el b/lisp/magit-mode.el
index 7dc1282472..3a8df694c4 100644
--- a/lisp/magit-mode.el
+++ b/lisp/magit-mode.el
@@ -528,6 +528,7 @@ Magit is documented in info node `(magit)'."
   (setq mode-line-process (magit-repository-local-get 'mode-line-process))
   (setq-local revert-buffer-function 'magit-refresh-buffer)
   (setq-local bookmark-make-record-function 'magit--make-bookmark)
+  (setq-local imenu-create-index-function 'magit--imenu-create-index)
   (setq-local isearch-filter-predicate 'magit-section--open-temporarily))
 
 ;;; Local Variables
@@ -580,6 +581,9 @@ your mode instead of adding an entry to this variable.")
 (defvar-local magit-previous-section nil)
 (put 'magit-previous-section 'permanent-local t)
 
+(defvar-local magit--imenu-group-types nil)
+(defvar-local magit--imenu-item-types nil)
+
 ;;; Setup Buffer
 
 (defmacro magit-setup-buffer (mode &optional locked &rest bindings)
@@ -1454,6 +1458,51 @@ mentioned caches completely."
              (setq magit-section-visibility-cache nil)))))
   (setq magit--libgit-available-p 'unknown))
 
+;;; Imenu Support
+
+(defun magit--imenu-create-index ()
+  ;; If `which-function-mode' is active, then the create-index
+  ;; function is called at the time the major-mode is being enabled.
+  ;; Modes that derive from `magit-mode' have not populated the buffer
+  ;; at that time yet, so we have to abort.
+  (and magit-root-section
+       (or magit--imenu-group-types
+           magit--imenu-item-types)
+       (let ((index
+              (mapcan
+               (lambda (section)
+                 (cond
+                  (magit--imenu-group-types
+                   (and (magit-section-match magit--imenu-group-types section)
+                        (when-let ((children (oref section children)))
+                          `((,(magit--imenu-index-name section)
+                             ,@(mapcar (lambda (s)
+                                         (cons (magit--imenu-index-name s)
+                                               (oref s start)))
+                                       children))))))
+                  (magit--imenu-item-types
+                   (and (magit-section-match magit--imenu-item-types section)
+                        `((,(magit--imenu-index-name section)
+                           . ,(oref section start)))))))
+               (oref magit-root-section children))))
+         (if (and magit--imenu-group-types (symbolp magit--imenu-group-types))
+             (cdar index)
+           index))))
+
+(defun magit--imenu-index-name (section)
+  (let ((heading (buffer-substring-no-properties
+                  (oref section start)
+                  (1- (or (oref section content)
+                          (oref section end))))))
+    (save-match-data
+      (cond
+       ((and (magit-section-match [commit logbuf] section)
+             (string-match "[^ ]+\\([ *|]*\\).+" heading))
+        (replace-match " " t t heading 1))
+       ((string-match " ([0-9]+)\\'" heading)
+        (substring heading 0 (match-beginning 0)))
+       (t heading)))))
+
 ;;; Utilities
 
 (defun magit-toggle-verbose-refresh ()
diff --git a/lisp/magit-process.el b/lisp/magit-process.el
index f069c991fd..aff19918a9 100644
--- a/lisp/magit-process.el
+++ b/lisp/magit-process.el
@@ -285,10 +285,7 @@ Used when `magit-process-display-mode-line-error' is 
non-nil."
   "Mode for looking at Git process output."
   :group 'magit-process
   (hack-dir-local-variables-non-file-buffer)
-  (setq imenu-prev-index-position-function
-        'magit-imenu--process-prev-index-position-function)
-  (setq imenu-extract-index-name-function
-        'magit-imenu--process-extract-index-name-function))
+  (setq magit--imenu-item-types 'process))
 
 (defun magit-process-buffer (&optional nodisplay)
   "Display the current repository's process buffer.
diff --git a/lisp/magit-reflog.el b/lisp/magit-reflog.el
index fb79d8efa6..9a38b779f8 100644
--- a/lisp/magit-reflog.el
+++ b/lisp/magit-reflog.el
@@ -156,7 +156,8 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
 
 \\{magit-reflog-mode-map}"
   :group 'magit-log
-  (hack-dir-local-variables-non-file-buffer))
+  (hack-dir-local-variables-non-file-buffer)
+  (setq magit--imenu-item-types 'commit))
 
 (defun magit-reflog-setup-buffer (ref)
   (require 'magit)
diff --git a/lisp/magit-refs.el b/lisp/magit-refs.el
index 0117e083f3..2665097138 100644
--- a/lisp/magit-refs.el
+++ b/lisp/magit-refs.el
@@ -301,8 +301,7 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
 \\{magit-refs-mode-map}"
   :group 'magit-refs
   (hack-dir-local-variables-non-file-buffer)
-  (setq imenu-create-index-function
-        #'magit-imenu--refs-create-index-function))
+  (setq magit--imenu-group-types '(local remote tags)))
 
 (defun magit-refs-setup-buffer (ref args)
   (magit-setup-buffer #'magit-refs-mode nil
diff --git a/lisp/magit-section.el b/lisp/magit-section.el
index 33c3b1052f..f3ae5f7e94 100644
--- a/lisp/magit-section.el
+++ b/lisp/magit-section.el
@@ -1662,27 +1662,6 @@ If optional SECTION is nil, use the current section."
                 (magit-section-position-in-heading-p section (region-end))))
        t))
 
-(defun magit-section--backward-protected ()
-  "Move to the beginning of the current or the previous visible section.
-Same as `magit-section-backward' but for non-interactive use.
-Suppress `magit-section-movement-hook', and return a boolean to
-indicate whether a section was found, instead of raising an error
-if not."
-  (condition-case nil
-      (let ((magit-section-movement-hook nil))
-        (magit-section-backward)
-        t)
-    (user-error nil)))
-
-(defun magit-section--backward-find (predicate)
-  "Move to the first previous section satisfying PREDICATE.
-PREDICATE does not take any parameter and should not move
-point."
-  (let (found)
-    (while (and (setq found (magit-section--backward-protected))
-                (not (funcall predicate))))
-    found))
-
 (defun magit-wash-sequence (function)
   "Repeatedly call FUNCTION until it returns nil or eob is reached.
 FUNCTION has to move point forward or return nil."
diff --git a/lisp/magit-stash.el b/lisp/magit-stash.el
index 7521256c29..f62d2b5a3e 100644
--- a/lisp/magit-stash.el
+++ b/lisp/magit-stash.el
@@ -496,7 +496,8 @@ If there is no stash buffer in the same frame, then do 
nothing."
 (define-derived-mode magit-stash-mode magit-diff-mode "Magit Stash"
   "Mode for looking at individual stashes."
   :group 'magit-diff
-  (hack-dir-local-variables-non-file-buffer))
+  (hack-dir-local-variables-non-file-buffer)
+  (setq magit--imenu-group-types '(commit)))
 
 (defun magit-stash-setup-buffer (stash args files)
   (magit-setup-buffer #'magit-stash-mode nil
diff --git a/lisp/magit-status.el b/lisp/magit-status.el
index 2ea3c75e28..cd97e035b5 100644
--- a/lisp/magit-status.el
+++ b/lisp/magit-status.el
@@ -406,8 +406,8 @@ Type \\[magit-commit] to create a commit.
 \\{magit-status-mode-map}"
   :group 'magit-status
   (hack-dir-local-variables-non-file-buffer)
-  (setq imenu-create-index-function
-        'magit-imenu--status-create-index-function))
+  (setq magit--imenu-group-types
+        '(unpushed unstaged unpulled untracked staged stashes pullreqs 
issues)))
 
 (put 'magit-status-mode 'magit-diff-default-arguments
      '("--no-ext-diff"))



reply via email to

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