emacs: Generalize buffer interface.
Extract the code for defining buffer interface from "guix-base.el", generalize it and move to "guix-buffer.el". * emacs.am (ELFILES): Add "emacs/guix-buffer.el". * emacs/guix-base.el (guix-profile, guix-entries, guix-buffer-type) (guix-entry-type, guix-search-type, guix-search-vals, guix-set-vars) (guix-get-symbol, guix-show-entries, guix-get-show-entries) (guix-set-buffer, guix-history-call, guix-make-history-item) (guix-get-params-for-receiving): Remove. (guix-switch-to-buffer): Rename to 'guix-buffer-display' and move to "guix-buffer.el". (guix-get-entries): Rename to 'guix-ui-get-entries' and move to "guix-ui.el". (guix-buffer-data, guix-buffer-value, guix-buffer-param-title) (guix-buffer-name, guix-buffer-history-size) (guix-buffer-revert-confirm?, guix-buffer-map, guix-buffer-revert) (guix-buffer-after-redisplay-hook, guix-buffer-redisplay) (guix-buffer-redisplay-goto-button): Move to... * emacs/guix-buffer.el: ... here. New file. (guix-buffer-item): New variable. (guix-buffer-with-item, guix-buffer-with-current-item) (guix-buffer-define-current-item-accessor) (guix-buffer-define-current-item-accessors) (guix-buffer-define-current-args-accessor) (guix-buffer-define-current-args-accessors): New macros. (guix-buffer-get-entries, guix-buffer-mode-enable) (guix-buffer-mode-initialize, guix-buffer-insert-entries) (guix-buffer-show-entries-default, guix-buffer-show-entries) (guix-buffer-message, guix-buffer-history-item, guix-buffer-set) (guix-buffer-display-entries-current) (guix-buffer-get-display-entries-current) (guix-buffer-display-entries, guix-buffer-get-display-entries): New procedures. * emacs/guix-info.el: Adjust for the procedures renaming. (guix-info-define-interface): Add ':show-entries-function' keyword. * emacs/guix-list.el: Likewise. * emacs/guix-ui.el (guix-ui-define-interface): Generate 'guix-ENTRY-TYPE-BUFFER-TYPE-get-entries' procedure based on 'guix-ui-get-entries'. * emacs/guix.el (guix-get-show-packages, guix-get-show-generations): Adjust for the procedures renaming.
This commit is contained in:
		
							parent
							
								
									8103c22fea
								
							
						
					
					
						commit
						6c40b7b703
					
				
					 7 changed files with 779 additions and 468 deletions
				
			
		
							
								
								
									
										1
									
								
								emacs.am
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								emacs.am
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -22,6 +22,7 @@ ELFILES =					\
 | 
			
		|||
  emacs/guix-backend.el				\
 | 
			
		||||
  emacs/guix-base.el				\
 | 
			
		||||
  emacs/guix-build-log.el			\
 | 
			
		||||
  emacs/guix-buffer.el				\
 | 
			
		||||
  emacs/guix-command.el				\
 | 
			
		||||
  emacs/guix-devel.el				\
 | 
			
		||||
  emacs/guix-emacs.el				\
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,9 +22,6 @@
 | 
			
		|||
;; This file provides some base and common definitions for guix.el
 | 
			
		||||
;; package.
 | 
			
		||||
 | 
			
		||||
;; List and info buffers have many common patterns that are defined
 | 
			
		||||
;; using `guix-buffer-define-interface' macro from this file.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'cl-lib)
 | 
			
		||||
| 
						 | 
				
			
			@ -34,8 +31,6 @@
 | 
			
		|||
(require 'guix-guile)
 | 
			
		||||
(require 'guix-utils)
 | 
			
		||||
(require 'guix-ui)
 | 
			
		||||
(require 'guix-history)
 | 
			
		||||
(require 'guix-messages)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Parameters of the entries
 | 
			
		||||
| 
						 | 
				
			
			@ -142,227 +137,6 @@ For the meaning of location, see `guix-find-location'."
 | 
			
		|||
                            'package-names-lists)))
 | 
			
		||||
   #'string<))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Buffers
 | 
			
		||||
 | 
			
		||||
(defun guix-switch-to-buffer (buffer)
 | 
			
		||||
  "Switch to a 'list' or 'info' BUFFER."
 | 
			
		||||
  (pop-to-buffer buffer
 | 
			
		||||
                 '((display-buffer-reuse-window
 | 
			
		||||
                    display-buffer-same-window))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Common definitions for buffer types
 | 
			
		||||
 | 
			
		||||
(defvar guix-buffer-data nil
 | 
			
		||||
  "Alist with 'buffer' data.
 | 
			
		||||
This alist is filled by `guix-buffer-define-interface' macro.")
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-value (buffer-type entry-type symbol)
 | 
			
		||||
  "Return SYMBOL's value for BUFFER-TYPE/ENTRY-TYPE from `guix-buffer-data'."
 | 
			
		||||
  (symbol-value
 | 
			
		||||
   (guix-assq-value guix-buffer-data buffer-type entry-type symbol)))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-param-title (buffer-type entry-type param)
 | 
			
		||||
  "Return PARAM title for BUFFER-TYPE/ENTRY-TYPE."
 | 
			
		||||
  (or (guix-assq-value (guix-buffer-value buffer-type entry-type 'titles)
 | 
			
		||||
                       param)
 | 
			
		||||
      ;; Fallback to a title defined in 'info' interface.
 | 
			
		||||
      (unless (eq buffer-type 'info)
 | 
			
		||||
        (guix-assq-value (guix-buffer-value 'info entry-type 'titles)
 | 
			
		||||
                         param))
 | 
			
		||||
      (guix-symbol-title param)))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-name (buffer-type entry-type profile)
 | 
			
		||||
  "Return name of BUFFER-TYPE buffer for displaying ENTRY-TYPE entries."
 | 
			
		||||
  (let ((str-or-fun (guix-buffer-value buffer-type entry-type
 | 
			
		||||
                                       'buffer-name)))
 | 
			
		||||
    (if (stringp str-or-fun)
 | 
			
		||||
        str-or-fun
 | 
			
		||||
      (funcall str-or-fun profile))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-history-size (buffer-type entry-type)
 | 
			
		||||
  "Return history size for BUFFER-TYPE/ENTRY-TYPE."
 | 
			
		||||
  (guix-buffer-value buffer-type entry-type 'history-size))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-revert-confirm? (buffer-type entry-type)
 | 
			
		||||
  "Return 'revert-confirm' value for BUFFER-TYPE/ENTRY-TYPE."
 | 
			
		||||
  (guix-buffer-value buffer-type entry-type 'revert-confirm))
 | 
			
		||||
 | 
			
		||||
(defvar guix-buffer-map
 | 
			
		||||
  (let ((map (make-sparse-keymap)))
 | 
			
		||||
    (define-key map (kbd "l") 'guix-history-back)
 | 
			
		||||
    (define-key map (kbd "r") 'guix-history-forward)
 | 
			
		||||
    (define-key map (kbd "g") 'revert-buffer)
 | 
			
		||||
    (define-key map (kbd "R") 'guix-buffer-redisplay)
 | 
			
		||||
    map)
 | 
			
		||||
  "Parent keymap for Guix buffer modes.")
 | 
			
		||||
 | 
			
		||||
(defvar-local guix-profile nil
 | 
			
		||||
  "Profile used for the current buffer.")
 | 
			
		||||
(put 'guix-profile 'permanent-local t)
 | 
			
		||||
 | 
			
		||||
(defvar-local guix-entries nil
 | 
			
		||||
  "List of the currently displayed entries.
 | 
			
		||||
Each element of the list is alist with entry info of the
 | 
			
		||||
following form:
 | 
			
		||||
 | 
			
		||||
  ((PARAM . VAL) ...)
 | 
			
		||||
 | 
			
		||||
PARAM is a name of the entry parameter.
 | 
			
		||||
VAL is a value of this parameter.")
 | 
			
		||||
(put 'guix-entries 'permanent-local t)
 | 
			
		||||
 | 
			
		||||
(defvar-local guix-buffer-type nil
 | 
			
		||||
  "Type of the current buffer.")
 | 
			
		||||
(put 'guix-buffer-type 'permanent-local t)
 | 
			
		||||
 | 
			
		||||
(defvar-local guix-entry-type nil
 | 
			
		||||
  "Type of the current entry.")
 | 
			
		||||
(put 'guix-entry-type 'permanent-local t)
 | 
			
		||||
 | 
			
		||||
(defvar-local guix-search-type nil
 | 
			
		||||
  "Type of the current search.")
 | 
			
		||||
(put 'guix-search-type 'permanent-local t)
 | 
			
		||||
 | 
			
		||||
(defvar-local guix-search-vals nil
 | 
			
		||||
  "Values of the current search.")
 | 
			
		||||
(put 'guix-search-vals 'permanent-local t)
 | 
			
		||||
 | 
			
		||||
(defsubst guix-set-vars (profile entries buffer-type entry-type
 | 
			
		||||
                         search-type search-vals)
 | 
			
		||||
  "Set local variables for the current Guix buffer."
 | 
			
		||||
  (setq default-directory profile
 | 
			
		||||
        guix-profile      profile
 | 
			
		||||
        guix-entries      entries
 | 
			
		||||
        guix-buffer-type  buffer-type
 | 
			
		||||
        guix-entry-type   entry-type
 | 
			
		||||
        guix-search-type  search-type
 | 
			
		||||
        guix-search-vals  search-vals))
 | 
			
		||||
 | 
			
		||||
(defun guix-get-symbol (postfix buffer-type &optional entry-type)
 | 
			
		||||
  (intern (concat "guix-"
 | 
			
		||||
                  (when entry-type
 | 
			
		||||
                    (concat (symbol-name entry-type) "-"))
 | 
			
		||||
                  (symbol-name buffer-type) "-" postfix)))
 | 
			
		||||
 | 
			
		||||
(defmacro guix-buffer-define-interface (buffer-type entry-type &rest args)
 | 
			
		||||
  "Define BUFFER-TYPE interface for displaying ENTRY-TYPE entries.
 | 
			
		||||
Remaining arguments (ARGS) should have a form [KEYWORD VALUE] ...
 | 
			
		||||
In the following description TYPE means ENTRY-TYPE-BUFFER-TYPE.
 | 
			
		||||
 | 
			
		||||
The following stuff should be defined outside this macro:
 | 
			
		||||
 | 
			
		||||
  - `guix-BUFFER-TYPE-mode' - parent mode of the generated mode.
 | 
			
		||||
 | 
			
		||||
  - `guix-TYPE-mode-initialize' (optional) - function for
 | 
			
		||||
  additional mode settings; it is called without arguments.
 | 
			
		||||
 | 
			
		||||
Required keywords:
 | 
			
		||||
 | 
			
		||||
  - `:buffer-name' - default value of the generated
 | 
			
		||||
    `guix-TYPE-buffer-name' variable.
 | 
			
		||||
 | 
			
		||||
Optional keywords:
 | 
			
		||||
 | 
			
		||||
  - `:titles' - default value of the generated
 | 
			
		||||
    `guix-TYPE-titles' variable.
 | 
			
		||||
 | 
			
		||||
  - `:history-size' - default value of the generated
 | 
			
		||||
    `guix-TYPE-history-size' variable.
 | 
			
		||||
 | 
			
		||||
  - `:revert-confirm?' - default value of the generated
 | 
			
		||||
    `guix-TYPE-revert-confirm' variable.
 | 
			
		||||
 | 
			
		||||
  - `:reduced?' - if non-nil, generate only group, faces group
 | 
			
		||||
    and titles variable."
 | 
			
		||||
  (declare (indent 2))
 | 
			
		||||
  (let* ((entry-type-str     (symbol-name entry-type))
 | 
			
		||||
         (buffer-type-str    (symbol-name buffer-type))
 | 
			
		||||
         (Entry-type-str     (capitalize entry-type-str))
 | 
			
		||||
         (Buffer-type-str    (capitalize buffer-type-str))
 | 
			
		||||
         (entry-str          (concat entry-type-str " entries"))
 | 
			
		||||
         (prefix             (concat "guix-" entry-type-str "-"
 | 
			
		||||
                                     buffer-type-str))
 | 
			
		||||
         (group              (intern prefix))
 | 
			
		||||
         (faces-group        (intern (concat prefix "-faces")))
 | 
			
		||||
         (mode-map-str       (concat prefix "-mode-map"))
 | 
			
		||||
         (parent-mode        (intern (concat "guix-" buffer-type-str "-mode")))
 | 
			
		||||
         (mode               (intern (concat prefix "-mode")))
 | 
			
		||||
         (mode-init-fun      (intern (concat prefix "-mode-initialize")))
 | 
			
		||||
         (buffer-name-var    (intern (concat prefix "-buffer-name")))
 | 
			
		||||
         (titles-var         (intern (concat prefix "-titles")))
 | 
			
		||||
         (history-size-var   (intern (concat prefix "-history-size")))
 | 
			
		||||
         (revert-confirm-var (intern (concat prefix "-revert-confirm"))))
 | 
			
		||||
    (guix-keyword-args-let args
 | 
			
		||||
        ((buffer-name-val    :buffer-name)
 | 
			
		||||
         (titles-val         :titles)
 | 
			
		||||
         (history-size-val   :history-size 20)
 | 
			
		||||
         (revert-confirm-val :revert-confirm? t)
 | 
			
		||||
         (reduced?           :reduced?))
 | 
			
		||||
      `(progn
 | 
			
		||||
         (defgroup ,group nil
 | 
			
		||||
           ,(format "Display '%s' entries in '%s' buffer."
 | 
			
		||||
                    entry-type-str buffer-type-str)
 | 
			
		||||
           :prefix ,(concat prefix "-")
 | 
			
		||||
           :group ',(intern (concat "guix-" buffer-type-str)))
 | 
			
		||||
 | 
			
		||||
         (defgroup ,faces-group nil
 | 
			
		||||
           ,(format "Faces for displaying '%s' entries in '%s' buffer."
 | 
			
		||||
                    entry-type-str buffer-type-str)
 | 
			
		||||
           :group ',(intern (concat "guix-" buffer-type-str "-faces")))
 | 
			
		||||
 | 
			
		||||
         (defcustom ,titles-var ,titles-val
 | 
			
		||||
           ,(format "Alist of titles of '%s' parameters."
 | 
			
		||||
                    entry-type-str)
 | 
			
		||||
           :type '(alist :key-type symbol :value-type string)
 | 
			
		||||
           :group ',group)
 | 
			
		||||
 | 
			
		||||
         ,(unless reduced?
 | 
			
		||||
            `(progn
 | 
			
		||||
               (defcustom ,buffer-name-var ,buffer-name-val
 | 
			
		||||
                 ,(format "\
 | 
			
		||||
Default name of '%s' buffer for displaying '%s' entries."
 | 
			
		||||
                          buffer-type-str entry-type-str)
 | 
			
		||||
                 :type 'string
 | 
			
		||||
                 :group ',group)
 | 
			
		||||
 | 
			
		||||
               (defcustom ,history-size-var ,history-size-val
 | 
			
		||||
                 ,(format "\
 | 
			
		||||
Maximum number of items saved in history of `%S' buffer.
 | 
			
		||||
If 0, the history is disabled."
 | 
			
		||||
                          buffer-name-var)
 | 
			
		||||
                 :type 'integer
 | 
			
		||||
                 :group ',group)
 | 
			
		||||
 | 
			
		||||
               (defcustom ,revert-confirm-var ,revert-confirm-val
 | 
			
		||||
                 ,(format "\
 | 
			
		||||
If non-nil, ask to confirm for reverting `%S' buffer."
 | 
			
		||||
                          buffer-name-var)
 | 
			
		||||
                 :type 'boolean
 | 
			
		||||
                 :group ',group)
 | 
			
		||||
 | 
			
		||||
               (guix-alist-put!
 | 
			
		||||
                '((buffer-name    . ,buffer-name-var)
 | 
			
		||||
                  (history-size   . ,history-size-var)
 | 
			
		||||
                  (revert-confirm . ,revert-confirm-var))
 | 
			
		||||
                'guix-buffer-data ',buffer-type ',entry-type)
 | 
			
		||||
 | 
			
		||||
               (define-derived-mode ,mode ,parent-mode
 | 
			
		||||
                 ,(concat "Guix-" Buffer-type-str)
 | 
			
		||||
                 ,(concat "Major mode for displaying information about "
 | 
			
		||||
                          entry-str ".\n\n"
 | 
			
		||||
                          "\\{" mode-map-str "}")
 | 
			
		||||
                 (setq-local revert-buffer-function 'guix-buffer-revert)
 | 
			
		||||
                 (setq-local guix-history-size
 | 
			
		||||
                             (guix-buffer-history-size
 | 
			
		||||
                              ',buffer-type ',entry-type))
 | 
			
		||||
                 (and (fboundp ',mode-init-fun) (,mode-init-fun)))))
 | 
			
		||||
 | 
			
		||||
         (guix-alist-put!
 | 
			
		||||
          ',titles-var 'guix-buffer-data
 | 
			
		||||
          ',buffer-type ',entry-type 'titles)))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Getting and displaying info about packages and generations
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -384,159 +158,6 @@ information)."
 | 
			
		|||
                 (const :tag "Display outputs" output))
 | 
			
		||||
  :group 'guix)
 | 
			
		||||
 | 
			
		||||
(defun guix-get-entries (profile entry-type search-type search-vals
 | 
			
		||||
                         &optional params)
 | 
			
		||||
  "Search for entries of ENTRY-TYPE.
 | 
			
		||||
 | 
			
		||||
Call an appropriate scheme function and return a list of the
 | 
			
		||||
form of `guix-entries'.
 | 
			
		||||
 | 
			
		||||
ENTRY-TYPE should be one of the following symbols: `package',
 | 
			
		||||
`output' or `generation'.
 | 
			
		||||
 | 
			
		||||
SEARCH-TYPE may be one of the following symbols:
 | 
			
		||||
 | 
			
		||||
- If ENTRY-TYPE is `package' or `output': `id', `name', `regexp',
 | 
			
		||||
  `all-available', `newest-available', `installed', `obsolete',
 | 
			
		||||
  `generation'.
 | 
			
		||||
 | 
			
		||||
- If ENTRY-TYPE is `generation': `id', `last', `all', `time'.
 | 
			
		||||
 | 
			
		||||
PARAMS is a list of parameters for receiving.  If nil, get
 | 
			
		||||
information with all available parameters."
 | 
			
		||||
  (guix-eval-read (guix-make-guile-expression
 | 
			
		||||
                   'entries
 | 
			
		||||
                   profile params entry-type search-type search-vals)))
 | 
			
		||||
 | 
			
		||||
(defun guix-get-show-entries (profile buffer-type entry-type search-type
 | 
			
		||||
                              &rest search-vals)
 | 
			
		||||
  "Search for ENTRY-TYPE entries and show results in BUFFER-TYPE buffer.
 | 
			
		||||
See `guix-get-entries' for the meaning of SEARCH-TYPE and SEARCH-VALS."
 | 
			
		||||
  (let ((entries (guix-get-entries profile entry-type search-type search-vals
 | 
			
		||||
                                   (guix-get-params-for-receiving
 | 
			
		||||
                                    buffer-type entry-type))))
 | 
			
		||||
    (guix-set-buffer profile entries buffer-type entry-type
 | 
			
		||||
                     search-type search-vals)))
 | 
			
		||||
 | 
			
		||||
(defun guix-set-buffer (profile entries buffer-type entry-type search-type
 | 
			
		||||
                        search-vals &optional history-replace no-display)
 | 
			
		||||
  "Set up BUFFER-TYPE buffer for displaying ENTRY-TYPE ENTRIES.
 | 
			
		||||
 | 
			
		||||
Insert ENTRIES in buffer, set variables and make history item.
 | 
			
		||||
ENTRIES should have a form of `guix-entries'.
 | 
			
		||||
 | 
			
		||||
See `guix-get-entries' for the meaning of SEARCH-TYPE and SEARCH-VALS.
 | 
			
		||||
 | 
			
		||||
If HISTORY-REPLACE is non-nil, replace current history item,
 | 
			
		||||
otherwise add the new one.
 | 
			
		||||
 | 
			
		||||
If NO-DISPLAY is non-nil, do not switch to the buffer."
 | 
			
		||||
  (when entries
 | 
			
		||||
    (let ((buf (if (and (eq major-mode
 | 
			
		||||
                            (guix-get-symbol "mode" buffer-type entry-type))
 | 
			
		||||
                        (equal guix-profile profile))
 | 
			
		||||
                   (current-buffer)
 | 
			
		||||
                 (get-buffer-create
 | 
			
		||||
                  (guix-buffer-name buffer-type entry-type profile)))))
 | 
			
		||||
      (with-current-buffer buf
 | 
			
		||||
        (guix-show-entries entries buffer-type entry-type)
 | 
			
		||||
        (guix-set-vars profile entries buffer-type entry-type
 | 
			
		||||
                       search-type search-vals)
 | 
			
		||||
        (funcall (if history-replace
 | 
			
		||||
                     #'guix-history-replace
 | 
			
		||||
                   #'guix-history-add)
 | 
			
		||||
                 (guix-make-history-item)))
 | 
			
		||||
      (or no-display
 | 
			
		||||
          (guix-switch-to-buffer buf))))
 | 
			
		||||
  (guix-result-message profile entries entry-type
 | 
			
		||||
                       search-type search-vals))
 | 
			
		||||
 | 
			
		||||
(defun guix-show-entries (entries buffer-type entry-type)
 | 
			
		||||
  "Display ENTRY-TYPE ENTRIES in the current BUFFER-TYPE buffer."
 | 
			
		||||
  (let ((inhibit-read-only t))
 | 
			
		||||
    (erase-buffer)
 | 
			
		||||
    (funcall (symbol-function (guix-get-symbol
 | 
			
		||||
                               "mode" buffer-type entry-type)))
 | 
			
		||||
    (funcall (guix-get-symbol "insert-entries" buffer-type)
 | 
			
		||||
             entries entry-type)
 | 
			
		||||
    (goto-char (point-min))))
 | 
			
		||||
 | 
			
		||||
(defun guix-history-call (profile entries buffer-type entry-type
 | 
			
		||||
                          search-type search-vals)
 | 
			
		||||
  "Function called for moving by history."
 | 
			
		||||
  (guix-show-entries entries buffer-type entry-type)
 | 
			
		||||
  (guix-set-vars profile entries buffer-type entry-type
 | 
			
		||||
                 search-type search-vals)
 | 
			
		||||
  (guix-result-message profile entries entry-type
 | 
			
		||||
                       search-type search-vals))
 | 
			
		||||
 | 
			
		||||
(defun guix-make-history-item ()
 | 
			
		||||
  "Make and return a history item for the current buffer."
 | 
			
		||||
  (list #'guix-history-call
 | 
			
		||||
        guix-profile guix-entries guix-buffer-type guix-entry-type
 | 
			
		||||
        guix-search-type guix-search-vals))
 | 
			
		||||
 | 
			
		||||
(defun guix-get-params-for-receiving (buffer-type entry-type)
 | 
			
		||||
  "Return parameters that should be received for BUFFER-TYPE, ENTRY-TYPE."
 | 
			
		||||
  (let* ((required-var (guix-get-symbol "required-params"
 | 
			
		||||
                                        buffer-type entry-type))
 | 
			
		||||
         (required (symbol-value required-var)))
 | 
			
		||||
    (unless (equal required 'all)
 | 
			
		||||
      (cl-union required
 | 
			
		||||
                (funcall (guix-get-symbol "displayed-params"
 | 
			
		||||
                                          buffer-type)
 | 
			
		||||
                         entry-type)))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-revert (_ignore-auto noconfirm)
 | 
			
		||||
  "Update information in the current buffer.
 | 
			
		||||
The function is suitable for `revert-buffer-function'.
 | 
			
		||||
See `revert-buffer' for the meaning of NOCONFIRM."
 | 
			
		||||
  (when (or noconfirm
 | 
			
		||||
            (guix-buffer-revert-confirm? guix-buffer-type
 | 
			
		||||
                                         guix-entry-type)
 | 
			
		||||
            (y-or-n-p "Update current information? "))
 | 
			
		||||
    (let* ((params (guix-get-params-for-receiving guix-buffer-type
 | 
			
		||||
                                                  guix-entry-type))
 | 
			
		||||
           (entries (guix-get-entries
 | 
			
		||||
                     guix-profile guix-entry-type
 | 
			
		||||
                     guix-search-type guix-search-vals params)))
 | 
			
		||||
      (guix-set-buffer guix-profile entries guix-buffer-type guix-entry-type
 | 
			
		||||
                       guix-search-type guix-search-vals t t))))
 | 
			
		||||
 | 
			
		||||
(defvar guix-buffer-after-redisplay-hook nil
 | 
			
		||||
  "Hook run by `guix-buffer-redisplay'.
 | 
			
		||||
This hook is called before seting up a window position.")
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-redisplay ()
 | 
			
		||||
  "Redisplay the current Guix buffer.
 | 
			
		||||
Restore the point and window positions after redisplaying.
 | 
			
		||||
 | 
			
		||||
This function does not update the buffer data, use
 | 
			
		||||
'\\[revert-buffer]' if you want the full update."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (let* ((old-point (point))
 | 
			
		||||
         ;; For simplicity, ignore an unlikely case when multiple
 | 
			
		||||
         ;; windows display the same buffer.
 | 
			
		||||
         (window (car (get-buffer-window-list (current-buffer) nil t)))
 | 
			
		||||
         (window-start (and window (window-start window))))
 | 
			
		||||
    (guix-set-buffer guix-profile guix-entries guix-buffer-type
 | 
			
		||||
                     guix-entry-type guix-search-type guix-search-vals
 | 
			
		||||
                     t t)
 | 
			
		||||
    (goto-char old-point)
 | 
			
		||||
    (run-hooks 'guix-buffer-after-redisplay-hook)
 | 
			
		||||
    (when window
 | 
			
		||||
      (set-window-point window (point))
 | 
			
		||||
      (set-window-start window window-start))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-redisplay-goto-button ()
 | 
			
		||||
  "Redisplay the current buffer and go to the next button, if needed."
 | 
			
		||||
  (let ((guix-buffer-after-redisplay-hook
 | 
			
		||||
         (cons (lambda ()
 | 
			
		||||
                 (unless (button-at (point))
 | 
			
		||||
                   (forward-button 1)))
 | 
			
		||||
               guix-buffer-after-redisplay-hook)))
 | 
			
		||||
    (guix-buffer-redisplay)))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Generations
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -640,13 +261,14 @@ Create the buffer if needed."
 | 
			
		|||
 | 
			
		||||
(defun guix-profile-generation-manifest-file (generation)
 | 
			
		||||
  "Return the file name of a GENERATION's manifest.
 | 
			
		||||
GENERATION is a generation number of `guix-profile' profile."
 | 
			
		||||
  (guix-manifest-file guix-profile generation))
 | 
			
		||||
GENERATION is a generation number of the current profile."
 | 
			
		||||
  (guix-manifest-file (guix-ui-current-profile) generation))
 | 
			
		||||
 | 
			
		||||
(defun guix-profile-generation-packages-buffer (generation)
 | 
			
		||||
  "Insert GENERATION's package outputs in a buffer and return it.
 | 
			
		||||
GENERATION is a generation number of `guix-profile' profile."
 | 
			
		||||
  (guix-generation-packages-buffer guix-profile generation))
 | 
			
		||||
GENERATION is a generation number of the current profile."
 | 
			
		||||
  (guix-generation-packages-buffer (guix-ui-current-profile)
 | 
			
		||||
                                   generation))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Actions on packages and generations
 | 
			
		||||
| 
						 | 
				
			
			@ -757,7 +379,7 @@ Ask a user if needed (see `guix-operation-confirm').
 | 
			
		|||
INSTALL, UPGRADE, REMOVE are 'package action specifications'.
 | 
			
		||||
See `guix-process-package-actions' for details."
 | 
			
		||||
  (or (null guix-operation-confirm)
 | 
			
		||||
      (let* ((entries (guix-get-entries
 | 
			
		||||
      (let* ((entries (guix-ui-get-entries
 | 
			
		||||
                       profile 'package 'id
 | 
			
		||||
                       (append (mapcar #'car install)
 | 
			
		||||
                               (mapcar #'car upgrade)
 | 
			
		||||
| 
						 | 
				
			
			@ -930,12 +552,12 @@ See Info node `(guix) Invoking guix package' for details.
 | 
			
		|||
Interactively, use the current profile and prompt for manifest
 | 
			
		||||
FILE.  With a prefix argument, also prompt for PROFILE."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let* ((default-profile (or guix-profile guix-current-profile))
 | 
			
		||||
   (let* ((current-profile (guix-ui-current-profile))
 | 
			
		||||
          (profile (if current-prefix-arg
 | 
			
		||||
                       (guix-profile-prompt)
 | 
			
		||||
                     default-profile))
 | 
			
		||||
                     (or current-profile guix-current-profile)))
 | 
			
		||||
          (file (read-file-name "File with manifest: "))
 | 
			
		||||
          (buffer (and guix-profile (current-buffer))))
 | 
			
		||||
          (buffer (and current-profile (current-buffer))))
 | 
			
		||||
     (list profile file buffer)))
 | 
			
		||||
  (when (or (not guix-operation-confirm)
 | 
			
		||||
            (y-or-n-p (format "Apply manifest from '%s' to profile '%s'? "
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										566
									
								
								emacs/guix-buffer.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										566
									
								
								emacs/guix-buffer.el
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,566 @@
 | 
			
		|||
;;; guix-buffer.el --- Buffer interface for displaying data  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright © 2014, 2015 Alex Kost <alezost@gmail.com>
 | 
			
		||||
 | 
			
		||||
;; This file is part of GNU Guix.
 | 
			
		||||
 | 
			
		||||
;; GNU Guix is free software; you can redistribute it and/or modify
 | 
			
		||||
;; it under the terms of the GNU General Public License as published by
 | 
			
		||||
;; the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
;; (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
;; GNU Guix is distributed in the hope that it will be useful,
 | 
			
		||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
;; GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
;; You should have received a copy of the GNU General Public License
 | 
			
		||||
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This file provides a general 'buffer' interface for displaying an
 | 
			
		||||
;; arbitrary data.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'cl-lib)
 | 
			
		||||
(require 'guix-history)
 | 
			
		||||
(require 'guix-utils)
 | 
			
		||||
 | 
			
		||||
(defvar guix-buffer-map
 | 
			
		||||
  (let ((map (make-sparse-keymap)))
 | 
			
		||||
    (define-key map (kbd "l") 'guix-history-back)
 | 
			
		||||
    (define-key map (kbd "r") 'guix-history-forward)
 | 
			
		||||
    (define-key map (kbd "g") 'revert-buffer)
 | 
			
		||||
    (define-key map (kbd "R") 'guix-buffer-redisplay)
 | 
			
		||||
    map)
 | 
			
		||||
  "Parent keymap for Guix buffer modes.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Buffer item
 | 
			
		||||
 | 
			
		||||
(cl-defstruct (guix-buffer-item
 | 
			
		||||
               (:constructor nil)
 | 
			
		||||
               (:constructor guix-buffer-make-item
 | 
			
		||||
                             (entries buffer-type entry-type args))
 | 
			
		||||
               (:copier      nil))
 | 
			
		||||
  entries buffer-type entry-type args)
 | 
			
		||||
 | 
			
		||||
(defvar-local guix-buffer-item nil
 | 
			
		||||
  "Data (structure) for the current Guix buffer.
 | 
			
		||||
The structure consists of the following elements:
 | 
			
		||||
 | 
			
		||||
- `entries': list of the currently displayed entries.
 | 
			
		||||
 | 
			
		||||
  Each element of the list is an alist with an entry data of the
 | 
			
		||||
  following form:
 | 
			
		||||
 | 
			
		||||
    ((PARAM . VAL) ...)
 | 
			
		||||
 | 
			
		||||
  PARAM is a name of the entry parameter.
 | 
			
		||||
  VAL is a value of this parameter.
 | 
			
		||||
 | 
			
		||||
- `entry-type': type of the currently displayed entries.
 | 
			
		||||
 | 
			
		||||
- `buffer-type': type of the current buffer.
 | 
			
		||||
 | 
			
		||||
- `args': search arguments used to get the current entries.")
 | 
			
		||||
(put 'guix-buffer-item 'permanent-local t)
 | 
			
		||||
 | 
			
		||||
(defmacro guix-buffer-with-item (item &rest body)
 | 
			
		||||
  "Evaluate BODY using buffer ITEM.
 | 
			
		||||
The following local variables are available inside BODY:
 | 
			
		||||
`%entries', `%buffer-type', `%entry-type', `%args'.
 | 
			
		||||
See `guix-buffer-item' for details."
 | 
			
		||||
  (declare (indent 1) (debug t))
 | 
			
		||||
  (let ((item-var (make-symbol "item")))
 | 
			
		||||
    `(let ((,item-var ,item))
 | 
			
		||||
       (let ((%entries     (guix-buffer-item-entries     ,item-var))
 | 
			
		||||
             (%buffer-type (guix-buffer-item-buffer-type ,item-var))
 | 
			
		||||
             (%entry-type  (guix-buffer-item-entry-type  ,item-var))
 | 
			
		||||
             (%args        (guix-buffer-item-args        ,item-var)))
 | 
			
		||||
         ,@body))))
 | 
			
		||||
 | 
			
		||||
(defmacro guix-buffer-with-current-item (&rest body)
 | 
			
		||||
  "Evaluate BODY using `guix-buffer-item'.
 | 
			
		||||
See `guix-buffer-with-item' for details."
 | 
			
		||||
  (declare (indent 0) (debug t))
 | 
			
		||||
  `(guix-buffer-with-item guix-buffer-item
 | 
			
		||||
     ,@body))
 | 
			
		||||
 | 
			
		||||
(defmacro guix-buffer-define-current-item-accessor (name)
 | 
			
		||||
  "Define `guix-buffer-current-NAME' function to access NAME
 | 
			
		||||
element of `guix-buffer-item' structure.
 | 
			
		||||
NAME should be a symbol."
 | 
			
		||||
  (let* ((name-str (symbol-name name))
 | 
			
		||||
         (accessor (intern (concat "guix-buffer-item-" name-str)))
 | 
			
		||||
         (fun-name (intern (concat "guix-buffer-current-" name-str)))
 | 
			
		||||
         (doc      (format "\
 | 
			
		||||
Return '%s' of the current Guix buffer.
 | 
			
		||||
See `guix-buffer-item' for details."
 | 
			
		||||
                           name-str)))
 | 
			
		||||
    `(defun ,fun-name ()
 | 
			
		||||
       ,doc
 | 
			
		||||
       (and guix-buffer-item
 | 
			
		||||
            (,accessor guix-buffer-item)))))
 | 
			
		||||
 | 
			
		||||
(defmacro guix-buffer-define-current-item-accessors (&rest names)
 | 
			
		||||
  "Define `guix-buffer-current-NAME' functions for NAMES.
 | 
			
		||||
See `guix-buffer-define-current-item-accessor' for details."
 | 
			
		||||
  `(progn
 | 
			
		||||
     ,@(mapcar (lambda (name)
 | 
			
		||||
                 `(guix-buffer-define-current-item-accessor ,name))
 | 
			
		||||
               names)))
 | 
			
		||||
 | 
			
		||||
(guix-buffer-define-current-item-accessors
 | 
			
		||||
 entries entry-type buffer-type args)
 | 
			
		||||
 | 
			
		||||
(defmacro guix-buffer-define-current-args-accessor (n prefix name)
 | 
			
		||||
  "Define `PREFIX-NAME' function to access Nth element of 'args'
 | 
			
		||||
field of `guix-buffer-item' structure.
 | 
			
		||||
PREFIX and NAME should be strings."
 | 
			
		||||
  (let ((fun-name (intern (concat prefix "-" name)))
 | 
			
		||||
        (doc      (format "\
 | 
			
		||||
Return '%s' of the current Guix buffer.
 | 
			
		||||
'%s' is the element number %d in 'args' of `guix-buffer-item'."
 | 
			
		||||
                          name name n)))
 | 
			
		||||
    `(defun ,fun-name ()
 | 
			
		||||
       ,doc
 | 
			
		||||
       (nth ,n (guix-buffer-current-args)))))
 | 
			
		||||
 | 
			
		||||
(defmacro guix-buffer-define-current-args-accessors (prefix &rest names)
 | 
			
		||||
  "Define `PREFIX-NAME' functions for NAMES.
 | 
			
		||||
See `guix-buffer-define-current-args-accessor' for details."
 | 
			
		||||
  `(progn
 | 
			
		||||
     ,@(cl-loop for name in names
 | 
			
		||||
                for i from 0
 | 
			
		||||
                collect `(guix-buffer-define-current-args-accessor
 | 
			
		||||
                          ,i ,prefix ,name))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Wrappers for defined variables
 | 
			
		||||
 | 
			
		||||
(defvar guix-buffer-data nil
 | 
			
		||||
  "Alist with 'buffer' data.
 | 
			
		||||
This alist is filled by `guix-buffer-define-interface' macro.")
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-value (buffer-type entry-type symbol)
 | 
			
		||||
  "Return SYMBOL's value for BUFFER-TYPE/ENTRY-TYPE from `guix-buffer-data'."
 | 
			
		||||
  (symbol-value
 | 
			
		||||
   (guix-assq-value guix-buffer-data buffer-type entry-type symbol)))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-get-entries (buffer-type entry-type args)
 | 
			
		||||
  "Return ENTRY-TYPE entries.
 | 
			
		||||
Call an appropriate 'get-entries' function from `guix-buffer'
 | 
			
		||||
using ARGS as its arguments."
 | 
			
		||||
  (apply (guix-buffer-value buffer-type entry-type 'get-entries)
 | 
			
		||||
         args))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-mode-enable (buffer-type entry-type)
 | 
			
		||||
  "Turn on major mode to display ENTRY-TYPE ENTRIES in BUFFER-TYPE buffer."
 | 
			
		||||
  (funcall (guix-buffer-value buffer-type entry-type 'mode)))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-mode-initialize (buffer-type entry-type)
 | 
			
		||||
  "Set up the current BUFFER-TYPE buffer to display ENTRY-TYPE entries."
 | 
			
		||||
  (let ((fun (guix-buffer-value buffer-type entry-type 'mode-init)))
 | 
			
		||||
    (when fun
 | 
			
		||||
      (funcall fun))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-insert-entries (entries buffer-type entry-type)
 | 
			
		||||
  "Show ENTRY-TYPE ENTRIES in the current BUFFER-TYPE buffer."
 | 
			
		||||
  (funcall (guix-buffer-value buffer-type entry-type 'insert-entries)
 | 
			
		||||
           entries))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-show-entries-default (entries buffer-type entry-type)
 | 
			
		||||
  "Show ENTRY-TYPE ENTRIES in the current BUFFER-TYPE buffer."
 | 
			
		||||
  (let ((inhibit-read-only t))
 | 
			
		||||
    (erase-buffer)
 | 
			
		||||
    (guix-buffer-mode-enable buffer-type entry-type)
 | 
			
		||||
    (guix-buffer-insert-entries entries buffer-type entry-type)
 | 
			
		||||
    (goto-char (point-min))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-show-entries (entries buffer-type entry-type)
 | 
			
		||||
  "Show ENTRY-TYPE ENTRIES in the current BUFFER-TYPE buffer."
 | 
			
		||||
  (funcall (guix-buffer-value buffer-type entry-type 'show-entries)
 | 
			
		||||
           entries))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-message (entries buffer-type entry-type args)
 | 
			
		||||
  "Display a message for BUFFER-ITEM after showing entries."
 | 
			
		||||
  (let ((fun (guix-buffer-value buffer-type entry-type 'message)))
 | 
			
		||||
    (when fun
 | 
			
		||||
      (apply fun entries args))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-name (buffer-type entry-type args)
 | 
			
		||||
  "Return name of BUFFER-TYPE buffer for displaying ENTRY-TYPE entries."
 | 
			
		||||
  (let ((str-or-fun (guix-buffer-value buffer-type entry-type
 | 
			
		||||
                                       'buffer-name)))
 | 
			
		||||
    (if (stringp str-or-fun)
 | 
			
		||||
        str-or-fun
 | 
			
		||||
      (apply str-or-fun args))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-param-title (buffer-type entry-type param)
 | 
			
		||||
  "Return PARAM title for BUFFER-TYPE/ENTRY-TYPE."
 | 
			
		||||
  (or (guix-assq-value (guix-buffer-value buffer-type entry-type 'titles)
 | 
			
		||||
                       param)
 | 
			
		||||
      ;; Fallback to a title defined in 'info' interface.
 | 
			
		||||
      (unless (eq buffer-type 'info)
 | 
			
		||||
        (guix-assq-value (guix-buffer-value 'info entry-type 'titles)
 | 
			
		||||
                         param))
 | 
			
		||||
      (guix-symbol-title param)))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-history-size (buffer-type entry-type)
 | 
			
		||||
  "Return history size for BUFFER-TYPE/ENTRY-TYPE."
 | 
			
		||||
  (guix-buffer-value buffer-type entry-type 'history-size))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-revert-confirm? (buffer-type entry-type)
 | 
			
		||||
  "Return 'revert-confirm' value for BUFFER-TYPE/ENTRY-TYPE."
 | 
			
		||||
  (guix-buffer-value buffer-type entry-type 'revert-confirm))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Displaying entries
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-display (buffer)
 | 
			
		||||
  "Switch to a Guix BUFFER."
 | 
			
		||||
  (pop-to-buffer buffer
 | 
			
		||||
                 '((display-buffer-reuse-window
 | 
			
		||||
                    display-buffer-same-window))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-history-item (buffer-item)
 | 
			
		||||
  "Make and return a history item for displaying BUFFER-ITEM."
 | 
			
		||||
  (list #'guix-buffer-set buffer-item))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-set (buffer-item &optional history)
 | 
			
		||||
  "Set up the current buffer for displaying BUFFER-ITEM.
 | 
			
		||||
HISTORY should be one of the following:
 | 
			
		||||
 | 
			
		||||
  `nil' - do not save BUFFER-ITEM in history,
 | 
			
		||||
 | 
			
		||||
  `add' - add it to history,
 | 
			
		||||
 | 
			
		||||
  `replace' - replace the current history item."
 | 
			
		||||
  (guix-buffer-with-item buffer-item
 | 
			
		||||
    (when %entries
 | 
			
		||||
      (guix-buffer-show-entries %entries %buffer-type %entry-type)
 | 
			
		||||
      (setq guix-buffer-item buffer-item)
 | 
			
		||||
      (when history
 | 
			
		||||
        (funcall (cl-ecase history
 | 
			
		||||
                   (add     #'guix-history-add)
 | 
			
		||||
                   (replace #'guix-history-replace))
 | 
			
		||||
                 (guix-buffer-history-item buffer-item))))
 | 
			
		||||
    (guix-buffer-message %entries %buffer-type %entry-type %args)))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-display-entries-current
 | 
			
		||||
    (entries buffer-type entry-type args &optional history)
 | 
			
		||||
  "Show ENTRIES in the current Guix buffer.
 | 
			
		||||
See `guix-buffer-item' for the meaning of BUFFER-TYPE, ENTRY-TYPE
 | 
			
		||||
and ARGS, and `guix-buffer-set' for the meaning of HISTORY."
 | 
			
		||||
  (let ((item (guix-buffer-make-item entries buffer-type
 | 
			
		||||
                                     entry-type args)))
 | 
			
		||||
    (guix-buffer-set item history)))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-get-display-entries-current
 | 
			
		||||
    (buffer-type entry-type args &optional history)
 | 
			
		||||
  "Search for entries and show them in the current Guix buffer.
 | 
			
		||||
See `guix-buffer-display-entries-current' for details."
 | 
			
		||||
  (guix-buffer-display-entries-current
 | 
			
		||||
   (guix-buffer-get-entries buffer-type entry-type args)
 | 
			
		||||
   buffer-type entry-type args history))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-display-entries
 | 
			
		||||
    (entries buffer-type entry-type args &optional history)
 | 
			
		||||
  "Show ENTRIES in a BUFFER-TYPE buffer.
 | 
			
		||||
See `guix-buffer-display-entries-current' for details."
 | 
			
		||||
  (let ((buffer (get-buffer-create
 | 
			
		||||
                 (guix-buffer-name buffer-type entry-type args))))
 | 
			
		||||
    (with-current-buffer buffer
 | 
			
		||||
      (guix-buffer-display-entries-current
 | 
			
		||||
       entries buffer-type entry-type args history))
 | 
			
		||||
    (when entries
 | 
			
		||||
      (guix-buffer-display buffer))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-get-display-entries
 | 
			
		||||
    (buffer-type entry-type args &optional history)
 | 
			
		||||
  "Search for entries and show them in a BUFFER-TYPE buffer.
 | 
			
		||||
See `guix-buffer-display-entries-current' for details."
 | 
			
		||||
  (guix-buffer-display-entries
 | 
			
		||||
   (guix-buffer-get-entries buffer-type entry-type args)
 | 
			
		||||
   buffer-type entry-type args history))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-revert (_ignore-auto noconfirm)
 | 
			
		||||
  "Update the data in the current Guix buffer.
 | 
			
		||||
This function is suitable for `revert-buffer-function'.
 | 
			
		||||
See `revert-buffer' for the meaning of NOCONFIRM."
 | 
			
		||||
  (guix-buffer-with-current-item
 | 
			
		||||
    (when (or noconfirm
 | 
			
		||||
              (not (guix-buffer-revert-confirm? %buffer-type %entry-type))
 | 
			
		||||
              (y-or-n-p "Update the current buffer? "))
 | 
			
		||||
      (guix-buffer-get-display-entries-current
 | 
			
		||||
       %buffer-type %entry-type %args 'replace))))
 | 
			
		||||
 | 
			
		||||
(defvar guix-buffer-after-redisplay-hook nil
 | 
			
		||||
  "Hook run by `guix-buffer-redisplay'.
 | 
			
		||||
This hook is called before seting up a window position.")
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-redisplay ()
 | 
			
		||||
  "Redisplay the current Guix buffer.
 | 
			
		||||
Restore the point and window positions after redisplaying.
 | 
			
		||||
 | 
			
		||||
This function does not update the buffer data, use
 | 
			
		||||
'\\[revert-buffer]' if you want the full update."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (let* ((old-point (point))
 | 
			
		||||
         ;; For simplicity, ignore an unlikely case when multiple
 | 
			
		||||
         ;; windows display the same buffer.
 | 
			
		||||
         (window (car (get-buffer-window-list (current-buffer) nil t)))
 | 
			
		||||
         (window-start (and window (window-start window))))
 | 
			
		||||
    (guix-buffer-set guix-buffer-item)
 | 
			
		||||
    (goto-char old-point)
 | 
			
		||||
    (run-hooks 'guix-buffer-after-redisplay-hook)
 | 
			
		||||
    (when window
 | 
			
		||||
      (set-window-point window (point))
 | 
			
		||||
      (set-window-start window window-start))))
 | 
			
		||||
 | 
			
		||||
(defun guix-buffer-redisplay-goto-button ()
 | 
			
		||||
  "Redisplay the current buffer and go to the next button, if needed."
 | 
			
		||||
  (let ((guix-buffer-after-redisplay-hook
 | 
			
		||||
         (cons (lambda ()
 | 
			
		||||
                 (unless (button-at (point))
 | 
			
		||||
                   (forward-button 1)))
 | 
			
		||||
               guix-buffer-after-redisplay-hook)))
 | 
			
		||||
    (guix-buffer-redisplay)))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Interface definer
 | 
			
		||||
 | 
			
		||||
(defmacro guix-buffer-define-interface (buffer-type entry-type &rest args)
 | 
			
		||||
  "Define BUFFER-TYPE interface for displaying ENTRY-TYPE entries.
 | 
			
		||||
Remaining arguments (ARGS) should have a form [KEYWORD VALUE] ...
 | 
			
		||||
In the following description TYPE means ENTRY-TYPE-BUFFER-TYPE.
 | 
			
		||||
 | 
			
		||||
Required keywords:
 | 
			
		||||
 | 
			
		||||
  - `:buffer-name' - default value of the generated
 | 
			
		||||
    `guix-TYPE-buffer-name' variable.
 | 
			
		||||
 | 
			
		||||
  - `:get-entries-function' - default value of the generated
 | 
			
		||||
    `guix-TYPE-get-function' variable.
 | 
			
		||||
 | 
			
		||||
  - `:show-entries-function' - default value of the generated
 | 
			
		||||
    `guix-TYPE-show-function' variable.
 | 
			
		||||
 | 
			
		||||
  Alternatively, if `:show-entries-function' is not specified, a
 | 
			
		||||
  default `guix-TYPE-show-entries' will be generated, and the
 | 
			
		||||
  following keyword should be specified instead:
 | 
			
		||||
 | 
			
		||||
  - `:insert-entries-function' - default value of the generated
 | 
			
		||||
    `guix-TYPE-insert-function' variable.
 | 
			
		||||
 | 
			
		||||
Optional keywords:
 | 
			
		||||
 | 
			
		||||
  - `:message-function' - default value of the generated
 | 
			
		||||
    `guix-TYPE-message-function' variable.
 | 
			
		||||
 | 
			
		||||
  - `:titles' - default value of the generated
 | 
			
		||||
    `guix-TYPE-titles' variable.
 | 
			
		||||
 | 
			
		||||
  - `:history-size' - default value of the generated
 | 
			
		||||
    `guix-TYPE-history-size' variable.
 | 
			
		||||
 | 
			
		||||
  - `:revert-confirm?' - default value of the generated
 | 
			
		||||
    `guix-TYPE-revert-confirm' variable.
 | 
			
		||||
 | 
			
		||||
  - `:mode-name' - name (a string appeared in the mode-line) of
 | 
			
		||||
     the generated `guix-TYPE-mode'.
 | 
			
		||||
 | 
			
		||||
  - `:mode-init-function' - default value of the generated
 | 
			
		||||
    `guix-TYPE-mode-initialize-function' variable.
 | 
			
		||||
 | 
			
		||||
  - `:reduced?' - if non-nil, generate only group, faces group
 | 
			
		||||
    and titles variable (if specified); all keywords become
 | 
			
		||||
    optional."
 | 
			
		||||
  (declare (indent 2))
 | 
			
		||||
  (let* ((entry-type-str     (symbol-name entry-type))
 | 
			
		||||
         (buffer-type-str    (symbol-name buffer-type))
 | 
			
		||||
         (prefix             (concat "guix-" entry-type-str "-"
 | 
			
		||||
                                     buffer-type-str))
 | 
			
		||||
         (group              (intern prefix))
 | 
			
		||||
         (faces-group        (intern (concat prefix "-faces")))
 | 
			
		||||
         (get-entries-var    (intern (concat prefix "-get-function")))
 | 
			
		||||
         (show-entries-var   (intern (concat prefix "-show-function")))
 | 
			
		||||
         (show-entries-fun   (intern (concat prefix "-show-entries")))
 | 
			
		||||
         (message-var        (intern (concat prefix "-message-function")))
 | 
			
		||||
         (buffer-name-var    (intern (concat prefix "-buffer-name")))
 | 
			
		||||
         (titles-var         (intern (concat prefix "-titles")))
 | 
			
		||||
         (history-size-var   (intern (concat prefix "-history-size")))
 | 
			
		||||
         (revert-confirm-var (intern (concat prefix "-revert-confirm"))))
 | 
			
		||||
    (guix-keyword-args-let args
 | 
			
		||||
        ((get-entries-val    :get-entries-function)
 | 
			
		||||
         (show-entries-val   :show-entries-function)
 | 
			
		||||
         (insert-entries-val :insert-entries-function)
 | 
			
		||||
         (mode-name          :mode-name (capitalize prefix))
 | 
			
		||||
         (mode-init-val      :mode-init-function)
 | 
			
		||||
         (message-val        :message-function)
 | 
			
		||||
         (buffer-name-val    :buffer-name)
 | 
			
		||||
         (titles-val         :titles)
 | 
			
		||||
         (history-size-val   :history-size 20)
 | 
			
		||||
         (revert-confirm-val :revert-confirm? t)
 | 
			
		||||
         (reduced?           :reduced?))
 | 
			
		||||
      `(progn
 | 
			
		||||
         (defgroup ,group nil
 | 
			
		||||
           ,(format "Display '%s' entries in '%s' buffer."
 | 
			
		||||
                    entry-type-str buffer-type-str)
 | 
			
		||||
           :prefix ,(concat prefix "-")
 | 
			
		||||
           :group ',(intern (concat "guix-" buffer-type-str)))
 | 
			
		||||
 | 
			
		||||
         (defgroup ,faces-group nil
 | 
			
		||||
           ,(format "Faces for displaying '%s' entries in '%s' buffer."
 | 
			
		||||
                    entry-type-str buffer-type-str)
 | 
			
		||||
           :group ',(intern (concat "guix-" buffer-type-str "-faces")))
 | 
			
		||||
 | 
			
		||||
         (defcustom ,titles-var ,titles-val
 | 
			
		||||
           ,(format "Alist of titles of '%s' parameters."
 | 
			
		||||
                    entry-type-str)
 | 
			
		||||
           :type '(alist :key-type symbol :value-type string)
 | 
			
		||||
           :group ',group)
 | 
			
		||||
 | 
			
		||||
         ,(unless reduced?
 | 
			
		||||
            `(progn
 | 
			
		||||
               (defvar ,get-entries-var ,get-entries-val
 | 
			
		||||
                 ,(format "\
 | 
			
		||||
Function used to receive '%s' entries for '%s' buffer."
 | 
			
		||||
                          entry-type-str buffer-type-str))
 | 
			
		||||
 | 
			
		||||
               (defvar ,show-entries-var
 | 
			
		||||
                 ,(or show-entries-val `',show-entries-fun)
 | 
			
		||||
                 ,(format "\
 | 
			
		||||
Function used to show '%s' entries in '%s' buffer."
 | 
			
		||||
                          entry-type-str buffer-type-str))
 | 
			
		||||
 | 
			
		||||
               (defvar ,message-var ,message-val
 | 
			
		||||
                 ,(format "\
 | 
			
		||||
Function used to display a message after showing '%s' entries.
 | 
			
		||||
If nil, do not display messages."
 | 
			
		||||
                          entry-type-str))
 | 
			
		||||
 | 
			
		||||
               (defcustom ,buffer-name-var ,buffer-name-val
 | 
			
		||||
                 ,(format "\
 | 
			
		||||
Default name of '%s' buffer for displaying '%s' entries.
 | 
			
		||||
May be a string or a function returning a string.  The function
 | 
			
		||||
is called with the same arguments as `%S'."
 | 
			
		||||
                          buffer-type-str entry-type-str get-entries-var)
 | 
			
		||||
                 :type '(choice string function)
 | 
			
		||||
                 :group ',group)
 | 
			
		||||
 | 
			
		||||
               (defcustom ,history-size-var ,history-size-val
 | 
			
		||||
                 ,(format "\
 | 
			
		||||
Maximum number of items saved in history of `%S' buffer.
 | 
			
		||||
If 0, the history is disabled."
 | 
			
		||||
                          buffer-name-var)
 | 
			
		||||
                 :type 'integer
 | 
			
		||||
                 :group ',group)
 | 
			
		||||
 | 
			
		||||
               (defcustom ,revert-confirm-var ,revert-confirm-val
 | 
			
		||||
                 ,(format "\
 | 
			
		||||
If non-nil, ask to confirm for reverting `%S' buffer."
 | 
			
		||||
                          buffer-name-var)
 | 
			
		||||
                 :type 'boolean
 | 
			
		||||
                 :group ',group)
 | 
			
		||||
 | 
			
		||||
               (guix-alist-put!
 | 
			
		||||
                '((get-entries    . ,get-entries-var)
 | 
			
		||||
                  (show-entries   . ,show-entries-var)
 | 
			
		||||
                  (message        . ,message-var)
 | 
			
		||||
                  (buffer-name    . ,buffer-name-var)
 | 
			
		||||
                  (history-size   . ,history-size-var)
 | 
			
		||||
                  (revert-confirm . ,revert-confirm-var))
 | 
			
		||||
                'guix-buffer-data ',buffer-type ',entry-type)
 | 
			
		||||
 | 
			
		||||
               ,(unless show-entries-val
 | 
			
		||||
                  `(defun ,show-entries-fun (entries)
 | 
			
		||||
                     ,(format "\
 | 
			
		||||
Show '%s' ENTRIES in the current '%s' buffer."
 | 
			
		||||
                              entry-type-str buffer-type-str)
 | 
			
		||||
                     (guix-buffer-show-entries-default
 | 
			
		||||
                      entries ',buffer-type ',entry-type)))
 | 
			
		||||
 | 
			
		||||
               ,(when (or insert-entries-val
 | 
			
		||||
                          (null show-entries-val))
 | 
			
		||||
                  (let ((insert-entries-var
 | 
			
		||||
                         (intern (concat prefix "-insert-function"))))
 | 
			
		||||
                    `(progn
 | 
			
		||||
                       (defvar ,insert-entries-var ,insert-entries-val
 | 
			
		||||
                         ,(format "\
 | 
			
		||||
Function used to print '%s' entries in '%s' buffer."
 | 
			
		||||
                                  entry-type-str buffer-type-str))
 | 
			
		||||
 | 
			
		||||
                       (guix-alist-put!
 | 
			
		||||
                        ',insert-entries-var 'guix-buffer-data
 | 
			
		||||
                        ',buffer-type ',entry-type
 | 
			
		||||
                        'insert-entries))))
 | 
			
		||||
 | 
			
		||||
               ,(when (or mode-name
 | 
			
		||||
                          mode-init-val
 | 
			
		||||
                          (null show-entries-val))
 | 
			
		||||
                  (let* ((mode-str      (concat prefix "-mode"))
 | 
			
		||||
                         (mode-map-str  (concat mode-str "-map"))
 | 
			
		||||
                         (mode          (intern mode-str))
 | 
			
		||||
                         (parent-mode   (intern
 | 
			
		||||
                                         (concat "guix-" buffer-type-str
 | 
			
		||||
                                                 "-mode")))
 | 
			
		||||
                         (mode-var      (intern
 | 
			
		||||
                                         (concat mode-str "-function")))
 | 
			
		||||
                         (mode-init-var (intern
 | 
			
		||||
                                         (concat mode-str
 | 
			
		||||
                                                 "-initialize-function"))))
 | 
			
		||||
                    `(progn
 | 
			
		||||
                       (defvar ,mode-var ',mode
 | 
			
		||||
                         ,(format "\
 | 
			
		||||
Major mode for displaying '%s' entries in '%s' buffer."
 | 
			
		||||
                                  entry-type-str buffer-type-str))
 | 
			
		||||
 | 
			
		||||
                       (defvar ,mode-init-var ,mode-init-val
 | 
			
		||||
                         ,(format "\
 | 
			
		||||
Function used to set up '%s' buffer for displaying '%s' entries."
 | 
			
		||||
                                  buffer-type-str entry-type-str))
 | 
			
		||||
 | 
			
		||||
                       (define-derived-mode ,mode ,parent-mode ,mode-name
 | 
			
		||||
                         ,(format "\
 | 
			
		||||
Major mode for displaying '%s' entries in '%s' buffer.
 | 
			
		||||
 | 
			
		||||
\\{%s}"
 | 
			
		||||
                                  entry-type-str buffer-type-str mode-map-str)
 | 
			
		||||
                         (setq-local revert-buffer-function
 | 
			
		||||
                                     'guix-buffer-revert)
 | 
			
		||||
                         (setq-local guix-history-size
 | 
			
		||||
                                     (guix-buffer-history-size
 | 
			
		||||
                                      ',buffer-type ',entry-type))
 | 
			
		||||
                         (guix-buffer-mode-initialize
 | 
			
		||||
                          ',buffer-type ',entry-type))
 | 
			
		||||
 | 
			
		||||
                       (guix-alist-put!
 | 
			
		||||
                        ',mode-var 'guix-buffer-data
 | 
			
		||||
                        ',buffer-type ',entry-type 'mode)
 | 
			
		||||
                       (guix-alist-put!
 | 
			
		||||
                        ',mode-init-var 'guix-buffer-data
 | 
			
		||||
                        ',buffer-type ',entry-type
 | 
			
		||||
                        'mode-init))))))
 | 
			
		||||
 | 
			
		||||
         (guix-alist-put!
 | 
			
		||||
          ',titles-var 'guix-buffer-data
 | 
			
		||||
          ',buffer-type ',entry-type 'titles)))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
(defvar guix-buffer-font-lock-keywords
 | 
			
		||||
  (eval-when-compile
 | 
			
		||||
    `((,(rx "(" (group (or "guix-buffer-with-item"
 | 
			
		||||
                           "guix-buffer-with-current-item"
 | 
			
		||||
                           "guix-buffer-define-interface"))
 | 
			
		||||
            symbol-end)
 | 
			
		||||
       . 1))))
 | 
			
		||||
 | 
			
		||||
(font-lock-add-keywords 'emacs-lisp-mode guix-buffer-font-lock-keywords)
 | 
			
		||||
 | 
			
		||||
(provide 'guix-buffer)
 | 
			
		||||
 | 
			
		||||
;;; guix-buffer.el ends here
 | 
			
		||||
| 
						 | 
				
			
			@ -202,8 +202,7 @@ LEVEL is 1 by default."
 | 
			
		|||
  (insert (guix-info-get-indent level)))
 | 
			
		||||
 | 
			
		||||
(defun guix-info-insert-entries (entries entry-type)
 | 
			
		||||
  "Display ENTRIES of ENTRY-TYPE in the current info buffer.
 | 
			
		||||
ENTRIES should have a form of `guix-entries'."
 | 
			
		||||
  "Display ENTRY-TYPE ENTRIES in the current info buffer."
 | 
			
		||||
  (guix-mapinsert (lambda (entry)
 | 
			
		||||
                    (guix-info-insert-entry entry entry-type))
 | 
			
		||||
                  entries
 | 
			
		||||
| 
						 | 
				
			
			@ -371,8 +370,11 @@ BUTTON-OR-FACE is a button type)."
 | 
			
		|||
  'face 'guix-package-info-name-button
 | 
			
		||||
  'help-echo "Describe this package"
 | 
			
		||||
  'action (lambda (btn)
 | 
			
		||||
            (guix-get-show-entries guix-profile 'info guix-package-info-type
 | 
			
		||||
                                   'name (button-label btn))))
 | 
			
		||||
            (guix-buffer-get-display-entries-current
 | 
			
		||||
             'info guix-package-info-type
 | 
			
		||||
             (list (guix-ui-current-profile)
 | 
			
		||||
                   'name (button-label btn))
 | 
			
		||||
             'add)))
 | 
			
		||||
 | 
			
		||||
(defun guix-info-button-copy-label (&optional pos)
 | 
			
		||||
  "Copy a label of the button at POS into kill ring.
 | 
			
		||||
| 
						 | 
				
			
			@ -407,7 +409,8 @@ See `insert-text-button' for the meaning of PROPERTIES."
 | 
			
		|||
  "Keymap for `guix-info-mode' buffers.")
 | 
			
		||||
 | 
			
		||||
(define-derived-mode guix-info-mode special-mode "Guix-Info"
 | 
			
		||||
  "Parent mode for displaying information in info buffers.")
 | 
			
		||||
  "Parent mode for displaying data in 'info' form."
 | 
			
		||||
  (setq-local revert-buffer-function 'guix-buffer-revert))
 | 
			
		||||
 | 
			
		||||
(defun guix-info-mode-initialize ()
 | 
			
		||||
  "Set up the current 'info' buffer."
 | 
			
		||||
| 
						 | 
				
			
			@ -435,7 +438,8 @@ The rest keyword arguments are passed to
 | 
			
		|||
         (group              (intern prefix))
 | 
			
		||||
         (format-var         (intern (concat prefix "-format"))))
 | 
			
		||||
    (guix-keyword-args-let args
 | 
			
		||||
        ((format-val         :format))
 | 
			
		||||
        ((show-entries-val   :show-entries-function)
 | 
			
		||||
         (format-val         :format))
 | 
			
		||||
      `(progn
 | 
			
		||||
         (defcustom ,format-var ,format-val
 | 
			
		||||
           ,(format "\
 | 
			
		||||
| 
						 | 
				
			
			@ -473,9 +477,23 @@ After calling each METHOD, a new line is inserted."
 | 
			
		|||
          '((format . ,format-var))
 | 
			
		||||
          'guix-info-data ',entry-type)
 | 
			
		||||
 | 
			
		||||
         (guix-buffer-define-interface info ,entry-type
 | 
			
		||||
           :mode-init-function 'guix-info-mode-initialize
 | 
			
		||||
           ,@%foreign-args)))))
 | 
			
		||||
         ,(if show-entries-val
 | 
			
		||||
              `(guix-buffer-define-interface info ,entry-type
 | 
			
		||||
                 :show-entries-function ,show-entries-val
 | 
			
		||||
                 ,@%foreign-args)
 | 
			
		||||
 | 
			
		||||
            (let ((insert-fun (intern (concat prefix "-insert-entries"))))
 | 
			
		||||
              `(progn
 | 
			
		||||
                 (defun ,insert-fun (entries)
 | 
			
		||||
                   ,(format "\
 | 
			
		||||
Print '%s' ENTRIES in the current 'info' buffer."
 | 
			
		||||
                            entry-type-str)
 | 
			
		||||
                   (guix-info-insert-entries entries ',entry-type))
 | 
			
		||||
 | 
			
		||||
                 (guix-buffer-define-interface info ,entry-type
 | 
			
		||||
                   :insert-entries-function ',insert-fun
 | 
			
		||||
                   :mode-init-function 'guix-info-mode-initialize
 | 
			
		||||
                   ,@%foreign-args))))))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Displaying packages
 | 
			
		||||
| 
						 | 
				
			
			@ -675,7 +693,7 @@ ENTRY is an alist with package info."
 | 
			
		|||
     type-str
 | 
			
		||||
     (lambda (btn)
 | 
			
		||||
       (guix-process-package-actions
 | 
			
		||||
        guix-profile
 | 
			
		||||
        (guix-ui-current-profile)
 | 
			
		||||
        `((,(button-get btn 'action-type) (,(button-get btn 'id)
 | 
			
		||||
                                           ,(button-get btn 'output))))
 | 
			
		||||
        (current-buffer)))
 | 
			
		||||
| 
						 | 
				
			
			@ -726,15 +744,16 @@ prompt depending on `guix-operation-confirm' variable)."
 | 
			
		|||
Find the file if needed (see `guix-package-info-auto-find-source').
 | 
			
		||||
ENTRY-ID is an ID of the current entry (package or output).
 | 
			
		||||
PACKAGE-ID is an ID of the package which source to show."
 | 
			
		||||
  (let* ((entries guix-entries)
 | 
			
		||||
         (entry   (guix-entry-by-id entry-id guix-entries))
 | 
			
		||||
  (let* ((entries (guix-buffer-current-entries))
 | 
			
		||||
         (entry   (guix-entry-by-id entry-id entries))
 | 
			
		||||
         (file    (guix-package-source-path package-id)))
 | 
			
		||||
    (or file
 | 
			
		||||
        (error "Couldn't define file name of the package source"))
 | 
			
		||||
    (let* ((new-entry (cons (cons 'source-file file)
 | 
			
		||||
                            entry))
 | 
			
		||||
           (new-entries (guix-replace-entry entry-id new-entry entries)))
 | 
			
		||||
      (setq guix-entries new-entries)
 | 
			
		||||
      (setf (guix-buffer-item-entries guix-buffer-item)
 | 
			
		||||
            new-entries)
 | 
			
		||||
      (guix-buffer-redisplay-goto-button)
 | 
			
		||||
      (if (file-exists-p file)
 | 
			
		||||
          (if guix-package-info-auto-find-source
 | 
			
		||||
| 
						 | 
				
			
			@ -872,15 +891,19 @@ This function is used to hide a \"Download\" button if needed."
 | 
			
		|||
  (guix-info-insert-action-button
 | 
			
		||||
   "Packages"
 | 
			
		||||
   (lambda (btn)
 | 
			
		||||
     (guix-get-show-entries guix-profile 'list guix-package-list-type
 | 
			
		||||
                            'generation (button-get btn 'number)))
 | 
			
		||||
     (guix-buffer-get-display-entries
 | 
			
		||||
      'list guix-package-list-type
 | 
			
		||||
      (list (guix-ui-current-profile)
 | 
			
		||||
            'generation (button-get btn 'number))
 | 
			
		||||
      'add))
 | 
			
		||||
   "Show installed packages for this generation"
 | 
			
		||||
   'number number)
 | 
			
		||||
  (guix-info-insert-indent)
 | 
			
		||||
  (guix-info-insert-action-button
 | 
			
		||||
   "Delete"
 | 
			
		||||
   (lambda (btn)
 | 
			
		||||
     (guix-delete-generations guix-profile (list (button-get btn 'number))
 | 
			
		||||
     (guix-delete-generations (guix-ui-current-profile)
 | 
			
		||||
                              (list (button-get btn 'number))
 | 
			
		||||
                              (current-buffer)))
 | 
			
		||||
   "Delete this generation"
 | 
			
		||||
   'number number))
 | 
			
		||||
| 
						 | 
				
			
			@ -894,7 +917,8 @@ This function is used to hide a \"Download\" button if needed."
 | 
			
		|||
    (guix-info-insert-action-button
 | 
			
		||||
     "Switch"
 | 
			
		||||
     (lambda (btn)
 | 
			
		||||
       (guix-switch-to-generation guix-profile (button-get btn 'number)
 | 
			
		||||
       (guix-switch-to-generation (guix-ui-current-profile)
 | 
			
		||||
                                  (button-get btn 'number)
 | 
			
		||||
                                  (current-buffer)))
 | 
			
		||||
     "Switch to this generation (make it the current one)"
 | 
			
		||||
     'number (guix-entry-value entry 'number))))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ With prefix argument, describe entries marked with any mark."
 | 
			
		|||
  (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))
 | 
			
		||||
         (entry-type (guix-buffer-current-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)))
 | 
			
		||||
| 
						 | 
				
			
			@ -168,8 +168,7 @@ Return a vector made of values of FUN calls."
 | 
			
		|||
           rest-spec))))
 | 
			
		||||
 | 
			
		||||
(defun guix-list-insert-entries (entries entry-type)
 | 
			
		||||
  "Display ENTRIES of ENTRY-TYPE in the current list buffer.
 | 
			
		||||
ENTRIES should have a form of `guix-entries'."
 | 
			
		||||
  "Print ENTRY-TYPE ENTRIES in the current buffer."
 | 
			
		||||
  (setq tabulated-list-entries
 | 
			
		||||
        (guix-list-tabulated-entries entries entry-type))
 | 
			
		||||
  (tabulated-list-print))
 | 
			
		||||
| 
						 | 
				
			
			@ -212,14 +211,18 @@ VAL may be nil."
 | 
			
		|||
        'follow-link t
 | 
			
		||||
        'help-echo "Find file"))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; 'List' lines
 | 
			
		||||
 | 
			
		||||
(defun guix-list-current-id ()
 | 
			
		||||
  "Return ID of the current entry."
 | 
			
		||||
  "Return ID of the entry at point."
 | 
			
		||||
  (or (tabulated-list-get-id)
 | 
			
		||||
      (user-error "No entry here")))
 | 
			
		||||
 | 
			
		||||
(defun guix-list-current-entry ()
 | 
			
		||||
  "Return alist of the current entry info."
 | 
			
		||||
  (guix-entry-by-id (guix-list-current-id) guix-entries))
 | 
			
		||||
  "Return entry at point."
 | 
			
		||||
  (guix-entry-by-id (guix-list-current-id)
 | 
			
		||||
                    (guix-buffer-current-entries)))
 | 
			
		||||
 | 
			
		||||
(defun guix-list-for-each-line (fun &rest args)
 | 
			
		||||
  "Call FUN with ARGS for each entry line."
 | 
			
		||||
| 
						 | 
				
			
			@ -429,8 +432,6 @@ The rest keyword arguments are passed to
 | 
			
		|||
  (let* ((entry-type-str     (symbol-name entry-type))
 | 
			
		||||
         (prefix             (concat "guix-" entry-type-str "-list"))
 | 
			
		||||
         (group              (intern prefix))
 | 
			
		||||
         (mode-str           (concat prefix "-mode"))
 | 
			
		||||
         (init-fun           (intern (concat prefix "-mode-initialize")))
 | 
			
		||||
         (describe-var       (intern (concat prefix "-describe-function")))
 | 
			
		||||
         (describe-count-var (intern (concat prefix
 | 
			
		||||
                                             "-describe-warning-count")))
 | 
			
		||||
| 
						 | 
				
			
			@ -438,7 +439,8 @@ The rest keyword arguments are passed to
 | 
			
		|||
         (sort-key-var       (intern (concat prefix "-sort-key")))
 | 
			
		||||
         (marks-var          (intern (concat prefix "-marks"))))
 | 
			
		||||
    (guix-keyword-args-let args
 | 
			
		||||
        ((describe-val       :describe-function)
 | 
			
		||||
        ((show-entries-val   :show-entries-function)
 | 
			
		||||
         (describe-val       :describe-function)
 | 
			
		||||
         (describe-count-val :describe-count 10)
 | 
			
		||||
         (format-val         :format)
 | 
			
		||||
         (sort-key-val       :sort-key)
 | 
			
		||||
| 
						 | 
				
			
			@ -498,10 +500,6 @@ See also `guix-list-describe'."
 | 
			
		|||
           ,(format "Function used to describe '%s' entries."
 | 
			
		||||
                    entry-type-str))
 | 
			
		||||
 | 
			
		||||
         (defun ,init-fun ()
 | 
			
		||||
           ,(concat "Initial settings for `" mode-str "'.")
 | 
			
		||||
           (guix-list-mode-initialize ',entry-type))
 | 
			
		||||
 | 
			
		||||
         (guix-alist-put!
 | 
			
		||||
          '((describe       . ,describe-var)
 | 
			
		||||
            (describe-count . ,describe-count-var)
 | 
			
		||||
| 
						 | 
				
			
			@ -510,8 +508,30 @@ See also `guix-list-describe'."
 | 
			
		|||
            (marks          . ,marks-var))
 | 
			
		||||
          'guix-list-data ',entry-type)
 | 
			
		||||
 | 
			
		||||
         (guix-buffer-define-interface list ,entry-type
 | 
			
		||||
           ,@%foreign-args)))))
 | 
			
		||||
         ,(if show-entries-val
 | 
			
		||||
              `(guix-buffer-define-interface list ,entry-type
 | 
			
		||||
                 :show-entries-function ,show-entries-val
 | 
			
		||||
                 ,@%foreign-args)
 | 
			
		||||
 | 
			
		||||
            (let ((insert-fun    (intern (concat prefix "-insert-entries")))
 | 
			
		||||
                  (mode-init-fun (intern (concat prefix "-mode-initialize"))))
 | 
			
		||||
              `(progn
 | 
			
		||||
                 (defun ,insert-fun (entries)
 | 
			
		||||
                   ,(format "\
 | 
			
		||||
Print '%s' ENTRIES in the current 'list' buffer."
 | 
			
		||||
                            entry-type-str)
 | 
			
		||||
                   (guix-list-insert-entries entries ',entry-type))
 | 
			
		||||
 | 
			
		||||
                 (defun ,mode-init-fun ()
 | 
			
		||||
                   ,(format "\
 | 
			
		||||
Set up the current 'list' buffer for displaying '%s' entries."
 | 
			
		||||
                            entry-type-str)
 | 
			
		||||
                   (guix-list-mode-initialize ',entry-type))
 | 
			
		||||
 | 
			
		||||
                 (guix-buffer-define-interface list ,entry-type
 | 
			
		||||
                   :insert-entries-function ',insert-fun
 | 
			
		||||
                   :mode-init-function ',mode-init-fun
 | 
			
		||||
                   ,@%foreign-args))))))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Displaying packages
 | 
			
		||||
| 
						 | 
				
			
			@ -584,7 +604,7 @@ Colorize it with `guix-package-list-installed' or
 | 
			
		|||
  (when (and (not guix-package-list-generation-marking-enabled)
 | 
			
		||||
             (or (derived-mode-p 'guix-package-list-mode)
 | 
			
		||||
                 (derived-mode-p 'guix-output-list-mode))
 | 
			
		||||
             (eq guix-search-type 'generation))
 | 
			
		||||
             (eq (guix-ui-current-search-type) 'generation))
 | 
			
		||||
    (error "Action marks are disabled for lists of 'generation packages'")))
 | 
			
		||||
 | 
			
		||||
(defun guix-package-list-mark-outputs (mark default
 | 
			
		||||
| 
						 | 
				
			
			@ -655,7 +675,7 @@ accept an entry as argument."
 | 
			
		|||
  (let ((obsolete (cl-remove-if-not
 | 
			
		||||
                   (lambda (entry)
 | 
			
		||||
                     (guix-entry-value entry 'obsolete))
 | 
			
		||||
                   guix-entries)))
 | 
			
		||||
                   (guix-buffer-current-entries))))
 | 
			
		||||
    (guix-list-for-each-line
 | 
			
		||||
     (lambda ()
 | 
			
		||||
       (let* ((id (guix-list-current-id))
 | 
			
		||||
| 
						 | 
				
			
			@ -682,8 +702,8 @@ FUN should accept action-type as argument."
 | 
			
		|||
  (let ((actions (delq nil
 | 
			
		||||
                       (mapcar fun '(install delete upgrade)))))
 | 
			
		||||
    (if actions
 | 
			
		||||
        (guix-process-package-actions
 | 
			
		||||
         guix-profile actions (current-buffer))
 | 
			
		||||
        (guix-process-package-actions (guix-ui-current-profile)
 | 
			
		||||
                                      actions (current-buffer))
 | 
			
		||||
      (user-error "No operations specified"))))
 | 
			
		||||
 | 
			
		||||
(defun guix-package-list-execute ()
 | 
			
		||||
| 
						 | 
				
			
			@ -714,7 +734,7 @@ The specification is suitable for `guix-process-package-actions'."
 | 
			
		|||
            (output nil 9 t)
 | 
			
		||||
            (installed nil 12 t)
 | 
			
		||||
            (synopsis guix-list-get-one-line 30 nil))
 | 
			
		||||
  :required '(package-id)
 | 
			
		||||
  :required '(id package-id)
 | 
			
		||||
  :sort-key '(name)
 | 
			
		||||
  :marks '((install . ?I)
 | 
			
		||||
           (upgrade . ?U)
 | 
			
		||||
| 
						 | 
				
			
			@ -784,15 +804,19 @@ The specification is suitable for `guix-process-output-actions'."
 | 
			
		|||
  "Describe outputs with IDS (list of output identifiers).
 | 
			
		||||
See `guix-package-info-type'."
 | 
			
		||||
  (if (eq guix-package-info-type 'output)
 | 
			
		||||
      (apply #'guix-get-show-entries
 | 
			
		||||
             guix-profile 'info 'output 'id ids)
 | 
			
		||||
      (guix-buffer-get-display-entries
 | 
			
		||||
       'info 'output
 | 
			
		||||
       (cl-list* (guix-ui-current-profile) 'id ids)
 | 
			
		||||
       'add)
 | 
			
		||||
    (let ((pids (mapcar (lambda (oid)
 | 
			
		||||
                          (car (guix-package-id-and-output-by-output-id
 | 
			
		||||
                                oid)))
 | 
			
		||||
                        ids)))
 | 
			
		||||
      (apply #'guix-get-show-entries
 | 
			
		||||
             guix-profile 'info 'package 'id
 | 
			
		||||
             (cl-remove-duplicates pids)))))
 | 
			
		||||
      (guix-buffer-get-display-entries
 | 
			
		||||
       'info 'package
 | 
			
		||||
       (cl-list* (guix-ui-current-profile)
 | 
			
		||||
                 'id (cl-remove-duplicates pids))
 | 
			
		||||
       'add))))
 | 
			
		||||
 | 
			
		||||
(defun guix-output-list-edit ()
 | 
			
		||||
  "Go to the location of the current package."
 | 
			
		||||
| 
						 | 
				
			
			@ -837,13 +861,15 @@ VAL is a boolean value."
 | 
			
		|||
         (number  (guix-entry-value entry 'number)))
 | 
			
		||||
    (if current
 | 
			
		||||
        (user-error "This generation is already the current one")
 | 
			
		||||
      (guix-switch-to-generation guix-profile number (current-buffer)))))
 | 
			
		||||
      (guix-switch-to-generation (guix-ui-current-profile)
 | 
			
		||||
                                 number (current-buffer)))))
 | 
			
		||||
 | 
			
		||||
(defun guix-generation-list-show-packages ()
 | 
			
		||||
  "List installed packages for the generation at point."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (guix-get-show-entries guix-profile 'list guix-package-list-type
 | 
			
		||||
                         'generation (guix-list-current-id)))
 | 
			
		||||
  (guix-get-show-packages
 | 
			
		||||
   (guix-ui-current-profile)
 | 
			
		||||
   'generation (guix-list-current-id)))
 | 
			
		||||
 | 
			
		||||
(defun guix-generation-list-generations-to-compare ()
 | 
			
		||||
  "Return a sorted list of 2 marked generations for comparing."
 | 
			
		||||
| 
						 | 
				
			
			@ -858,9 +884,12 @@ If 2 generations are marked with \\[guix-list-mark], display
 | 
			
		|||
outputs installed in the latest marked generation that were not
 | 
			
		||||
installed in the other one."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (apply #'guix-get-show-entries
 | 
			
		||||
         guix-profile 'list 'output 'generation-diff
 | 
			
		||||
         (reverse (guix-generation-list-generations-to-compare))))
 | 
			
		||||
  (guix-buffer-get-display-entries
 | 
			
		||||
   'list 'output
 | 
			
		||||
   (cl-list* (guix-ui-current-profile)
 | 
			
		||||
             'generation-diff
 | 
			
		||||
             (reverse (guix-generation-list-generations-to-compare)))
 | 
			
		||||
   'add))
 | 
			
		||||
 | 
			
		||||
(defun guix-generation-list-show-removed-packages ()
 | 
			
		||||
  "List package outputs removed from the latest marked generation.
 | 
			
		||||
| 
						 | 
				
			
			@ -868,9 +897,12 @@ If 2 generations are marked with \\[guix-list-mark], display
 | 
			
		|||
outputs not installed in the latest marked generation that were
 | 
			
		||||
installed in the other one."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (apply #'guix-get-show-entries
 | 
			
		||||
         guix-profile 'list 'output 'generation-diff
 | 
			
		||||
         (guix-generation-list-generations-to-compare)))
 | 
			
		||||
  (guix-buffer-get-display-entries
 | 
			
		||||
   'list 'output
 | 
			
		||||
   (cl-list* (guix-ui-current-profile)
 | 
			
		||||
             'generation-diff
 | 
			
		||||
             (guix-generation-list-generations-to-compare))
 | 
			
		||||
   'add))
 | 
			
		||||
 | 
			
		||||
(defun guix-generation-list-compare (diff-fun gen-fun)
 | 
			
		||||
  "Run GEN-FUN on the 2 marked generations and run DIFF-FUN on the results."
 | 
			
		||||
| 
						 | 
				
			
			@ -938,7 +970,8 @@ With ARG, mark all generations for deletion."
 | 
			
		|||
  (let ((marked (guix-list-get-marked-id-list 'delete)))
 | 
			
		||||
    (or marked
 | 
			
		||||
        (user-error "No generations marked for deletion"))
 | 
			
		||||
    (guix-delete-generations guix-profile marked (current-buffer))))
 | 
			
		||||
    (guix-delete-generations (guix-ui-current-profile)
 | 
			
		||||
                             marked (current-buffer))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
(defvar guix-list-font-lock-keywords
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,10 @@
 | 
			
		|||
 | 
			
		||||
(require 'cl-lib)
 | 
			
		||||
(require 'guix-backend)
 | 
			
		||||
(require 'guix-buffer)
 | 
			
		||||
(require 'guix-guile)
 | 
			
		||||
(require 'guix-utils)
 | 
			
		||||
(require 'guix-messages)
 | 
			
		||||
 | 
			
		||||
(defgroup guix-ui nil
 | 
			
		||||
  "Settings for Guix package management.
 | 
			
		||||
| 
						 | 
				
			
			@ -41,10 +44,38 @@ generations in 'list' and 'info' buffers."
 | 
			
		|||
    map)
 | 
			
		||||
  "Parent keymap for Guix package/generation buffers.")
 | 
			
		||||
 | 
			
		||||
(guix-buffer-define-current-args-accessors
 | 
			
		||||
 "guix-ui-current" "profile" "search-type" "search-values")
 | 
			
		||||
 | 
			
		||||
(defun guix-ui-get-entries (profile entry-type search-type search-values
 | 
			
		||||
                                    &optional params)
 | 
			
		||||
  "Receive ENTRY-TYPE entries for PROFILE.
 | 
			
		||||
Call an appropriate scheme procedure and return a list of entries.
 | 
			
		||||
 | 
			
		||||
ENTRY-TYPE should be one of the following symbols: `package',
 | 
			
		||||
`output' or `generation'.
 | 
			
		||||
 | 
			
		||||
SEARCH-TYPE may be one of the following symbols:
 | 
			
		||||
 | 
			
		||||
- If ENTRY-TYPE is `package' or `output': `id', `name', `regexp',
 | 
			
		||||
  `all-available', `newest-available', `installed', `obsolete',
 | 
			
		||||
  `generation'.
 | 
			
		||||
 | 
			
		||||
- If ENTRY-TYPE is `generation': `id', `last', `all', `time'.
 | 
			
		||||
 | 
			
		||||
PARAMS is a list of parameters for receiving.  If nil, get data
 | 
			
		||||
with all available parameters."
 | 
			
		||||
  (guix-eval-read
 | 
			
		||||
   (guix-make-guile-expression
 | 
			
		||||
    'entries
 | 
			
		||||
    profile params entry-type search-type search-values)))
 | 
			
		||||
 | 
			
		||||
(defun guix-ui-list-describe (ids)
 | 
			
		||||
  "Describe 'ui' entries with IDS (list of identifiers)."
 | 
			
		||||
  (apply #'guix-get-show-entries
 | 
			
		||||
         guix-profile 'info guix-entry-type 'id ids))
 | 
			
		||||
  (guix-buffer-get-display-entries
 | 
			
		||||
   'info (guix-buffer-current-entry-type)
 | 
			
		||||
   (cl-list* (guix-ui-current-profile) 'id ids)
 | 
			
		||||
   'add))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;; Buffers and auto updating
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +192,16 @@ Optional keywords:
 | 
			
		|||
    `guix-TYPE-required-params' variable.
 | 
			
		||||
 | 
			
		||||
The rest keyword arguments are passed to
 | 
			
		||||
`guix-BUFFER-TYPE-define-interface' macro."
 | 
			
		||||
`guix-BUFFER-TYPE-define-interface' macro.
 | 
			
		||||
 | 
			
		||||
Along with the mentioned definitions, this macro also defines:
 | 
			
		||||
 | 
			
		||||
  - `guix-TYPE-mode-map' - keymap based on `guix-ui-map' and
 | 
			
		||||
    `guix-BUFFER-TYPE-mode-map'.
 | 
			
		||||
 | 
			
		||||
  - `guix-TYPE-get-entries' - a wrapper around `guix-ui-get-entries'.
 | 
			
		||||
 | 
			
		||||
  - `guix-TYPE-message' - a wrapper around `guix-result-message'."
 | 
			
		||||
  (declare (indent 2))
 | 
			
		||||
  (let* ((entry-type-str  (symbol-name entry-type))
 | 
			
		||||
         (buffer-type-str (symbol-name buffer-type))
 | 
			
		||||
| 
						 | 
				
			
			@ -173,6 +213,10 @@ The rest keyword arguments are passed to
 | 
			
		|||
                                          buffer-type-str)))
 | 
			
		||||
         (required-var    (intern (concat prefix "-required-params")))
 | 
			
		||||
         (buffer-name-fun (intern (concat prefix "-buffer-name")))
 | 
			
		||||
         (get-fun         (intern (concat prefix "-get-entries")))
 | 
			
		||||
         (message-fun     (intern (concat prefix "-message")))
 | 
			
		||||
         (displayed-fun   (intern (format "guix-%s-displayed-params"
 | 
			
		||||
                                          buffer-type-str)))
 | 
			
		||||
         (definer         (intern (format "guix-%s-define-interface"
 | 
			
		||||
                                          buffer-type-str))))
 | 
			
		||||
    (guix-keyword-args-let args
 | 
			
		||||
| 
						 | 
				
			
			@ -188,9 +232,13 @@ The rest keyword arguments are passed to
 | 
			
		|||
 | 
			
		||||
         (defvar ,required-var ,required-val
 | 
			
		||||
           ,(format "\
 | 
			
		||||
List of the required '%s' parameters for '%s' buffer.
 | 
			
		||||
These parameters are received along with the displayed parameters."
 | 
			
		||||
                    entry-type-str buffer-type-str))
 | 
			
		||||
List of the required '%s' parameters.
 | 
			
		||||
These parameters are received by `%S'
 | 
			
		||||
along with the displayed parameters.
 | 
			
		||||
 | 
			
		||||
Do not remove `id' from this list as it is required for
 | 
			
		||||
identifying an entry."
 | 
			
		||||
                    entry-type-str get-fun))
 | 
			
		||||
 | 
			
		||||
         (defun ,buffer-name-fun (profile &rest _)
 | 
			
		||||
           ,(format "\
 | 
			
		||||
| 
						 | 
				
			
			@ -199,7 +247,27 @@ See `guix-ui-buffer-name' for details."
 | 
			
		|||
                    buffer-type-str entry-type-str)
 | 
			
		||||
           (guix-ui-buffer-name ,buffer-name-val profile))
 | 
			
		||||
 | 
			
		||||
         (defun ,get-fun (profile search-type &rest search-values)
 | 
			
		||||
           ,(format "\
 | 
			
		||||
Receive '%s' entries for displaying them in '%s' buffer.
 | 
			
		||||
See `guix-ui-get-entries' for details."
 | 
			
		||||
                    entry-type-str buffer-type-str)
 | 
			
		||||
           (guix-ui-get-entries
 | 
			
		||||
            profile ',entry-type search-type search-values
 | 
			
		||||
            (cl-union ,required-var
 | 
			
		||||
                      (,displayed-fun ',entry-type))))
 | 
			
		||||
 | 
			
		||||
         (defun ,message-fun (entries profile search-type
 | 
			
		||||
                                      &rest search-values)
 | 
			
		||||
           ,(format "\
 | 
			
		||||
Display a message after showing '%s' entries."
 | 
			
		||||
                    entry-type-str)
 | 
			
		||||
           (guix-result-message
 | 
			
		||||
            profile entries ',entry-type search-type search-values))
 | 
			
		||||
 | 
			
		||||
         (,definer ,entry-type
 | 
			
		||||
           :get-entries-function ',get-fun
 | 
			
		||||
           :message-function ',message-fun
 | 
			
		||||
           :buffer-name ',buffer-name-fun
 | 
			
		||||
           ,@%foreign-args)))))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,42 +56,39 @@ If nil, show a single package in the info buffer."
 | 
			
		|||
(defvar guix-search-history nil
 | 
			
		||||
  "A history of minibuffer prompts.")
 | 
			
		||||
 | 
			
		||||
(defun guix-get-show-packages (profile search-type &rest search-vals)
 | 
			
		||||
(defun guix-get-show-packages (profile search-type &rest search-values)
 | 
			
		||||
  "Search for packages and show results.
 | 
			
		||||
 | 
			
		||||
If PROFILE is nil, use `guix-current-profile'.
 | 
			
		||||
 | 
			
		||||
See `guix-get-entries' for the meaning of SEARCH-TYPE and
 | 
			
		||||
SEARCH-VALS.
 | 
			
		||||
See `guix-ui-get-entries' for the meaning of SEARCH-TYPE and
 | 
			
		||||
SEARCH-VALUES.
 | 
			
		||||
 | 
			
		||||
Results are displayed in the list buffer, unless a single package
 | 
			
		||||
is found and `guix-list-single-package' is nil."
 | 
			
		||||
  (or profile (setq profile guix-current-profile))
 | 
			
		||||
  (let ((packages (guix-get-entries profile guix-package-list-type
 | 
			
		||||
                                    search-type search-vals
 | 
			
		||||
                                    (guix-get-params-for-receiving
 | 
			
		||||
                                     'list guix-package-list-type))))
 | 
			
		||||
  (let* ((args    (cl-list* (or profile guix-current-profile)
 | 
			
		||||
                            search-type search-values))
 | 
			
		||||
         (entries (guix-buffer-get-entries
 | 
			
		||||
                   'list guix-package-list-type args)))
 | 
			
		||||
    (if (or guix-list-single-package
 | 
			
		||||
            (cdr packages))
 | 
			
		||||
        (guix-set-buffer profile packages 'list guix-package-list-type
 | 
			
		||||
                         search-type search-vals)
 | 
			
		||||
      (let ((packages (guix-get-entries profile guix-package-info-type
 | 
			
		||||
                                        search-type search-vals
 | 
			
		||||
                                        (guix-get-params-for-receiving
 | 
			
		||||
                                         'info guix-package-info-type))))
 | 
			
		||||
        (guix-set-buffer profile packages 'info guix-package-info-type
 | 
			
		||||
                         search-type search-vals)))))
 | 
			
		||||
            (null entries)
 | 
			
		||||
            (cdr entries))
 | 
			
		||||
        (guix-buffer-display-entries
 | 
			
		||||
         entries 'list guix-package-list-type args 'add)
 | 
			
		||||
      (guix-buffer-get-display-entries
 | 
			
		||||
       'info guix-package-info-type args 'add))))
 | 
			
		||||
 | 
			
		||||
(defun guix-get-show-generations (profile search-type &rest search-vals)
 | 
			
		||||
(defun guix-get-show-generations (profile search-type &rest search-values)
 | 
			
		||||
  "Search for generations and show results.
 | 
			
		||||
 | 
			
		||||
If PROFILE is nil, use `guix-current-profile'.
 | 
			
		||||
 | 
			
		||||
See `guix-get-entries' for the meaning of SEARCH-TYPE and
 | 
			
		||||
SEARCH-VALS."
 | 
			
		||||
  (apply #'guix-get-show-entries
 | 
			
		||||
         (or profile guix-current-profile)
 | 
			
		||||
         'list 'generation search-type search-vals))
 | 
			
		||||
See `guix-ui-get-entries' for the meaning of SEARCH-TYPE and
 | 
			
		||||
SEARCH-VALUES."
 | 
			
		||||
  (let ((args (cl-list* (or profile guix-current-profile)
 | 
			
		||||
                        search-type search-values)))
 | 
			
		||||
    (guix-buffer-get-display-entries
 | 
			
		||||
     'list 'generation args 'add)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun guix-search-by-name (name &optional profile)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Reference in a new issue