dotemacs

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

magit-bookmark.el (7949B)


      1 ;;; magit-bookmark.el --- bookmark support for Magit  -*- 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: Jonas Bernoulli <jonas@bernoul.li>
      9 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
     10 
     11 ;; Inspired by an earlier implementation by Yuri Khan.
     12 
     13 ;; SPDX-License-Identifier: GPL-3.0-or-later
     14 
     15 ;; Magit is free software; you can redistribute it and/or modify it
     16 ;; under the terms of the GNU General Public License as published by
     17 ;; the Free Software Foundation; either version 3, or (at your option)
     18 ;; any later version.
     19 ;;
     20 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
     21 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     22 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     23 ;; License for more details.
     24 ;;
     25 ;; You should have received a copy of the GNU General Public License
     26 ;; along with Magit.  If not, see http://www.gnu.org/licenses.
     27 
     28 ;;; Commentary:
     29 
     30 ;; Support for bookmarks for most Magit buffers.
     31 
     32 ;;; Code:
     33 
     34 (require 'magit)
     35 (require 'bookmark)
     36 
     37 ;;; Core
     38 
     39 (defun magit--make-bookmark ()
     40   "Create a bookmark for the current Magit buffer.
     41 Input values are the major-mode's `magit-bookmark-name' method,
     42 and the buffer-local values of the variables referenced in its
     43 `magit-bookmark-variables' property."
     44   (if (plist-member (symbol-plist major-mode) 'magit-bookmark-variables)
     45       ;; `bookmark-make-record-default's return value does not match
     46       ;; (NAME . ALIST), even though it is used as the default value
     47       ;; of `bookmark-make-record-function', which states that such
     48       ;; functions must do that.  See #4356.
     49       (let ((bookmark (cons nil (bookmark-make-record-default 'no-file))))
     50         (bookmark-prop-set bookmark 'handler  'magit--handle-bookmark)
     51         (bookmark-prop-set bookmark 'mode     major-mode)
     52         (bookmark-prop-set bookmark 'filename (magit-toplevel))
     53         (bookmark-prop-set bookmark 'defaults (list (magit-bookmark-name)))
     54         (dolist (var (get major-mode 'magit-bookmark-variables))
     55           (bookmark-prop-set bookmark var (symbol-value var)))
     56         (bookmark-prop-set
     57          bookmark 'magit-hidden-sections
     58          (--keep (and (oref it hidden)
     59                       (cons (oref it type)
     60                             (if (derived-mode-p 'magit-stash-mode)
     61                                 (replace-regexp-in-string
     62                                  (regexp-quote magit-buffer-revision)
     63                                  magit-buffer-revision-hash
     64                                  (oref it value))
     65                               (oref it value))))
     66                  (oref magit-root-section children)))
     67         bookmark)
     68     (user-error "Bookmarking is not implemented for %s buffers" major-mode)))
     69 
     70 ;;;###autoload
     71 (defun magit--handle-bookmark (bookmark)
     72   "Open a bookmark created by `magit--make-bookmark'.
     73 Call the `magit-*-setup-buffer' function of the the major-mode
     74 with the variables' values as arguments, which were recorded by
     75 `magit--make-bookmark'.  Ignore `magit-display-buffer-function'."
     76   (let ((buffer (let ((default-directory (bookmark-get-filename bookmark))
     77                       (mode (bookmark-prop-get bookmark 'mode))
     78                       (magit-display-buffer-function #'identity)
     79                       (magit-display-buffer-noselect t))
     80                   (apply (intern (format "%s-setup-buffer"
     81                                          (substring (symbol-name mode) 0 -5)))
     82                          (--map (bookmark-prop-get bookmark it)
     83                                 (get mode 'magit-bookmark-variables))))))
     84     (set-buffer buffer) ; That is the interface we have to adhere to.
     85     (when-let ((hidden (bookmark-prop-get bookmark 'magit-hidden-sections)))
     86       (with-current-buffer buffer
     87         (dolist (child (oref magit-root-section children))
     88           (if (member (cons (oref child type)
     89                             (oref child value))
     90                       hidden)
     91               (magit-section-hide child)
     92             (magit-section-show child)))))
     93     ;; Compatibility with `bookmark+' package.  See #4356.
     94     (when (bound-and-true-p bmkp-jump-display-function)
     95       (funcall bmkp-jump-display-function (current-buffer)))
     96     nil))
     97 
     98 (cl-defgeneric magit-bookmark-name ()
     99   "Return name for bookmark to current buffer."
    100   (format "%s%s"
    101           (substring (symbol-name major-mode) 0 -5)
    102           (if-let ((vars (get major-mode 'magit-bookmark-variables)))
    103               (cl-mapcan (lambda (var)
    104                            (let ((val (symbol-value var)))
    105                              (if (and val (atom val))
    106                                  (list val)
    107                                val)))
    108                          vars)
    109             "")))
    110 
    111 ;;; Diff
    112 ;;;; Diff
    113 
    114 (put 'magit-diff-mode 'magit-bookmark-variables
    115      '(magit-buffer-range-hashed
    116        magit-buffer-typearg
    117        magit-buffer-diff-args
    118        magit-buffer-diff-files))
    119 
    120 (cl-defmethod magit-bookmark-name (&context (major-mode magit-diff-mode))
    121   (format "magit-diff(%s%s)"
    122           (pcase (magit-diff-type)
    123             (`staged "staged")
    124             (`unstaged "unstaged")
    125             (`committed magit-buffer-range)
    126             (`undefined
    127              (delq nil (list magit-buffer-typearg magit-buffer-range-hashed))))
    128           (if magit-buffer-diff-files
    129               (concat " -- " (mapconcat #'identity magit-buffer-diff-files " "))
    130             "")))
    131 
    132 ;;;; Revision
    133 
    134 (put 'magit-revision-mode 'magit-bookmark-variables
    135      '(magit-buffer-revision-hash
    136        magit-buffer-diff-args
    137        magit-buffer-diff-files))
    138 
    139 (cl-defmethod magit-bookmark-name (&context (major-mode magit-revision-mode))
    140   (format "magit-revision(%s %s)"
    141           (magit-rev-abbrev magit-buffer-revision)
    142           (if magit-buffer-diff-files
    143               (mapconcat #'identity magit-buffer-diff-files " ")
    144             (magit-rev-format "%s" magit-buffer-revision))))
    145 
    146 ;;;; Stash
    147 
    148 (put 'magit-stash-mode 'magit-bookmark-variables
    149      '(magit-buffer-revision-hash
    150        magit-buffer-diff-args
    151        magit-buffer-diff-files))
    152 
    153 (cl-defmethod magit-bookmark-name (&context (major-mode magit-stash-mode))
    154   (format "magit-stash(%s %s)"
    155           (magit-rev-abbrev magit-buffer-revision)
    156           (if magit-buffer-diff-files
    157               (mapconcat #'identity magit-buffer-diff-files " ")
    158             (magit-rev-format "%s" magit-buffer-revision))))
    159 
    160 ;;; Log
    161 ;;;; Log
    162 
    163 (put 'magit-log-mode 'magit-bookmark-variables
    164      '(magit-buffer-revisions
    165        magit-buffer-log-args
    166        magit-buffer-log-files))
    167 
    168 (cl-defmethod magit-bookmark-name (&context (major-mode magit-log-mode))
    169   (format "magit-log(%s%s)"
    170           (mapconcat #'identity magit-buffer-revisions " ")
    171           (if magit-buffer-log-files
    172               (concat " -- " (mapconcat #'identity magit-buffer-log-files " "))
    173             "")))
    174 
    175 ;;;; Cherry
    176 
    177 (put 'magit-cherry-mode 'magit-bookmark-variables
    178      '(magit-buffer-refname
    179        magit-buffer-upstream))
    180 
    181 (cl-defmethod magit-bookmark-name (&context (major-mode magit-cherry-mode))
    182   (format "magit-cherry(%s > %s)"
    183           magit-buffer-refname
    184           magit-buffer-upstream))
    185 
    186 ;;;; Reflog
    187 
    188 (put 'magit-reflog-mode 'magit-bookmark-variables
    189      '(magit-buffer-refname))
    190 
    191 (cl-defmethod magit-bookmark-name (&context (major-mode magit-reflog-mode))
    192   (format "magit-reflog(%s)" magit-buffer-refname))
    193 
    194 ;;; Misc
    195 
    196 (put 'magit-status-mode 'magit-bookmark-variables nil)
    197 
    198 (put 'magit-refs-mode 'magit-bookmark-variables
    199      '(magit-buffer-upstream
    200        magit-buffer-arguments))
    201 
    202 (put 'magit-stashes-mode 'magit-bookmark-variables nil)
    203 
    204 (cl-defmethod magit-bookmark-name (&context (major-mode magit-stashes-mode))
    205   (format "magit-states(%s)" magit-buffer-refname))
    206 
    207 ;;; _
    208 (provide 'magit-bookmark)
    209 ;;; magit-bookmark.el ends here