emacs: list: Generalize 'describe' code.

* emacs/guix-list.el (guix-list-describe-warning-count): Remove variable.
  (guix-list-define-entry-type): Generate
  'guix-ENTRY-TYPE-list-describe-warning-count' and
  'guix-ENTRY-TYPE-list-describe-function' variables.
  (guix-list-describe-maybe): Remove.  Move the code...
  (guix-list-describe): ... here.
  (guix-list-describe-warning-count, guix-list-describe-entries)
  (guix-list-describe-ids): New procedures.
  (guix-output-list-describe): Adjust accordingly.
  (guix-list-mode-map): Bind "i" key to 'guix-list-describe'.
  (guix-generation-list-mode-map): Remove "i" key.
master
Alex Kost 2015-11-19 15:58:19 +03:00
parent f768e4b387
commit 7b31510f26
1 changed files with 79 additions and 52 deletions

View File

@ -51,13 +51,6 @@
"Face used for time stamps." "Face used for time stamps."
:group 'guix-list-faces) :group 'guix-list-faces)
(defcustom guix-list-describe-warning-count 10
"The maximum number of entries for describing without a warning.
If a user wants to describe more than this number of marked
entries, he will be prompted for confirmation."
:type 'integer
:group 'guix-list)
(defvar guix-list-format (defvar guix-list-format
`((package `((package
(name guix-package-list-get-name 20 t) (name guix-package-list-get-name 20 t)
@ -98,6 +91,26 @@ For the meaning of WIDTH, SORT and PROPS, see
Has the same structure as `guix-param-titles', but titles from Has the same structure as `guix-param-titles', but titles from
this list have a priority.") this list have a priority.")
(defun guix-list-describe (&optional mark-names)
"Describe entries marked with a general mark.
'Describe' means display entries in 'info' buffer.
If no entries are marked, describe the current entry.
With prefix argument, describe entries marked with any mark."
(interactive (list (unless current-prefix-arg '(general))))
(let* ((ids (or (apply #'guix-list-get-marked-id-list mark-names)
(list (guix-list-current-id))))
(count (length ids))
(entry-type guix-entry-type))
(when (or (<= count (guix-list-describe-warning-count entry-type))
(y-or-n-p (format "Do you really want to describe %d entries? "
count)))
(guix-list-describe-entries entry-type ids))))
(defun guix-list-describe-ids (ids)
"Describe entries with IDS (list of identifiers)."
(apply #'guix-get-show-entries
guix-profile 'info guix-entry-type 'id ids))
;;; Wrappers for 'list' variables ;;; Wrappers for 'list' variables
@ -127,6 +140,15 @@ This alist is filled by `guix-list-define-entry-type' macro.")
"Return alist of additional marks for ENTRY-TYPE." "Return alist of additional marks for ENTRY-TYPE."
(guix-list-value entry-type 'marks)) (guix-list-value entry-type 'marks))
(defun guix-list-describe-warning-count (entry-type)
"Return the maximum number of ENTRY-TYPE entries to describe."
(guix-list-value entry-type 'describe-count))
(defun guix-list-describe-entries (entry-type ids)
"Describe ENTRY-TYPE entries with IDS in 'info' buffer"
(funcall (guix-list-value entry-type 'describe)
ids))
;;; Tabulated list internals ;;; Tabulated list internals
@ -409,6 +431,7 @@ Same as `tabulated-list-sort', but also restore marks after sorting."
map (make-composed-keymap guix-root-map map (make-composed-keymap guix-root-map
tabulated-list-mode-map)) tabulated-list-mode-map))
(define-key map (kbd "RET") 'guix-list-describe) (define-key map (kbd "RET") 'guix-list-describe)
(define-key map (kbd "i") 'guix-list-describe)
(define-key map (kbd "m") 'guix-list-mark) (define-key map (kbd "m") 'guix-list-mark)
(define-key map (kbd "*") 'guix-list-mark) (define-key map (kbd "*") 'guix-list-mark)
(define-key map (kbd "u") 'guix-list-unmark) (define-key map (kbd "u") 'guix-list-unmark)
@ -431,18 +454,27 @@ following keywords are available:
- `:invert-sort' - if non-nil, invert initial sort. - `:invert-sort' - if non-nil, invert initial sort.
- `:describe-function' - default value of the generated
`guix-ENTRY-TYPE-describe-function' variable.
- `:marks' - default value of the generated - `:marks' - default value of the generated
`guix-ENTRY-TYPE-list-marks' variable. `guix-ENTRY-TYPE-list-marks' variable.
" "
(let* ((entry-type-str (symbol-name entry-type)) (let* ((entry-type-str (symbol-name entry-type))
(prefix (concat "guix-" entry-type-str "-list")) (prefix (concat "guix-" entry-type-str "-list"))
(mode-str (concat prefix "-mode")) (group (intern prefix))
(init-fun (intern (concat prefix "-mode-initialize"))) (mode-str (concat prefix "-mode"))
(marks-var (intern (concat prefix "-marks")))) (init-fun (intern (concat prefix "-mode-initialize")))
(describe-var (intern (concat prefix "-describe-function")))
(describe-count-var (intern (concat prefix
"-describe-warning-count")))
(marks-var (intern (concat prefix "-marks"))))
(guix-keyword-args-let args (guix-keyword-args-let args
((sort-key :sort-key) ((describe-val :describe-function)
(invert-sort :invert-sort) (describe-count-val :describe-count 10)
(marks-val :marks)) (sort-key :sort-key)
(invert-sort :invert-sort)
(marks-val :marks))
`(progn `(progn
(defvar ,marks-var ,marks-val (defvar ,marks-var ,marks-val
,(format "\ ,(format "\
@ -450,6 +482,20 @@ Alist of additional marks for 'list' buffer with '%s' entries.
Marks from this list are used along with `guix-list-default-marks'." Marks from this list are used along with `guix-list-default-marks'."
entry-type-str)) entry-type-str))
(defcustom ,describe-count-var ,describe-count-val
,(format "\
The maximum number of '%s' entries to describe without a warning.
If a user wants to describe more than this number of marked
entries, he will be prompted for confirmation.
See also `guix-list-describe'."
entry-type-str)
:type 'integer
:group ',group)
(defvar ,describe-var ,describe-val
,(format "Function used to describe '%s' entries."
entry-type-str))
(defun ,init-fun () (defun ,init-fun ()
,(concat "Initial settings for `" mode-str "'.") ,(concat "Initial settings for `" mode-str "'.")
,(when sort-key ,(when sort-key
@ -462,30 +508,13 @@ Marks from this list are used along with `guix-list-default-marks'."
(tabulated-list-init-header)) (tabulated-list-init-header))
(guix-alist-put! (guix-alist-put!
'((marks . ,marks-var)) '((describe . ,describe-var)
(describe-count . ,describe-count-var)
(marks . ,marks-var))
'guix-list-data ',entry-type))))) 'guix-list-data ',entry-type)))))
(put 'guix-list-define-entry-type 'lisp-indent-function 'defun) (put 'guix-list-define-entry-type 'lisp-indent-function 'defun)
(defun guix-list-describe-maybe (entry-type ids)
"Describe ENTRY-TYPE entries in info buffer using list of IDS."
(let ((count (length ids)))
(when (or (<= count guix-list-describe-warning-count)
(y-or-n-p (format "Do you really want to describe %d entries? "
count)))
(apply #'guix-get-show-entries
guix-profile 'info entry-type 'id ids))))
(defun guix-list-describe (&optional arg)
"Describe entries marked with a general mark.
If no entries are marked, describe the current entry.
With prefix (if ARG is non-nil), describe entries marked with any mark."
(interactive "P")
(let ((ids (or (apply #'guix-list-get-marked-id-list
(unless arg '(general)))
(list (guix-list-current-id)))))
(guix-list-describe-maybe guix-entry-type ids)))
(defun guix-list-edit-package () (defun guix-list-edit-package ()
"Go to the location of the current package." "Go to the location of the current package."
(interactive) (interactive)
@ -497,6 +526,7 @@ With prefix (if ARG is non-nil), describe entries marked with any mark."
(guix-define-buffer-type list package) (guix-define-buffer-type list package)
(guix-list-define-entry-type package (guix-list-define-entry-type package
:describe-function 'guix-list-describe-ids
:sort-key name :sort-key name
:marks '((install . ?I) :marks '((install . ?I)
(upgrade . ?U) (upgrade . ?U)
@ -680,13 +710,13 @@ The specification is suitable for `guix-process-package-actions'."
:required (package-id)) :required (package-id))
(guix-list-define-entry-type output (guix-list-define-entry-type output
:describe-function 'guix-output-list-describe
:sort-key name :sort-key name
:marks '((install . ?I) :marks '((install . ?I)
(upgrade . ?U) (upgrade . ?U)
(delete . ?D))) (delete . ?D)))
(let ((map guix-output-list-mode-map)) (let ((map guix-output-list-mode-map))
(define-key map (kbd "RET") 'guix-output-list-describe)
(define-key map (kbd "e") 'guix-list-edit-package) (define-key map (kbd "e") 'guix-list-edit-package)
(define-key map (kbd "x") 'guix-output-list-execute) (define-key map (kbd "x") 'guix-output-list-execute)
(define-key map (kbd "i") 'guix-output-list-mark-install) (define-key map (kbd "i") 'guix-output-list-mark-install)
@ -746,22 +776,19 @@ The specification is suitable for `guix-process-output-actions'."
(mapcar #'guix-package-id-and-output-by-output-id (mapcar #'guix-package-id-and-output-by-output-id
ids))))) ids)))))
(defun guix-output-list-describe (&optional arg) (defun guix-output-list-describe (ids)
"Describe outputs or packages marked with a general mark. "Describe outputs with IDS (list of output identifiers).
If no entries are marked, describe the current output or package. See `guix-package-info-type'."
With prefix (if ARG is non-nil), describe entries marked with any mark.
Also see `guix-package-info-type'."
(interactive "P")
(if (eq guix-package-info-type 'output) (if (eq guix-package-info-type 'output)
(guix-list-describe arg) (apply #'guix-get-show-entries
(let* ((oids (or (apply #'guix-list-get-marked-id-list guix-profile 'info 'output 'id ids)
(unless arg '(general))) (let ((pids (mapcar (lambda (oid)
(list (guix-list-current-id)))) (car (guix-package-id-and-output-by-output-id
(pids (mapcar (lambda (oid) oid)))
(car (guix-package-id-and-output-by-output-id ids)))
oid))) (apply #'guix-get-show-entries
oids))) guix-profile 'info 'package 'id
(guix-list-describe-maybe 'package (cl-remove-duplicates pids))))) (cl-remove-duplicates pids)))))
;;; Displaying generations ;;; Displaying generations
@ -769,6 +796,7 @@ Also see `guix-package-info-type'."
(guix-define-buffer-type list generation) (guix-define-buffer-type list generation)
(guix-list-define-entry-type generation (guix-list-define-entry-type generation
:describe-function 'guix-list-describe-ids
:sort-key number :sort-key number
:invert-sort t :invert-sort t
:marks '((delete . ?D))) :marks '((delete . ?D)))
@ -781,7 +809,6 @@ Also see `guix-package-info-type'."
(define-key map (kbd "D") 'guix-generation-list-diff) (define-key map (kbd "D") 'guix-generation-list-diff)
(define-key map (kbd "e") 'guix-generation-list-ediff) (define-key map (kbd "e") 'guix-generation-list-ediff)
(define-key map (kbd "x") 'guix-generation-list-execute) (define-key map (kbd "x") 'guix-generation-list-execute)
(define-key map (kbd "i") 'guix-list-describe)
(define-key map (kbd "s") 'guix-generation-list-switch) (define-key map (kbd "s") 'guix-generation-list-switch)
(define-key map (kbd "d") 'guix-generation-list-mark-delete)) (define-key map (kbd "d") 'guix-generation-list-mark-delete))