dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

magit-imenu.el (8684B)


      1 ;;; magit-imenu.el --- Integrate Imenu in magit major modes  -*- lexical-binding: t -*-
      2 
      3 ;; Copyright (C) 2010-2021  The Magit Project Contributors
      4 ;;
      5 ;; You should have received a copy of the AUTHORS.md file which
      6 ;; lists all contributors.  If not, see http://magit.vc/authors.
      7 
      8 ;; Author: Damien Cassou <damien@cassou.me>
      9 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
     10 
     11 ;; SPDX-License-Identifier: GPL-3.0-or-later
     12 
     13 ;; Magit is free software; you can redistribute it and/or modify it
     14 ;; under the terms of the GNU General Public License as published by
     15 ;; the Free Software Foundation; either version 3, or (at your option)
     16 ;; any later version.
     17 ;;
     18 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
     19 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     20 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     21 ;; License for more details.
     22 ;;
     23 ;; You should have received a copy of the GNU General Public License
     24 ;; along with Magit.  If not, see http://www.gnu.org/licenses.
     25 
     26 ;;; Commentary:
     27 
     28 ;; Emacs' major modes can facilitate navigation in their buffers by
     29 ;; supporting Imenu.  In such major modes, launching Imenu (M-x imenu)
     30 ;; makes Emacs display a list of items (e.g., function definitions in
     31 ;; a programming major mode).  Selecting an item from this list moves
     32 ;; point to this item.
     33 
     34 ;; magit-imenu.el adds Imenu support to every major mode in Magit.
     35 
     36 ;;; Code:
     37 
     38 (require 'magit)
     39 (require 'git-rebase)
     40 
     41 ;;; Core
     42 
     43 (defun magit-imenu--index-function (entry-types menu-types)
     44   "Return an alist of imenu entries in current buffer.
     45 
     46 ENTRY-TYPES is a list of section types to be selected through
     47 `imenu'.
     48 
     49 MENU-TYPES is a list of section types containing elements of
     50 ENTRY-TYPES.  Elements of MENU-TYPES are used to categorize
     51 elements of ENTRY-TYPES.
     52 
     53 This function is used as a helper for functions set as
     54 `imenu-create-index-function'."
     55   ;; If `which-function-mode' is active, then the create-index
     56   ;; function is called at the time the major-mode is being enabled.
     57   ;; Modes that derive from `magit-mode' have not populated the buffer
     58   ;; at that time yet, so we have to abort.
     59   (when-let ((section (magit-current-section))
     60              (entries (make-hash-table :test 'equal)))
     61     (goto-char (point-max))
     62     (unless (oref section parent)
     63       (forward-line -1))
     64     (while (magit-section--backward-find
     65             (lambda ()
     66               (let* ((section (magit-current-section))
     67                      (type (oref section type))
     68                      (parent (oref section parent))
     69                      (parent-type (oref parent type)))
     70                 (and (memq type entry-types)
     71                      (memq parent-type menu-types)))))
     72       (let* ((section (magit-current-section))
     73              (name (buffer-substring-no-properties
     74                     (line-beginning-position)
     75                     (line-end-position)))
     76              (parent (oref section parent))
     77              (parent-title (buffer-substring-no-properties
     78                             (oref parent start)
     79                             (1- (oref parent content)))))
     80         (when (string-match " ([0-9]*)\\'" parent-title)
     81           (setq parent-title (substring parent-title 0 (match-beginning 0))))
     82         (puthash parent-title
     83                  (cons (cons name (point))
     84                        (gethash parent-title entries (list)))
     85                  entries)))
     86     (mapcar (lambda (menu-title)
     87               (cons menu-title (gethash menu-title entries)))
     88             (hash-table-keys entries))))
     89 
     90 ;;; Log mode
     91 
     92 ;;;###autoload
     93 (defun magit-imenu--log-prev-index-position-function ()
     94   "Move point to previous line in current buffer.
     95 This function is used as a value for
     96 `imenu-prev-index-position-function'."
     97   (magit-section--backward-find
     98    (lambda ()
     99      (-contains-p '(commit stash)
    100                   (oref (magit-current-section) type)))))
    101 
    102 ;;;###autoload
    103 (defun magit-imenu--log-extract-index-name-function ()
    104   "Return imenu name for line at point.
    105 This function is used as a value for
    106 `imenu-extract-index-name-function'.  Point should be at the
    107 beginning of the line."
    108   (save-match-data
    109     (looking-at "\\([^ ]+\\)[ *|]+\\(.+\\)$")
    110     (format "%s: %s"
    111             (match-string-no-properties 1)
    112             (match-string-no-properties 2))))
    113 
    114 ;;; Diff mode
    115 
    116 ;;;###autoload
    117 (defun magit-imenu--diff-prev-index-position-function ()
    118   "Move point to previous file line in current buffer.
    119 This function is used as a value for
    120 `imenu-prev-index-position-function'."
    121   (magit-section--backward-find
    122    (lambda ()
    123      (let ((section (magit-current-section)))
    124        (and (magit-file-section-p section)
    125             (not (equal (oref (oref section parent) type)
    126                         'diffstat)))))))
    127 
    128 ;;;###autoload
    129 (defun magit-imenu--diff-extract-index-name-function ()
    130   "Return imenu name for line at point.
    131 This function is used as a value for
    132 `imenu-extract-index-name-function'.  Point should be at the
    133 beginning of the line."
    134   (buffer-substring-no-properties (line-beginning-position)
    135                                   (line-end-position)))
    136 
    137 ;;; Status mode
    138 
    139 ;;;###autoload
    140 (defun magit-imenu--status-create-index-function ()
    141   "Return an alist of all imenu entries in current buffer.
    142 This function is used as a value for
    143 `imenu-create-index-function'."
    144   (magit-imenu--index-function
    145    '(file commit stash pullreq issue)
    146    '(unpushed unstaged unpulled untracked staged stashes pullreqs issues)))
    147 
    148 ;;; Refs mode
    149 
    150 ;;;###autoload
    151 (defun magit-imenu--refs-create-index-function ()
    152   "Return an alist of all imenu entries in current buffer.
    153 This function is used as a value for
    154 `imenu-create-index-function'."
    155   (magit-imenu--index-function
    156    '(branch commit tag)
    157    '(local remote tags)))
    158 
    159 ;;; Cherry mode
    160 
    161 ;;;###autoload
    162 (defun magit-imenu--cherry-create-index-function ()
    163   "Return an alist of all imenu entries in current buffer.
    164 This function is used as a value for
    165 `imenu-create-index-function'."
    166   (magit-imenu--index-function
    167    '(commit)
    168    '(cherries)))
    169 
    170 ;;; Submodule list mode
    171 
    172 ;;;###autoload
    173 (defun magit-imenu--submodule-prev-index-position-function ()
    174   "Move point to previous line in magit-submodule-list buffer.
    175 This function is used as a value for
    176 `imenu-prev-index-position-function'."
    177   (unless (bobp)
    178     (forward-line -1)))
    179 
    180 ;;;###autoload
    181 (defun magit-imenu--submodule-extract-index-name-function ()
    182   "Return imenu name for line at point.
    183 This function is used as a value for
    184 `imenu-extract-index-name-function'.  Point should be at the
    185 beginning of the line."
    186   (elt (tabulated-list-get-entry) 0))
    187 
    188 ;;; Repolist mode
    189 
    190 ;;;###autoload
    191 (defun magit-imenu--repolist-prev-index-position-function ()
    192   "Move point to previous line in magit-repolist buffer.
    193 This function is used as a value for
    194 `imenu-prev-index-position-function'."
    195   (unless (bobp)
    196     (forward-line -1)))
    197 
    198 ;;;###autoload
    199 (defun magit-imenu--repolist-extract-index-name-function ()
    200   "Return imenu name for line at point.
    201 This function is used as a value for
    202 `imenu-extract-index-name-function'.  Point should be at the
    203 beginning of the line."
    204   (let ((entry (tabulated-list-get-entry)))
    205     (format "%s (%s)"
    206             (elt entry 0)
    207             (elt entry (1- (length entry))))))
    208 
    209 ;;; Process mode
    210 
    211 ;;;###autoload
    212 (defun magit-imenu--process-prev-index-position-function ()
    213   "Move point to previous process in magit-process buffer.
    214 This function is used as a value for
    215 `imenu-prev-index-position-function'."
    216   (magit-section--backward-find
    217    (lambda ()
    218      (eq (oref (magit-current-section) type) 'process))))
    219 
    220 ;;;###autoload
    221 (defun magit-imenu--process-extract-index-name-function ()
    222   "Return imenu name for line at point.
    223 This function is used as a value for
    224 `imenu-extract-index-name-function'.  Point should be at the
    225 beginning of the line."
    226   (buffer-substring-no-properties (line-beginning-position)
    227                                   (line-end-position)))
    228 
    229 ;;; Rebase mode
    230 
    231 ;;;###autoload
    232 (defun magit-imenu--rebase-prev-index-position-function ()
    233   "Move point to previous commit in git-rebase buffer.
    234 This function is used as a value for
    235 `imenu-prev-index-position-function'."
    236   (catch 'found
    237     (while (not (bobp))
    238       (git-rebase-backward-line)
    239       (when (git-rebase-line-p)
    240         (throw 'found t)))))
    241 
    242 ;;;###autoload
    243 (defun magit-imenu--rebase-extract-index-name-function ()
    244   "Return imenu name for line at point.
    245 This function is used as a value for
    246 `imenu-extract-index-name-function'.  Point should be at the
    247 beginning of the line."
    248   (buffer-substring-no-properties (line-beginning-position)
    249                                   (line-end-position)))
    250 
    251 ;;; _
    252 (provide 'magit-imenu)
    253 ;;; magit-imenu.el ends here