summaryrefslogtreecommitdiff
path: root/emacs/guix-buffer.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs/guix-buffer.el')
-rw-r--r--emacs/guix-buffer.el624
1 files changed, 0 insertions, 624 deletions
diff --git a/emacs/guix-buffer.el b/emacs/guix-buffer.el
deleted file mode 100644
index 4cefe9989e..0000000000
--- a/emacs/guix-buffer.el
+++ /dev/null
@@ -1,624 +0,0 @@
-;;; 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
- ;; Set buffer item before showing entries, so that its value can
- ;; be used by the code for displaying entries.
- (setq guix-buffer-item buffer-item)
- (guix-buffer-show-entries %entries %buffer-type %entry-type)
- (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 definers
-
-(defmacro guix-define-groups (type &rest args)
- "Define `guix-TYPE' and `guix-TYPE-faces' custom groups.
-Remaining arguments (ARGS) should have a form [KEYWORD VALUE] ...
-
-Optional keywords:
-
- - `:parent-group' - name of a parent custom group.
-
- - `:parent-faces-group' - name of a parent custom faces group.
-
- - `:group-doc' - docstring of a `guix-TYPE' group.
-
- - `:faces-group-doc' - docstring of a `guix-TYPE-faces' group."
- (declare (indent 1))
- (let* ((type-str (symbol-name type))
- (prefix (concat "guix-" type-str))
- (group (intern prefix))
- (faces-group (intern (concat prefix "-faces"))))
- (guix-keyword-args-let args
- ((parent-group :parent-group 'guix)
- (parent-faces-group :parent-faces-group 'guix-faces)
- (group-doc :group-doc
- (format "Settings for '%s' buffers."
- type-str))
- (faces-group-doc :faces-group-doc
- (format "Faces for '%s' buffers."
- type-str)))
- `(progn
- (defgroup ,group nil
- ,group-doc
- :group ',parent-group)
-
- (defgroup ,faces-group nil
- ,faces-group-doc
- :group ',group
- :group ',parent-faces-group)))))
-
-(defmacro guix-define-entry-type (entry-type &rest args)
- "Define general code for ENTRY-TYPE.
-See `guix-define-groups'."
- (declare (indent 1))
- `(guix-define-groups ,entry-type
- ,@args))
-
-(defmacro guix-define-buffer-type (buffer-type &rest args)
- "Define general code for BUFFER-TYPE.
-See `guix-define-groups'."
- (declare (indent 1))
- `(guix-define-groups ,buffer-type
- ,@args))
-
-(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 "Displaying '%s' entries in '%s' buffer."
- entry-type-str buffer-type-str)
- :group ',(intern (concat "guix-" entry-type-str))
- :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 ',group
- :group ',(intern (concat "guix-" entry-type-str "-faces"))
- :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"
- "guix-define-groups"
- "guix-define-entry-type"
- "guix-define-buffer-type"))
- symbol-end)
- . 1))))
-
-(font-lock-add-keywords 'emacs-lisp-mode guix-buffer-font-lock-keywords)
-
-(provide 'guix-buffer)
-
-;;; guix-buffer.el ends here