guix-ui.el 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. ;;; guix-ui.el --- Common code for Guix package management interface -*- lexical-binding: t -*-
  2. ;; Copyright © 2014–2017 Alex Kost <alezost@gmail.com>
  3. ;; This file is part of Emacs-Guix.
  4. ;; Emacs-Guix is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation, either version 3 of the License, or
  7. ;; (at your option) any later version.
  8. ;;
  9. ;; Emacs-Guix is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with Emacs-Guix. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;; This file provides some general code for 'list'/'info' interfaces for
  18. ;; packages and generations.
  19. ;;; Code:
  20. (require 'cl-lib)
  21. (require 'bui)
  22. (require 'guix nil t)
  23. (require 'guix-repl)
  24. (require 'guix-guile)
  25. (require 'guix-utils)
  26. (require 'guix-ui-messages)
  27. (require 'guix-profiles)
  28. (defvar guix-ui-map
  29. (let ((map (make-sparse-keymap)))
  30. (define-key map (kbd "M") 'guix-apply-manifest)
  31. (define-key map (kbd "C-c C-z") 'guix-switch-to-repl)
  32. map)
  33. "Parent keymap for Guix package/generation buffers.")
  34. (defvar guix-ui-hint
  35. '(("\\[guix-apply-manifest]") " apply manifest; "
  36. ("\\[guix-switch-to-repl]") " switch to Guix REPL;\n")
  37. "General hint for UI buffers.
  38. See `bui-hint' for details.")
  39. (bui-define-current-args-accessors
  40. guix-ui-current profile search-type search-values)
  41. (defun guix-ui-read-package-profile ()
  42. "Return `guix-current-profile' or prompt for it.
  43. This function is intended for using in `interactive' forms."
  44. (if current-prefix-arg
  45. (guix-read-package-profile)
  46. guix-current-profile))
  47. (defun guix-ui-read-generation-profile ()
  48. "Return `guix-current-profile' or prompt for it.
  49. This function is intended for using in `interactive' forms."
  50. (if current-prefix-arg
  51. (guix-read-generation-profile)
  52. guix-current-profile))
  53. (defun guix-ui-get-entries (profile entry-type search-type search-values
  54. &optional params)
  55. "Receive ENTRY-TYPE entries for PROFILE.
  56. Call an appropriate scheme procedure and return a list of entries.
  57. ENTRY-TYPE should be one of the following symbols: `package' or
  58. `output'.
  59. SEARCH-TYPE may be one of the following symbols: `id', `name',
  60. `regexp', `all-available', `newest-available', `installed', `unknown',
  61. `superseded', `license', `location', `from-file', `from-os-file'.
  62. PARAMS is a list of parameters for receiving. If nil, get data
  63. with all available parameters."
  64. (guix-eval-read
  65. (guix-make-guile-expression
  66. 'package/output-sexps
  67. profile entry-type search-type search-values params)))
  68. (defun guix-ui-list-describe (&rest ids)
  69. "Describe 'ui' entries with IDS (list of identifiers)."
  70. (bui-get-display-entries
  71. (bui-current-entry-type) 'info
  72. (cl-list* (guix-ui-current-profile) 'id ids)
  73. 'add))
  74. ;;; Buffers
  75. (defcustom guix-ui-buffer-name-function
  76. #'guix-ui-buffer-name-full
  77. "Function used to define a name of a Guix buffer.
  78. The function is called with 2 arguments: BASE-NAME and PROFILE."
  79. :type '(choice (function-item guix-ui-buffer-name-full)
  80. (function-item guix-ui-buffer-name-short)
  81. (function-item guix-ui-buffer-name-simple)
  82. (function :tag "Other function"))
  83. :group 'guix)
  84. (defun guix-ui-buffer-name-simple (base-name &rest _)
  85. "Return BASE-NAME."
  86. base-name)
  87. (defun guix-ui-buffer-name-short (base-name profile)
  88. "Return buffer name by appending BASE-NAME and PROFILE's base file name."
  89. (guix-compose-buffer-name base-name
  90. (file-name-base (directory-file-name profile))))
  91. (defun guix-ui-buffer-name-full (base-name profile)
  92. "Return buffer name by appending BASE-NAME and PROFILE's full name."
  93. (guix-compose-buffer-name base-name profile))
  94. (defun guix-ui-buffer-name (base-name profile)
  95. "Return Guix buffer name based on BASE-NAME and profile.
  96. See `guix-ui-buffer-name-function' for details."
  97. (funcall guix-ui-buffer-name-function
  98. base-name profile))
  99. ;;; Interface definers
  100. (defmacro guix-ui-define-entry-type (entry-type &rest args)
  101. "Define general code for ENTRY-TYPE.
  102. Remaining arguments (ARGS) should have a form [KEYWORD VALUE] ...
  103. They are passed to `bui-define-entry-type' macro.
  104. This macro also defines:
  105. - `guix-TYPE-message' - a wrapper around `guix-result-message'."
  106. (declare (indent 1))
  107. (let* ((entry-type-str (symbol-name entry-type))
  108. (full-entry-type (guix-make-symbol entry-type))
  109. (prefix (concat "guix-" entry-type-str))
  110. (message-fun (intern (concat prefix "-message"))))
  111. `(progn
  112. (defun ,message-fun (entries profile search-type
  113. &rest search-values)
  114. ,(format "\
  115. Display a message after showing '%s' entries.
  116. This is a wrapper for `guix-result-message'."
  117. entry-type-str)
  118. (guix-result-message profile entries ',entry-type
  119. search-type search-values))
  120. (guix-define-groups ,entry-type)
  121. (bui-define-entry-type ,full-entry-type
  122. :message-function ',message-fun
  123. ,@args))))
  124. (defmacro guix-ui-define-interface (entry-type buffer-type &rest args)
  125. "Define BUFFER-TYPE interface for displaying ENTRY-TYPE entries.
  126. Remaining arguments (ARGS) should have a form [KEYWORD VALUE] ...
  127. In the following description TYPE means ENTRY-TYPE-BUFFER-TYPE.
  128. Required keywords:
  129. - `:buffer-name' - base part of a buffer name. It is used in a
  130. generated `guix-TYPE-buffer-name' function; see
  131. `guix-ui-buffer-name' for details.
  132. Optional keywords:
  133. - `:required' - default value of the generated
  134. `guix-TYPE-required-params' variable.
  135. The rest keyword arguments are passed to `bui-define-interface'
  136. macro.
  137. Along with the mentioned definitions, this macro also defines:
  138. - `guix-TYPE-mode-map' - keymap based on `guix-ui-map' and
  139. `bui-BUFFER-TYPE-mode-map'."
  140. (declare (indent 2))
  141. (let* ((entry-type-str (symbol-name entry-type))
  142. (buffer-type-str (symbol-name buffer-type))
  143. (prefix (concat "guix-" entry-type-str "-"
  144. buffer-type-str))
  145. (mode-str (concat prefix "-mode"))
  146. (mode-map (intern (concat mode-str "-map")))
  147. (parent-map (intern (format "bui-%s-mode-map"
  148. buffer-type-str)))
  149. (required-var (intern (concat prefix "-required-params")))
  150. (buffer-name-fun (intern (concat prefix "-buffer-name"))))
  151. (bui-plist-let args
  152. ((buffer-name-val :buffer-name)
  153. (required-val :required ''(id)))
  154. `(progn
  155. (defvar ,mode-map
  156. (let ((map (make-sparse-keymap)))
  157. (set-keymap-parent
  158. map (make-composed-keymap guix-ui-map ,parent-map))
  159. map)
  160. ,(format "Keymap for `%s' buffers." mode-str))
  161. (defvar ,required-var ,required-val
  162. ,(format "\
  163. List of the required '%s' parameters.
  164. These parameters are received from the Scheme side
  165. along with the displayed parameters.
  166. Do not remove `id' from this list as it is required for
  167. identifying an entry."
  168. entry-type-str))
  169. (defun ,buffer-name-fun (profile &rest _)
  170. ,(format "\
  171. Return a name of '%s' buffer for displaying '%s' entries.
  172. See `guix-ui-buffer-name' for details."
  173. buffer-type-str entry-type-str)
  174. (guix-ui-buffer-name ,buffer-name-val profile))
  175. (bui-define-interface ,(guix-make-symbol entry-type) ,buffer-type
  176. :buffer-name ',buffer-name-fun
  177. ,@%foreign-args)))))
  178. (defvar guix-ui-font-lock-keywords
  179. (eval-when-compile
  180. `((,(rx "(" (group (or "guix-ui-define-entry-type"
  181. "guix-ui-define-interface"))
  182. symbol-end)
  183. . 1))))
  184. (font-lock-add-keywords 'emacs-lisp-mode guix-ui-font-lock-keywords)
  185. (provide 'guix-ui)
  186. ;;; guix-ui.el ends here