[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"))
- [nongnu] elpa/git-commit updated (9b94654921 -> 3525928602), ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit f321409f4d 01/10: Rename magit-utils.el to magit-base.el, ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit 50953fc4f0 02/10: Define section classes in magit-base.el, ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit 3525928602 10/10: magit-stashes-section-map: Bind magit-stash-list, ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit 9585356e98 03/10: magit-commit-section: New class, ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit df50834f24 07/10: magit-imenu--{*}: Rearrange and abbreviate docstrings, ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit 8fef6b9651 05/10: magit-status-mode: Add more to Imenu index, ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit 512d78cb3a 08/10: magit-imenu--{*}: Cosmetics, ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit f815ea7795 09/10: Disband magit-imenu.el, ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit b563e448c1 06/10: magit-refs-mode: Make Imenu items less noisy, ELPA Syncer, 2022/02/22
- [nongnu] elpa/git-commit 4727dcbe22 04/10: Refactor Imenu support,
ELPA Syncer <=