summaryrefslogtreecommitdiff
path: root/emacs/guix-list.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs/guix-list.el')
-rw-r--r--emacs/guix-list.el585
1 files changed, 0 insertions, 585 deletions
diff --git a/emacs/guix-list.el b/emacs/guix-list.el
deleted file mode 100644
index c91c67cb29..0000000000
--- a/emacs/guix-list.el
+++ /dev/null
@@ -1,585 +0,0 @@
-;;; guix-list.el --- 'List' 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 'list' buffer interface for displaying an arbitrary
-;; data.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'tabulated-list)
-(require 'guix-buffer)
-(require 'guix-info)
-(require 'guix-entry)
-(require 'guix-utils)
-
-(guix-define-buffer-type list)
-
-(defface guix-list-file-name
- '((t :inherit guix-info-file-name))
- "Face used for file names."
- :group 'guix-list-faces)
-
-(defface guix-list-url
- '((t :inherit guix-info-url))
- "Face used for URLs."
- :group 'guix-list-faces)
-
-(defface guix-list-time
- '((t :inherit guix-info-time))
- "Face used for time stamps."
- :group 'guix-list-faces)
-
-(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-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)))
- (guix-list-describe-entries entry-type ids))))
-
-
-;;; Wrappers for 'list' variables
-
-(defvar guix-list-data nil
- "Alist with 'list' data.
-This alist is filled by `guix-list-define-interface' macro.")
-
-(defun guix-list-value (entry-type symbol)
- "Return SYMBOL's value for ENTRY-TYPE from `guix-list-data'."
- (symbol-value (guix-assq-value guix-list-data entry-type symbol)))
-
-(defun guix-list-param-title (entry-type param)
- "Return column title of an ENTRY-TYPE parameter PARAM."
- (guix-buffer-param-title 'list entry-type param))
-
-(defun guix-list-format (entry-type)
- "Return column format for ENTRY-TYPE."
- (guix-list-value entry-type 'format))
-
-(defun guix-list-displayed-params (entry-type)
- "Return a list of ENTRY-TYPE parameters that should be displayed."
- (mapcar #'car (guix-list-format entry-type)))
-
-(defun guix-list-sort-key (entry-type)
- "Return sort key for ENTRY-TYPE."
- (guix-list-value entry-type 'sort-key))
-
-(defun guix-list-additional-marks (entry-type)
- "Return alist of additional marks for ENTRY-TYPE."
- (guix-list-value entry-type 'marks))
-
-(defun guix-list-single-entry? (entry-type)
- "Return non-nil, if a single entry of ENTRY-TYPE should be listed."
- (guix-list-value entry-type 'list-single))
-
-(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
-
-(defun guix-list-sort-numerically (column a b)
- "Compare COLUMN of tabulated entries A and B numerically.
-This function is used for sort predicates for `tabulated-list-format'.
-Return non-nil, if B is bigger than A."
- (cl-flet ((num (entry)
- (string-to-number (aref (cadr entry) column))))
- (> (num b) (num a))))
-
-(defmacro guix-list-define-numerical-sorter (column)
- "Define numerical sort predicate for COLUMN.
-See `guix-list-sort-numerically' for details."
- (let ((name (intern (format "guix-list-sort-numerically-%d" column)))
- (doc (format "\
-Predicate to sort tabulated list by column %d numerically.
-See `guix-list-sort-numerically' for details."
- column)))
- `(defun ,name (a b)
- ,doc
- (guix-list-sort-numerically ,column a b))))
-
-(defmacro guix-list-define-numerical-sorters (n)
- "Define numerical sort predicates for columns from 0 to N.
-See `guix-list-define-numerical-sorter' for details."
- `(progn
- ,@(mapcar (lambda (i)
- `(guix-list-define-numerical-sorter ,i))
- (number-sequence 0 n))))
-
-(guix-list-define-numerical-sorters 9)
-
-(defun guix-list-tabulated-sort-key (entry-type)
- "Return ENTRY-TYPE sort key for `tabulated-list-sort-key'."
- (let ((sort-key (guix-list-sort-key entry-type)))
- (and sort-key
- (cons (guix-list-param-title entry-type (car sort-key))
- (cdr sort-key)))))
-
-(defun guix-list-tabulated-vector (entry-type fun)
- "Call FUN on each column specification for ENTRY-TYPE.
-
-FUN is applied to column specification as arguments (see
-`guix-list-format').
-
-Return a vector made of values of FUN calls."
- (apply #'vector
- (mapcar (lambda (col-spec)
- (apply fun col-spec))
- (guix-list-format entry-type))))
-
-(defun guix-list-tabulated-format (entry-type)
- "Return ENTRY-TYPE list specification for `tabulated-list-format'."
- (guix-list-tabulated-vector
- entry-type
- (lambda (param _ &rest rest-spec)
- (cons (guix-list-param-title entry-type param)
- rest-spec))))
-
-(defun guix-list-tabulated-entries (entries entry-type)
- "Return a list of ENTRY-TYPE values for `tabulated-list-entries'."
- (mapcar (lambda (entry)
- (list (guix-entry-id entry)
- (guix-list-tabulated-entry entry entry-type)))
- entries))
-
-(defun guix-list-tabulated-entry (entry entry-type)
- "Return array of values for `tabulated-list-entries'.
-Parameters are taken from ENTRY-TYPE ENTRY."
- (guix-list-tabulated-vector
- entry-type
- (lambda (param fun &rest _)
- (let ((val (guix-entry-value entry param)))
- (if fun
- (funcall fun val entry)
- (guix-get-string val))))))
-
-
-;;; Displaying entries
-
-(defun guix-list-get-display-entries (entry-type &rest args)
- "Search for entries and show them in a 'list' buffer preferably."
- (let ((entries (guix-buffer-get-entries 'list entry-type args)))
- (if (or (null entries) ; = 0
- (cdr entries) ; > 1
- (guix-list-single-entry? entry-type)
- (null (guix-buffer-value 'info entry-type 'show-entries)))
- (guix-buffer-display-entries entries 'list entry-type args 'add)
- (if (equal (guix-buffer-value 'info entry-type 'get-entries)
- (guix-buffer-value 'list entry-type 'get-entries))
- (guix-buffer-display-entries entries 'info entry-type args 'add)
- (guix-buffer-get-display-entries 'info entry-type args 'add)))))
-
-(defun guix-list-insert-entries (entries entry-type)
- "Print ENTRY-TYPE ENTRIES in the current buffer."
- (setq tabulated-list-entries
- (guix-list-tabulated-entries entries entry-type))
- (tabulated-list-print))
-
-(defun guix-list-get-one-line (val &optional _)
- "Return one-line string from a multi-line string VAL.
-VAL may be nil."
- (if val
- (guix-get-one-line val)
- (guix-get-string nil)))
-
-(defun guix-list-get-time (seconds &optional _)
- "Return formatted time string from SECONDS."
- (guix-get-string (guix-get-time-string seconds)
- 'guix-list-time))
-
-(defun guix-list-get-file-name (file-name &optional _)
- "Return FILE-NAME button specification for `tabulated-list-entries'."
- (list file-name
- 'face 'guix-list-file-name
- 'action (lambda (btn) (find-file (button-label btn)))
- 'follow-link t
- 'help-echo "Find file"))
-
-(defun guix-list-get-url (url &optional _)
- "Return URL button specification for `tabulated-list-entries'."
- (list url
- 'face 'guix-list-url
- 'action (lambda (btn) (browse-url (button-label btn)))
- 'follow-link t
- 'help-echo "Browse URL"))
-
-
-;;; 'List' lines
-
-(defun guix-list-current-id ()
- "Return ID of the entry at point."
- (or (tabulated-list-get-id)
- (user-error "No entry here")))
-
-(defun guix-list-current-entry ()
- "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."
- (or (derived-mode-p 'guix-list-mode)
- (error "The current buffer is not in Guix List mode"))
- (save-excursion
- (goto-char (point-min))
- (while (not (eobp))
- (apply fun args)
- (forward-line))))
-
-(defun guix-list-fold-lines (fun init)
- "Fold over entry lines in the current list buffer.
-Call FUN with RESULT as argument for each line, using INIT as
-the initial value of RESULT. Return the final result."
- (let ((res init))
- (guix-list-for-each-line
- (lambda () (setq res (funcall fun res))))
- res))
-
-
-;;; Marking and sorting
-
-(defvar-local guix-list-marked nil
- "List of the marked entries.
-Each element of the list has a form:
-
- (ID MARK-NAME . ARGS)
-
-ID is an entry ID.
-MARK-NAME is a symbol from `guix-list-marks'.
-ARGS is a list of additional values.")
-
-(defvar-local guix-list-marks nil
- "Alist of available mark names and mark characters.")
-
-(defvar guix-list-default-marks
- '((empty . ?\s)
- (general . ?*))
- "Alist of default mark names and mark characters.")
-
-(defun guix-list-marks (entry-type)
- "Return alist of available marks for ENTRY-TYPE."
- (append guix-list-default-marks
- (guix-list-additional-marks entry-type)))
-
-(defun guix-list-get-mark (name)
- "Return mark character by its NAME."
- (or (guix-assq-value guix-list-marks name)
- (error "Mark '%S' not found" name)))
-
-(defun guix-list-get-mark-string (name)
- "Return mark string by its NAME."
- (string (guix-list-get-mark name)))
-
-(defun guix-list-current-mark ()
- "Return mark character of the current line."
- (char-after (line-beginning-position)))
-
-(defun guix-list-get-marked (&rest mark-names)
- "Return list of specs of entries marked with any mark from MARK-NAMES.
-Entry specs are elements from `guix-list-marked' list.
-If MARK-NAMES are not specified, use all marks from
-`guix-list-marks' except the `empty' one."
- (or mark-names
- (setq mark-names
- (delq 'empty
- (mapcar #'car guix-list-marks))))
- (cl-remove-if-not (lambda (assoc)
- (memq (cadr assoc) mark-names))
- guix-list-marked))
-
-(defun guix-list-get-marked-args (mark-name)
- "Return list of (ID . ARGS) elements from lines marked with MARK-NAME.
-See `guix-list-marked' for the meaning of ARGS."
- (mapcar (lambda (spec)
- (let ((id (car spec))
- (args (cddr spec)))
- (cons id args)))
- (guix-list-get-marked mark-name)))
-
-(defun guix-list-get-marked-id-list (&rest mark-names)
- "Return list of IDs of entries marked with any mark from MARK-NAMES.
-See `guix-list-get-marked' for details."
- (mapcar #'car (apply #'guix-list-get-marked mark-names)))
-
-(defun guix-list--mark (mark-name &optional advance &rest args)
- "Put a mark on the current line.
-Also add the current entry to `guix-list-marked' using its ID and ARGS.
-MARK-NAME is a symbol from `guix-list-marks'.
-If ADVANCE is non-nil, move forward by one line after marking."
- (let ((id (guix-list-current-id)))
- (if (eq mark-name 'empty)
- (setq guix-list-marked (assq-delete-all id guix-list-marked))
- (let ((assoc (assq id guix-list-marked))
- (val (cons mark-name args)))
- (if assoc
- (setcdr assoc val)
- (push (cons id val) guix-list-marked)))))
- (tabulated-list-put-tag (guix-list-get-mark-string mark-name)
- advance))
-
-(defun guix-list-mark (&optional arg)
- "Mark the current line and move to the next line.
-With ARG, mark all lines."
- (interactive "P")
- (if arg
- (guix-list-mark-all)
- (guix-list--mark 'general t)))
-
-(defun guix-list-mark-all (&optional mark-name)
- "Mark all lines with MARK-NAME mark.
-MARK-NAME is a symbol from `guix-list-marks'.
-Interactively, put a general mark on all lines."
- (interactive)
- (or mark-name (setq mark-name 'general))
- (guix-list-for-each-line #'guix-list--mark mark-name))
-
-(defun guix-list-unmark (&optional arg)
- "Unmark the current line and move to the next line.
-With ARG, unmark all lines."
- (interactive "P")
- (if arg
- (guix-list-unmark-all)
- (guix-list--mark 'empty t)))
-
-(defun guix-list-unmark-backward ()
- "Move up one line and unmark it."
- (interactive)
- (forward-line -1)
- (guix-list--mark 'empty))
-
-(defun guix-list-unmark-all ()
- "Unmark all lines."
- (interactive)
- (guix-list-mark-all 'empty))
-
-(defun guix-list-restore-marks ()
- "Put marks according to `guix-list-marked'."
- (guix-list-for-each-line
- (lambda ()
- (let ((mark-name (car (guix-assq-value guix-list-marked
- (guix-list-current-id)))))
- (tabulated-list-put-tag
- (guix-list-get-mark-string (or mark-name 'empty)))))))
-
-(defun guix-list-sort (&optional n)
- "Sort guix list entries by the column at point.
-With a numeric prefix argument N, sort the Nth column.
-Same as `tabulated-list-sort', but also restore marks after sorting."
- (interactive "P")
- (tabulated-list-sort n)
- (guix-list-restore-marks))
-
-
-;;; Major mode and interface definer
-
-(defvar guix-list-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent
- map (make-composed-keymap guix-buffer-map
- tabulated-list-mode-map))
- (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 "*") 'guix-list-mark)
- (define-key map (kbd "u") 'guix-list-unmark)
- (define-key map (kbd "DEL") 'guix-list-unmark-backward)
- (define-key map [remap tabulated-list-sort] 'guix-list-sort)
- map)
- "Keymap for `guix-list-mode' buffers.")
-
-(define-derived-mode guix-list-mode tabulated-list-mode "Guix-List"
- "Parent mode for displaying data in 'list' form.")
-
-(defun guix-list-mode-initialize (entry-type)
- "Set up the current 'list' buffer for displaying ENTRY-TYPE entries."
- (setq tabulated-list-padding 2
- tabulated-list-format (guix-list-tabulated-format entry-type)
- tabulated-list-sort-key (guix-list-tabulated-sort-key entry-type))
- (setq-local guix-list-marks (guix-list-marks entry-type))
- (tabulated-list-init-header))
-
-(defmacro guix-list-define-interface (entry-type &rest args)
- "Define 'list' interface for displaying ENTRY-TYPE entries.
-Remaining arguments (ARGS) should have a form [KEYWORD VALUE] ...
-
-Required keywords:
-
- - `:format' - default value of the generated
- `guix-ENTRY-TYPE-list-format' variable.
-
-Optional keywords:
-
- - `:sort-key' - default value of the generated
- `guix-ENTRY-TYPE-list-sort-key' variable.
-
- - `:describe-function' - default value of the generated
- `guix-ENTRY-TYPE-describe-function' variable.
-
- - `:list-single?' - default value of the generated
- `guix-ENTRY-TYPE-list-single' variable.
-
- - `:marks' - default value of the generated
- `guix-ENTRY-TYPE-list-marks' variable.
-
-The rest keyword arguments are passed to
-`guix-buffer-define-interface' macro."
- (declare (indent 1))
- (let* ((entry-type-str (symbol-name entry-type))
- (prefix (concat "guix-" entry-type-str "-list"))
- (group (intern prefix))
- (describe-var (intern (concat prefix "-describe-function")))
- (describe-count-var (intern (concat prefix
- "-describe-warning-count")))
- (format-var (intern (concat prefix "-format")))
- (sort-key-var (intern (concat prefix "-sort-key")))
- (list-single-var (intern (concat prefix "-single")))
- (marks-var (intern (concat prefix "-marks"))))
- (guix-keyword-args-let args
- ((show-entries-val :show-entries-function)
- (describe-val :describe-function)
- (describe-count-val :describe-count 10)
- (format-val :format)
- (sort-key-val :sort-key)
- (list-single-val :list-single?)
- (marks-val :marks))
- `(progn
- (defcustom ,format-var ,format-val
- ,(format "\
-List of format values of the displayed columns.
-Each element of the list has a form:
-
- (PARAM VALUE-FUN WIDTH SORT . PROPS)
-
-PARAM is a name of '%s' entry parameter.
-
-VALUE-FUN may be either nil or a function returning a value that
-will be inserted. The function is called with 2 arguments: the
-first one is the value of the parameter; the second one is an
-entry (alist of parameter names and values).
-
-For the meaning of WIDTH, SORT and PROPS, see
-`tabulated-list-format'."
- entry-type-str)
- :type 'sexp
- :group ',group)
-
- (defcustom ,sort-key-var ,sort-key-val
- ,(format "\
-Default sort key for 'list' buffer with '%s' entries.
-Should be nil (no sort) or have a form:
-
- (PARAM . FLIP)
-
-PARAM is the name of '%s' entry parameter. For the meaning of
-FLIP, see `tabulated-list-sort-key'."
- entry-type-str entry-type-str)
- :type '(choice (const :tag "No sort" nil)
- (cons symbol boolean))
- :group ',group)
-
- (defvar ,marks-var ,marks-val
- ,(format "\
-Alist of additional marks for 'list' buffer with '%s' entries.
-Marks from this list are used along with `guix-list-default-marks'."
- entry-type-str))
-
- (defcustom ,list-single-var ,list-single-val
- ,(format "\
-If non-nil, list '%s' entry even if it is the only matching result.
-If nil, show a single '%s' entry in the 'info' buffer."
- entry-type-str entry-type-str)
- :type 'boolean
- :group ',group)
-
- (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))
-
- (guix-alist-put!
- '((describe . ,describe-var)
- (describe-count . ,describe-count-var)
- (format . ,format-var)
- (sort-key . ,sort-key-var)
- (list-single . ,list-single-var)
- (marks . ,marks-var))
- 'guix-list-data ',entry-type)
-
- ,(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))))))))
-
-
-(defvar guix-list-font-lock-keywords
- (eval-when-compile
- `((,(rx "(" (group "guix-list-define-interface")
- symbol-end)
- . 1))))
-
-(font-lock-add-keywords 'emacs-lisp-mode guix-list-font-lock-keywords)
-
-(provide 'guix-list)
-
-;;; guix-list.el ends here