config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

magit-transient.el (9163B)


      1 ;;; magit-transient.el --- Support for transients  -*- lexical-binding:t -*-
      2 
      3 ;; Copyright (C) 2008-2024 The Magit Project Contributors
      4 
      5 ;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
      6 ;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
      7 
      8 ;; SPDX-License-Identifier: GPL-3.0-or-later
      9 
     10 ;; Magit is free software: you can redistribute it and/or modify it
     11 ;; under the terms of the GNU General Public License as published by
     12 ;; the Free Software Foundation, either version 3 of the License, or
     13 ;; (at your option) any later version.
     14 ;;
     15 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
     16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     18 ;; License for more details.
     19 ;;
     20 ;; You should have received a copy of the GNU General Public License
     21 ;; along with Magit.  If not, see <https://www.gnu.org/licenses/>.
     22 
     23 ;;; Commentary:
     24 
     25 ;; This library implements Magit-specific prefix and suffix classes,
     26 ;; and their methods.
     27 
     28 ;;; Code:
     29 
     30 (require 'magit-git)
     31 (require 'magit-mode)
     32 (require 'magit-process)
     33 
     34 (require 'transient)
     35 
     36 ;;; Classes
     37 
     38 (defclass magit--git-variable (transient-variable)
     39   ((scope       :initarg :scope)
     40    (global      :initarg :global      :initform nil)
     41    (default     :initarg :default     :initform nil)))
     42 
     43 (defclass magit--git-variable:choices (magit--git-variable)
     44   ((choices     :initarg :choices)
     45    (fallback    :initarg :fallback    :initform nil)))
     46 
     47 (defclass magit--git-variable:boolean (magit--git-variable:choices)
     48   ((choices     :initarg :choices     :initform '("true" "false"))))
     49 
     50 (defclass magit--git-variable:urls (magit--git-variable)
     51   ((seturl-arg  :initarg :seturl-arg  :initform nil)))
     52 
     53 ;;; Methods
     54 ;;;; Init
     55 
     56 (cl-defmethod transient-init-scope ((obj magit--git-variable))
     57   (oset obj scope
     58         (cond (transient--prefix
     59                (oref transient--prefix scope))
     60               ((slot-boundp obj 'scope)
     61                (funcall (oref obj scope) obj)))))
     62 
     63 (cl-defmethod transient-init-value ((obj magit--git-variable))
     64   (let ((variable (format (oref obj variable)
     65                           (oref obj scope)))
     66         (arg (if (oref obj global) "--global" "--local")))
     67     (oset obj variable variable)
     68     (oset obj value
     69           (cond ((oref obj multi-value)
     70                  (magit-get-all arg variable))
     71                 (t
     72                  (magit-get arg variable))))))
     73 
     74 (cl-defmethod transient-init-value ((obj magit--git-variable:boolean))
     75   (let ((variable (format (oref obj variable)
     76                           (oref obj scope)))
     77         (arg (if (oref obj global) "--global" "--local")))
     78     (oset obj variable variable)
     79     (oset obj value (if (magit-get-boolean arg variable) "true" "false"))))
     80 
     81 ;;;; Read
     82 
     83 (cl-defmethod transient-infix-read :around ((obj magit--git-variable:urls))
     84   (transient--with-emergency-exit
     85     (transient--with-suspended-override
     86      (mapcar (lambda (url)
     87                (if (string-prefix-p "~" url)
     88                    (expand-file-name url)
     89                  url))
     90              (cl-call-next-method obj)))))
     91 
     92 (cl-defmethod transient-infix-read ((obj magit--git-variable:choices))
     93   (let ((choices (oref obj choices)))
     94     (when (functionp choices)
     95       (setq choices (funcall choices)))
     96     (if-let ((value (oref obj value)))
     97         (cadr (member value choices))
     98       (car choices))))
     99 
    100 ;;;; Readers
    101 
    102 (defun magit-transient-read-person (prompt initial-input history)
    103   (magit-completing-read
    104    prompt
    105    (mapcar (lambda (line)
    106              (save-excursion
    107                (and (string-match "\\`[\s\t]+[0-9]+\t" line)
    108                     (list (substring line (match-end 0))))))
    109            (magit-git-lines "shortlog" "-n" "-s" "-e" "HEAD"))
    110    nil nil initial-input history))
    111 
    112 (defun magit-transient-read-revision (prompt initial-input history)
    113   (or (magit-completing-read prompt (cons "HEAD" (magit-list-refnames))
    114                              nil nil initial-input history
    115                              (or (magit-branch-or-commit-at-point)
    116                                  (magit-get-current-branch)))
    117       (user-error "Nothing selected")))
    118 
    119 ;;;; Set
    120 
    121 (cl-defmethod transient-infix-set ((obj magit--git-variable) value)
    122   (let ((variable (oref obj variable))
    123         (arg (if (oref obj global) "--global" "--local")))
    124     (oset obj value value)
    125     (if (oref obj multi-value)
    126         (magit-set-all value arg variable)
    127       (magit-set value arg variable))
    128     (magit-refresh)
    129     (unless (or value transient--prefix)
    130       (message "Unset %s" variable))))
    131 
    132 (cl-defmethod transient-infix-set ((obj magit--git-variable:urls) values)
    133   (let ((previous (oref obj value))
    134         (seturl   (oref obj seturl-arg))
    135         (remote   (oref transient--prefix scope)))
    136     (oset obj value values)
    137     (dolist (v (cl-set-difference values previous :test #'equal))
    138       (magit-call-git "remote" "set-url" seturl "--add" remote v))
    139     (dolist (v (cl-set-difference previous values :test #'equal))
    140       (magit-call-git "remote" "set-url" seturl "--delete" remote
    141                       (concat "^" (regexp-quote v) "$")))
    142     (magit-refresh)))
    143 
    144 ;;;; Draw
    145 
    146 (cl-defmethod transient-format-description ((obj magit--git-variable))
    147   (or (oref obj description)
    148       (oref obj variable)))
    149 
    150 (cl-defmethod transient-format-value ((obj magit--git-variable))
    151   (if-let ((value (oref obj value)))
    152       (if (oref obj multi-value)
    153           (if (cdr value)
    154               (mapconcat (lambda (v)
    155                            (concat "\n     "
    156                                    (propertize v 'face 'transient-value)))
    157                          value "")
    158             (propertize (car value) 'face 'transient-value))
    159         (propertize (car (split-string value "\n"))
    160                     'face 'transient-value))
    161     (if-let* ((default (oref obj default))
    162               (default (if (functionp default) (funcall default) default)))
    163         (concat (propertize "default:" 'face 'transient-inactive-value)
    164                 (propertize default 'face 'transient-value))
    165       (propertize "unset" 'face 'transient-inactive-value))))
    166 
    167 (cl-defmethod transient-format-value ((obj magit--git-variable:choices))
    168   (let* ((variable (oref obj variable))
    169          (choices  (oref obj choices))
    170          (globalp  (oref obj global))
    171          (value    nil)
    172          (global   (magit-git-string "config" "--global" variable))
    173          (defaultp (oref obj default))
    174          (default  (if (functionp defaultp) (funcall defaultp obj) defaultp))
    175          (fallback (oref obj fallback))
    176          (fallback (and fallback
    177                         (and-let* ((val (magit-get fallback)))
    178                           (concat fallback ":" val)))))
    179     (if (not globalp)
    180         (setq value (magit-git-string "config" "--local"  variable))
    181       (setq value global)
    182       (setq global nil))
    183     (when (functionp choices)
    184       (setq choices (funcall choices)))
    185     (concat
    186      (propertize "[" 'face 'transient-inactive-value)
    187      (mapconcat (lambda (choice)
    188                   (propertize choice 'face (if (equal choice value)
    189                                                (if (member choice choices)
    190                                                    'transient-value
    191                                                  'font-lock-warning-face)
    192                                              'transient-inactive-value)))
    193                 (if (and value (not (member value choices)))
    194                     (cons value choices)
    195                   choices)
    196                 (propertize "|" 'face 'transient-inactive-value))
    197      (and (or global fallback default)
    198           (concat
    199            (propertize "|" 'face 'transient-inactive-value)
    200            (cond (global
    201                   (propertize (concat "global:" global)
    202                               'face (cond (value
    203                                            'transient-inactive-value)
    204                                           ((member global choices)
    205                                            'transient-value)
    206                                           (t
    207                                            'font-lock-warning-face))))
    208                  (fallback
    209                   (propertize fallback
    210                               'face (if value
    211                                         'transient-inactive-value
    212                                       'transient-value)))
    213                  (default
    214                   (propertize (if (functionp defaultp)
    215                                   (concat "dwim:" default)
    216                                 (concat "default:" default))
    217                               'face (if value
    218                                         'transient-inactive-value
    219                                       'transient-value))))))
    220      (propertize "]" 'face 'transient-inactive-value))))
    221 
    222 ;;; Utilities
    223 
    224 (defun magit--transient-args-and-files ()
    225   "Return (args files) for use by log and diff functions.
    226 The value derives from that returned by `transient-get-value'."
    227   (let ((args (transient-get-value)))
    228     (list (seq-filter #'atom args)
    229           (cdr (assoc "--" args)))))
    230 
    231 ;;; _
    232 (provide 'magit-transient)
    233 ;;; magit-transient.el ends here