You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

625 lines
24 KiB

  1. ;;; guix-buffer.el --- Buffer interface for displaying data -*- lexical-binding: t -*-
  2. ;; Copyright © 2014, 2015 Alex Kost <alezost@gmail.com>
  3. ;; This file is part of GNU Guix.
  4. ;; GNU 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. ;; GNU Guix is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;; You should have received a copy of the GNU General Public License
  13. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. ;;; Commentary:
  15. ;; This file provides a general 'buffer' interface for displaying an
  16. ;; arbitrary data.
  17. ;;; Code:
  18. (require 'cl-lib)
  19. (require 'guix-history)
  20. (require 'guix-utils)
  21. (defvar guix-buffer-map
  22. (let ((map (make-sparse-keymap)))
  23. (define-key map (kbd "l") 'guix-history-back)
  24. (define-key map (kbd "r") 'guix-history-forward)
  25. (define-key map (kbd "g") 'revert-buffer)
  26. (define-key map (kbd "R") 'guix-buffer-redisplay)
  27. map)
  28. "Parent keymap for Guix buffer modes.")
  29. ;;; Buffer item
  30. (cl-defstruct (guix-buffer-item
  31. (:constructor nil)
  32. (:constructor guix-buffer-make-item
  33. (entries buffer-type entry-type args))
  34. (:copier nil))
  35. entries buffer-type entry-type args)
  36. (defvar-local guix-buffer-item nil
  37. "Data (structure) for the current Guix buffer.
  38. The structure consists of the following elements:
  39. - `entries': list of the currently displayed entries.
  40. Each element of the list is an alist with an entry data of the
  41. following form:
  42. ((PARAM . VAL) ...)
  43. PARAM is a name of the entry parameter.
  44. VAL is a value of this parameter.
  45. - `entry-type': type of the currently displayed entries.
  46. - `buffer-type': type of the current buffer.
  47. - `args': search arguments used to get the current entries.")
  48. (put 'guix-buffer-item 'permanent-local t)
  49. (defmacro guix-buffer-with-item (item &rest body)
  50. "Evaluate BODY using buffer ITEM.
  51. The following local variables are available inside BODY:
  52. `%entries', `%buffer-type', `%entry-type', `%args'.
  53. See `guix-buffer-item' for details."
  54. (declare (indent 1) (debug t))
  55. (let ((item-var (make-symbol "item")))
  56. `(let ((,item-var ,item))
  57. (let ((%entries (guix-buffer-item-entries ,item-var))
  58. (%buffer-type (guix-buffer-item-buffer-type ,item-var))
  59. (%entry-type (guix-buffer-item-entry-type ,item-var))
  60. (%args (guix-buffer-item-args ,item-var)))
  61. ,@body))))
  62. (defmacro guix-buffer-with-current-item (&rest body)
  63. "Evaluate BODY using `guix-buffer-item'.
  64. See `guix-buffer-with-item' for details."
  65. (declare (indent 0) (debug t))
  66. `(guix-buffer-with-item guix-buffer-item
  67. ,@body))
  68. (defmacro guix-buffer-define-current-item-accessor (name)
  69. "Define `guix-buffer-current-NAME' function to access NAME
  70. element of `guix-buffer-item' structure.
  71. NAME should be a symbol."
  72. (let* ((name-str (symbol-name name))
  73. (accessor (intern (concat "guix-buffer-item-" name-str)))
  74. (fun-name (intern (concat "guix-buffer-current-" name-str)))
  75. (doc (format "\
  76. Return '%s' of the current Guix buffer.
  77. See `guix-buffer-item' for details."
  78. name-str)))
  79. `(defun ,fun-name ()
  80. ,doc
  81. (and guix-buffer-item
  82. (,accessor guix-buffer-item)))))
  83. (defmacro guix-buffer-define-current-item-accessors (&rest names)
  84. "Define `guix-buffer-current-NAME' functions for NAMES.
  85. See `guix-buffer-define-current-item-accessor' for details."
  86. `(progn
  87. ,@(mapcar (lambda (name)
  88. `(guix-buffer-define-current-item-accessor ,name))
  89. names)))
  90. (guix-buffer-define-current-item-accessors
  91. entries entry-type buffer-type args)
  92. (defmacro guix-buffer-define-current-args-accessor (n prefix name)
  93. "Define `PREFIX-NAME' function to access Nth element of 'args'
  94. field of `guix-buffer-item' structure.
  95. PREFIX and NAME should be strings."
  96. (let ((fun-name (intern (concat prefix "-" name)))
  97. (doc (format "\
  98. Return '%s' of the current Guix buffer.
  99. '%s' is the element number %d in 'args' of `guix-buffer-item'."
  100. name name n)))
  101. `(defun ,fun-name ()
  102. ,doc
  103. (nth ,n (guix-buffer-current-args)))))
  104. (defmacro guix-buffer-define-current-args-accessors (prefix &rest names)
  105. "Define `PREFIX-NAME' functions for NAMES.
  106. See `guix-buffer-define-current-args-accessor' for details."
  107. `(progn
  108. ,@(cl-loop for name in names
  109. for i from 0
  110. collect `(guix-buffer-define-current-args-accessor
  111. ,i ,prefix ,name))))
  112. ;;; Wrappers for defined variables
  113. (defvar guix-buffer-data nil
  114. "Alist with 'buffer' data.
  115. This alist is filled by `guix-buffer-define-interface' macro.")
  116. (defun guix-buffer-value (buffer-type entry-type symbol)
  117. "Return SYMBOL's value for BUFFER-TYPE/ENTRY-TYPE from `guix-buffer-data'."
  118. (symbol-value
  119. (guix-assq-value guix-buffer-data buffer-type entry-type symbol)))
  120. (defun guix-buffer-get-entries (buffer-type entry-type args)
  121. "Return ENTRY-TYPE entries.
  122. Call an appropriate 'get-entries' function from `guix-buffer'
  123. using ARGS as its arguments."
  124. (apply (guix-buffer-value buffer-type entry-type 'get-entries)
  125. args))
  126. (defun guix-buffer-mode-enable (buffer-type entry-type)
  127. "Turn on major mode to display ENTRY-TYPE ENTRIES in BUFFER-TYPE buffer."
  128. (funcall (guix-buffer-value buffer-type entry-type 'mode)))
  129. (defun guix-buffer-mode-initialize (buffer-type entry-type)
  130. "Set up the current BUFFER-TYPE buffer to display ENTRY-TYPE entries."
  131. (let ((fun (guix-buffer-value buffer-type entry-type 'mode-init)))
  132. (when fun
  133. (funcall fun))))
  134. (defun guix-buffer-insert-entries (entries buffer-type entry-type)
  135. "Show ENTRY-TYPE ENTRIES in the current BUFFER-TYPE buffer."
  136. (funcall (guix-buffer-value buffer-type entry-type 'insert-entries)
  137. entries))
  138. (defun guix-buffer-show-entries-default (entries buffer-type entry-type)
  139. "Show ENTRY-TYPE ENTRIES in the current BUFFER-TYPE buffer."
  140. (let ((inhibit-read-only t))
  141. (erase-buffer)
  142. (guix-buffer-mode-enable buffer-type entry-type)
  143. (guix-buffer-insert-entries entries buffer-type entry-type)
  144. (goto-char (point-min))))
  145. (defun guix-buffer-show-entries (entries buffer-type entry-type)
  146. "Show ENTRY-TYPE ENTRIES in the current BUFFER-TYPE buffer."
  147. (funcall (guix-buffer-value buffer-type entry-type 'show-entries)
  148. entries))
  149. (defun guix-buffer-message (entries buffer-type entry-type args)
  150. "Display a message for BUFFER-ITEM after showing entries."
  151. (let ((fun (guix-buffer-value buffer-type entry-type 'message)))
  152. (when fun
  153. (apply fun entries args))))
  154. (defun guix-buffer-name (buffer-type entry-type args)
  155. "Return name of BUFFER-TYPE buffer for displaying ENTRY-TYPE entries."
  156. (let ((str-or-fun (guix-buffer-value buffer-type entry-type
  157. 'buffer-name)))
  158. (if (stringp str-or-fun)
  159. str-or-fun
  160. (apply str-or-fun args))))
  161. (defun guix-buffer-param-title (buffer-type entry-type param)
  162. "Return PARAM title for BUFFER-TYPE/ENTRY-TYPE."
  163. (or (guix-assq-value (guix-buffer-value buffer-type entry-type 'titles)
  164. param)
  165. ;; Fallback to a title defined in 'info' interface.
  166. (unless (eq buffer-type 'info)
  167. (guix-assq-value (guix-buffer-value 'info entry-type 'titles)
  168. param))
  169. (guix-symbol-title param)))
  170. (defun guix-buffer-history-size (buffer-type entry-type)
  171. "Return history size for BUFFER-TYPE/ENTRY-TYPE."
  172. (guix-buffer-value buffer-type entry-type 'history-size))
  173. (defun guix-buffer-revert-confirm? (buffer-type entry-type)
  174. "Return 'revert-confirm' value for BUFFER-TYPE/ENTRY-TYPE."
  175. (guix-buffer-value buffer-type entry-type 'revert-confirm))
  176. ;;; Displaying entries
  177. (defun guix-buffer-display (buffer)
  178. "Switch to a Guix BUFFER."
  179. (pop-to-buffer buffer
  180. '((display-buffer-reuse-window
  181. display-buffer-same-window))))
  182. (defun guix-buffer-history-item (buffer-item)
  183. "Make and return a history item for displaying BUFFER-ITEM."
  184. (list #'guix-buffer-set buffer-item))
  185. (defun guix-buffer-set (buffer-item &optional history)
  186. "Set up the current buffer for displaying BUFFER-ITEM.
  187. HISTORY should be one of the following:
  188. `nil' - do not save BUFFER-ITEM in history,
  189. `add' - add it to history,
  190. `replace' - replace the current history item."
  191. (guix-buffer-with-item buffer-item
  192. (when %entries
  193. ;; Set buffer item before showing entries, so that its value can
  194. ;; be used by the code for displaying entries.
  195. (setq guix-buffer-item buffer-item)
  196. (guix-buffer-show-entries %entries %buffer-type %entry-type)
  197. (when history
  198. (funcall (cl-ecase history
  199. (add #'guix-history-add)
  200. (replace #'guix-history-replace))
  201. (guix-buffer-history-item buffer-item))))
  202. (guix-buffer-message %entries %buffer-type %entry-type %args)))
  203. (defun guix-buffer-display-entries-current
  204. (entries buffer-type entry-type args &optional history)
  205. "Show ENTRIES in the current Guix buffer.
  206. See `guix-buffer-item' for the meaning of BUFFER-TYPE, ENTRY-TYPE
  207. and ARGS, and `guix-buffer-set' for the meaning of HISTORY."
  208. (let ((item (guix-buffer-make-item entries buffer-type
  209. entry-type args)))
  210. (guix-buffer-set item history)))
  211. (defun guix-buffer-get-display-entries-current
  212. (buffer-type entry-type args &optional history)
  213. "Search for entries and show them in the current Guix buffer.
  214. See `guix-buffer-display-entries-current' for details."
  215. (guix-buffer-display-entries-current
  216. (guix-buffer-get-entries buffer-type entry-type args)
  217. buffer-type entry-type args history))
  218. (defun guix-buffer-display-entries
  219. (entries buffer-type entry-type args &optional history)
  220. "Show ENTRIES in a BUFFER-TYPE buffer.
  221. See `guix-buffer-display-entries-current' for details."
  222. (let ((buffer (get-buffer-create
  223. (guix-buffer-name buffer-type entry-type args))))
  224. (with-current-buffer buffer
  225. (guix-buffer-display-entries-current
  226. entries buffer-type entry-type args history))
  227. (when entries
  228. (guix-buffer-display buffer))))
  229. (defun guix-buffer-get-display-entries
  230. (buffer-type entry-type args &optional history)
  231. "Search for entries and show them in a BUFFER-TYPE buffer.
  232. See `guix-buffer-display-entries-current' for details."
  233. (guix-buffer-display-entries
  234. (guix-buffer-get-entries buffer-type entry-type args)
  235. buffer-type entry-type args history))
  236. (defun guix-buffer-revert (_ignore-auto noconfirm)
  237. "Update the data in the current Guix buffer.
  238. This function is suitable for `revert-buffer-function'.
  239. See `revert-buffer' for the meaning of NOCONFIRM."
  240. (guix-buffer-with-current-item
  241. (when (or noconfirm
  242. (not (guix-buffer-revert-confirm? %buffer-type %entry-type))
  243. (y-or-n-p "Update the current buffer? "))
  244. (guix-buffer-get-display-entries-current
  245. %buffer-type %entry-type %args 'replace))))
  246. (defvar guix-buffer-after-redisplay-hook nil
  247. "Hook run by `guix-buffer-redisplay'.
  248. This hook is called before seting up a window position.")
  249. (defun guix-buffer-redisplay ()
  250. "Redisplay the current Guix buffer.
  251. Restore the point and window positions after redisplaying.
  252. This function does not update the buffer data, use
  253. '\\[revert-buffer]' if you want the full update."
  254. (interactive)
  255. (let* ((old-point (point))
  256. ;; For simplicity, ignore an unlikely case when multiple
  257. ;; windows display the same buffer.
  258. (window (car (get-buffer-window-list (current-buffer) nil t)))
  259. (window-start (and window (window-start window))))
  260. (guix-buffer-set guix-buffer-item)
  261. (goto-char old-point)
  262. (run-hooks 'guix-buffer-after-redisplay-hook)
  263. (when window
  264. (set-window-point window (point))
  265. (set-window-start window window-start))))
  266. (defun guix-buffer-redisplay-goto-button ()
  267. "Redisplay the current buffer and go to the next button, if needed."
  268. (let ((guix-buffer-after-redisplay-hook
  269. (cons (lambda ()
  270. (unless (button-at (point))
  271. (forward-button 1)))
  272. guix-buffer-after-redisplay-hook)))
  273. (guix-buffer-redisplay)))
  274. ;;; Interface definers
  275. (defmacro guix-define-groups (type &rest args)
  276. "Define `guix-TYPE' and `guix-TYPE-faces' custom groups.
  277. Remaining arguments (ARGS) should have a form [KEYWORD VALUE] ...
  278. Optional keywords:
  279. - `:parent-group' - name of a parent custom group.
  280. - `:parent-faces-group' - name of a parent custom faces group.
  281. - `:group-doc' - docstring of a `guix-TYPE' group.
  282. - `:faces-group-doc' - docstring of a `guix-TYPE-faces' group."
  283. (declare (indent 1))
  284. (let* ((type-str (symbol-name type))
  285. (prefix (concat "guix-" type-str))
  286. (group (intern prefix))
  287. (faces-group (intern (concat prefix "-faces"))))
  288. (guix-keyword-args-let args
  289. ((parent-group :parent-group 'guix)
  290. (parent-faces-group :parent-faces-group 'guix-faces)
  291. (group-doc :group-doc
  292. (format "Settings for '%s' buffers."
  293. type-str))
  294. (faces-group-doc :faces-group-doc
  295. (format "Faces for '%s' buffers."
  296. type-str)))
  297. `(progn
  298. (defgroup ,group nil
  299. ,group-doc
  300. :group ',parent-group)
  301. (defgroup ,faces-group nil
  302. ,faces-group-doc
  303. :group ',group
  304. :group ',parent-faces-group)))))
  305. (defmacro guix-define-entry-type (entry-type &rest args)
  306. "Define general code for ENTRY-TYPE.
  307. See `guix-define-groups'."
  308. (declare (indent 1))
  309. `(guix-define-groups ,entry-type
  310. ,@args))
  311. (defmacro guix-define-buffer-type (buffer-type &rest args)
  312. "Define general code for BUFFER-TYPE.
  313. See `guix-define-groups'."
  314. (declare (indent 1))
  315. `(guix-define-groups ,buffer-type
  316. ,@args))
  317. (defmacro guix-buffer-define-interface (buffer-type entry-type &rest args)
  318. "Define BUFFER-TYPE interface for displaying ENTRY-TYPE entries.
  319. Remaining arguments (ARGS) should have a form [KEYWORD VALUE] ...
  320. In the following description TYPE means ENTRY-TYPE-BUFFER-TYPE.
  321. Required keywords:
  322. - `:buffer-name' - default value of the generated
  323. `guix-TYPE-buffer-name' variable.
  324. - `:get-entries-function' - default value of the generated
  325. `guix-TYPE-get-function' variable.
  326. - `:show-entries-function' - default value of the generated
  327. `guix-TYPE-show-function' variable.
  328. Alternatively, if `:show-entries-function' is not specified, a
  329. default `guix-TYPE-show-entries' will be generated, and the
  330. following keyword should be specified instead:
  331. - `:insert-entries-function' - default value of the generated
  332. `guix-TYPE-insert-function' variable.
  333. Optional keywords:
  334. - `:message-function' - default value of the generated
  335. `guix-TYPE-message-function' variable.
  336. - `:titles' - default value of the generated
  337. `guix-TYPE-titles' variable.
  338. - `:history-size' - default value of the generated
  339. `guix-TYPE-history-size' variable.
  340. - `:revert-confirm?' - default value of the generated
  341. `guix-TYPE-revert-confirm' variable.
  342. - `:mode-name' - name (a string appeared in the mode-line) of
  343. the generated `guix-TYPE-mode'.
  344. - `:mode-init-function' - default value of the generated
  345. `guix-TYPE-mode-initialize-function' variable.
  346. - `:reduced?' - if non-nil, generate only group, faces group
  347. and titles variable (if specified); all keywords become
  348. optional."
  349. (declare (indent 2))
  350. (let* ((entry-type-str (symbol-name entry-type))
  351. (buffer-type-str (symbol-name buffer-type))
  352. (prefix (concat "guix-" entry-type-str "-"
  353. buffer-type-str))
  354. (group (intern prefix))
  355. (faces-group (intern (concat prefix "-faces")))
  356. (get-entries-var (intern (concat prefix "-get-function")))
  357. (show-entries-var (intern (concat prefix "-show-function")))
  358. (show-entries-fun (intern (concat prefix "-show-entries")))
  359. (message-var (intern (concat prefix "-message-function")))
  360. (buffer-name-var (intern (concat prefix "-buffer-name")))
  361. (titles-var (intern (concat prefix "-titles")))
  362. (history-size-var (intern (concat prefix "-history-size")))
  363. (revert-confirm-var (intern (concat prefix "-revert-confirm"))))
  364. (guix-keyword-args-let args
  365. ((get-entries-val :get-entries-function)
  366. (show-entries-val :show-entries-function)
  367. (insert-entries-val :insert-entries-function)
  368. (mode-name :mode-name (capitalize prefix))
  369. (mode-init-val :mode-init-function)
  370. (message-val :message-function)
  371. (buffer-name-val :buffer-name)
  372. (titles-val :titles)
  373. (history-size-val :history-size 20)
  374. (revert-confirm-val :revert-confirm? t)
  375. (reduced? :reduced?))
  376. `(progn
  377. (defgroup ,group nil
  378. ,(format "Displaying '%s' entries in '%s' buffer."
  379. entry-type-str buffer-type-str)
  380. :group ',(intern (concat "guix-" entry-type-str))
  381. :group ',(intern (concat "guix-" buffer-type-str)))
  382. (defgroup ,faces-group nil
  383. ,(format "Faces for displaying '%s' entries in '%s' buffer."
  384. entry-type-str buffer-type-str)
  385. :group ',group
  386. :group ',(intern (concat "guix-" entry-type-str "-faces"))
  387. :group ',(intern (concat "guix-" buffer-type-str "-faces")))
  388. (defcustom ,titles-var ,titles-val
  389. ,(format "Alist of titles of '%s' parameters."
  390. entry-type-str)
  391. :type '(alist :key-type symbol :value-type string)
  392. :group ',group)
  393. ,(unless reduced?
  394. `(progn
  395. (defvar ,get-entries-var ,get-entries-val
  396. ,(format "\
  397. Function used to receive '%s' entries for '%s' buffer."
  398. entry-type-str buffer-type-str))
  399. (defvar ,show-entries-var
  400. ,(or show-entries-val `',show-entries-fun)
  401. ,(format "\
  402. Function used to show '%s' entries in '%s' buffer."
  403. entry-type-str buffer-type-str))
  404. (defvar ,message-var ,message-val
  405. ,(format "\
  406. Function used to display a message after showing '%s' entries.
  407. If nil, do not display messages."
  408. entry-type-str))
  409. (defcustom ,buffer-name-var ,buffer-name-val
  410. ,(format "\
  411. Default name of '%s' buffer for displaying '%s' entries.
  412. May be a string or a function returning a string. The function
  413. is called with the same arguments as `%S'."
  414. buffer-type-str entry-type-str get-entries-var)
  415. :type '(choice string function)
  416. :group ',group)
  417. (defcustom ,history-size-var ,history-size-val
  418. ,(format "\
  419. Maximum number of items saved in history of `%S' buffer.
  420. If 0, the history is disabled."
  421. buffer-name-var)
  422. :type 'integer
  423. :group ',group)
  424. (defcustom ,revert-confirm-var ,revert-confirm-val
  425. ,(format "\
  426. If non-nil, ask to confirm for reverting `%S' buffer."
  427. buffer-name-var)
  428. :type 'boolean
  429. :group ',group)
  430. (guix-alist-put!
  431. '((get-entries . ,get-entries-var)
  432. (show-entries . ,show-entries-var)
  433. (message . ,message-var)
  434. (buffer-name . ,buffer-name-var)
  435. (history-size . ,history-size-var)
  436. (revert-confirm . ,revert-confirm-var))
  437. 'guix-buffer-data ',buffer-type ',entry-type)
  438. ,(unless show-entries-val
  439. `(defun ,show-entries-fun (entries)
  440. ,(format "\
  441. Show '%s' ENTRIES in the current '%s' buffer."
  442. entry-type-str buffer-type-str)
  443. (guix-buffer-show-entries-default
  444. entries ',buffer-type ',entry-type)))
  445. ,(when (or insert-entries-val
  446. (null show-entries-val))
  447. (let ((insert-entries-var
  448. (intern (concat prefix "-insert-function"))))
  449. `(progn
  450. (defvar ,insert-entries-var ,insert-entries-val
  451. ,(format "\
  452. Function used to print '%s' entries in '%s' buffer."
  453. entry-type-str buffer-type-str))
  454. (guix-alist-put!
  455. ',insert-entries-var 'guix-buffer-data
  456. ',buffer-type ',entry-type
  457. 'insert-entries))))
  458. ,(when (or mode-name
  459. mode-init-val
  460. (null show-entries-val))
  461. (let* ((mode-str (concat prefix "-mode"))
  462. (mode-map-str (concat mode-str "-map"))
  463. (mode (intern mode-str))
  464. (parent-mode (intern
  465. (concat "guix-" buffer-type-str
  466. "-mode")))
  467. (mode-var (intern
  468. (concat mode-str "-function")))
  469. (mode-init-var (intern
  470. (concat mode-str
  471. "-initialize-function"))))
  472. `(progn
  473. (defvar ,mode-var ',mode
  474. ,(format "\
  475. Major mode for displaying '%s' entries in '%s' buffer."
  476. entry-type-str buffer-type-str))
  477. (defvar ,mode-init-var ,mode-init-val
  478. ,(format "\
  479. Function used to set up '%s' buffer for displaying '%s' entries."
  480. buffer-type-str entry-type-str))
  481. (define-derived-mode ,mode ,parent-mode ,mode-name
  482. ,(format "\
  483. Major mode for displaying '%s' entries in '%s' buffer.
  484. \\{%s}"
  485. entry-type-str buffer-type-str mode-map-str)
  486. (setq-local revert-buffer-function
  487. 'guix-buffer-revert)
  488. (setq-local guix-history-size
  489. (guix-buffer-history-size
  490. ',buffer-type ',entry-type))
  491. (guix-buffer-mode-initialize
  492. ',buffer-type ',entry-type))
  493. (guix-alist-put!
  494. ',mode-var 'guix-buffer-data
  495. ',buffer-type ',entry-type 'mode)
  496. (guix-alist-put!
  497. ',mode-init-var 'guix-buffer-data
  498. ',buffer-type ',entry-type
  499. 'mode-init))))))
  500. (guix-alist-put!
  501. ',titles-var 'guix-buffer-data
  502. ',buffer-type ',entry-type 'titles)))))
  503. (defvar guix-buffer-font-lock-keywords
  504. (eval-when-compile
  505. `((,(rx "(" (group (or "guix-buffer-with-item"
  506. "guix-buffer-with-current-item"
  507. "guix-buffer-define-interface"
  508. "guix-define-groups"
  509. "guix-define-entry-type"
  510. "guix-define-buffer-type"))
  511. symbol-end)
  512. . 1))))
  513. (font-lock-add-keywords 'emacs-lisp-mode guix-buffer-font-lock-keywords)
  514. (provide 'guix-buffer)
  515. ;;; guix-buffer.el ends here