Commit | Line | Data |
---|---|---|
d007d8a1 AK |
1 | ;;; guix-read.el --- Minibuffer readers |
2 | ||
3 | ;; Copyright © 2015 Alex Kost <alezost@gmail.com> | |
4 | ||
5 | ;; This file is part of GNU Guix. | |
6 | ||
7 | ;; GNU Guix is free software; you can redistribute it and/or modify | |
8 | ;; it under the terms of the GNU General Public License as published by | |
9 | ;; the Free Software Foundation, either version 3 of the License, or | |
10 | ;; (at your option) any later version. | |
11 | ||
12 | ;; GNU Guix is distributed in the hope that it will be useful, | |
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | ;; GNU General Public License for more details. | |
16 | ||
17 | ;; You should have received a copy of the GNU General Public License | |
18 | ;; along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | ||
20 | ;;; Commentary: | |
21 | ||
22 | ;; This file provides functions to prompt a user for packages, system | |
23 | ;; types, hash formats and other guix related stuff. | |
24 | ||
25 | ;;; Code: | |
26 | ||
27 | (require 'guix-help-vars) | |
28 | (require 'guix-utils) | |
29 | (require 'guix-base) | |
30 | ||
31 | (defun guix-read-file-name (prompt &optional dir default-filename | |
32 | mustmatch initial predicate) | |
33 | "Read file name. | |
34 | This function is similar to `read-file-name' except it also | |
35 | expands the file name." | |
36 | (expand-file-name (read-file-name prompt dir default-filename | |
37 | mustmatch initial predicate))) | |
38 | ||
39 | (defmacro guix-define-reader (name read-fun completions prompt) | |
40 | "Define NAME function to read from minibuffer. | |
41 | READ-FUN may be `completing-read', `completing-read-multiple' or | |
42 | another function with the same arguments." | |
43 | `(defun ,name (&optional prompt initial-contents) | |
44 | (,read-fun ,(if prompt | |
45 | `(or prompt ,prompt) | |
46 | 'prompt) | |
47 | ,completions nil nil initial-contents))) | |
48 | ||
49 | (defmacro guix-define-readers (&rest args) | |
50 | "Define reader functions. | |
51 | ||
52 | ARGS should have a form [KEYWORD VALUE] ... The following | |
53 | keywords are available: | |
54 | ||
55 | - `completions-var' - variable used to get completions. | |
56 | ||
57 | - `completions-getter' - function used to get completions. | |
58 | ||
59 | - `single-reader', `single-prompt' - name of a function to read | |
60 | a single value, and a prompt for it. | |
61 | ||
62 | - `multiple-reader', `multiple-prompt' - name of a function to | |
63 | read multiple values, and a prompt for it. | |
64 | ||
65 | - `multiple-separator' - if specified, another | |
66 | `<multiple-reader-name>-string' function returning a string | |
67 | of multiple values separated the specified separator will be | |
68 | defined." | |
69 | (let (completions-var | |
70 | completions-getter | |
71 | single-reader | |
72 | single-prompt | |
73 | multiple-reader | |
74 | multiple-prompt | |
75 | multiple-separator) | |
76 | ||
77 | ;; Process the keyword args. | |
78 | (while (keywordp (car args)) | |
79 | (pcase (pop args) | |
80 | (`:completions-var (setq completions-var (pop args))) | |
81 | (`:completions-getter (setq completions-getter (pop args))) | |
82 | (`:single-reader (setq single-reader (pop args))) | |
83 | (`:single-prompt (setq single-prompt (pop args))) | |
84 | (`:multiple-reader (setq multiple-reader (pop args))) | |
85 | (`:multiple-prompt (setq multiple-prompt (pop args))) | |
86 | (`:multiple-separator (setq multiple-separator (pop args))) | |
87 | (_ (pop args)))) | |
88 | ||
89 | (let ((completions | |
90 | (cond ((and completions-var completions-getter) | |
91 | `(or ,completions-var | |
92 | (setq ,completions-var | |
93 | (funcall ',completions-getter)))) | |
94 | (completions-var | |
95 | completions-var) | |
96 | (completions-getter | |
97 | `(funcall ',completions-getter))))) | |
98 | `(progn | |
99 | ,(when (and completions-var | |
100 | (not (boundp completions-var))) | |
101 | `(defvar ,completions-var nil)) | |
102 | ||
103 | ,(when single-reader | |
104 | `(guix-define-reader ,single-reader completing-read | |
105 | ,completions ,single-prompt)) | |
106 | ||
107 | ,(when multiple-reader | |
108 | `(guix-define-reader ,multiple-reader completing-read-multiple | |
109 | ,completions ,multiple-prompt)) | |
110 | ||
111 | ,(when (and multiple-reader multiple-separator) | |
112 | (let ((name (intern (concat (symbol-name multiple-reader) | |
113 | "-string")))) | |
114 | `(defun ,name (&optional prompt initial-contents) | |
115 | (guix-concat-strings | |
116 | (,multiple-reader prompt initial-contents) | |
117 | ,multiple-separator)))))))) | |
118 | ||
119 | (guix-define-readers | |
120 | :completions-var guix-help-system-types | |
121 | :single-reader guix-read-system-type | |
122 | :single-prompt "System type: ") | |
123 | ||
124 | (guix-define-readers | |
125 | :completions-var guix-help-source-types | |
126 | :single-reader guix-read-source-type | |
127 | :single-prompt "Source type: ") | |
128 | ||
129 | (guix-define-readers | |
130 | :completions-var guix-help-hash-formats | |
131 | :single-reader guix-read-hash-format | |
132 | :single-prompt "Hash format: ") | |
133 | ||
134 | (guix-define-readers | |
135 | :completions-var guix-help-refresh-subsets | |
136 | :single-reader guix-read-refresh-subset | |
137 | :single-prompt "Refresh subset: ") | |
138 | ||
139 | (guix-define-readers | |
140 | :completions-var guix-help-key-policies | |
141 | :single-reader guix-read-key-policy | |
142 | :single-prompt "Key policy: ") | |
143 | ||
144 | (guix-define-readers | |
145 | :completions-var guix-help-elpa-archives | |
146 | :single-reader guix-read-elpa-archive | |
147 | :single-prompt "ELPA archive: ") | |
148 | ||
149 | (guix-define-readers | |
150 | :completions-var guix-help-verify-options | |
151 | :multiple-reader guix-read-verify-options | |
152 | :multiple-prompt "Verify option,s: " | |
153 | :multiple-separator ",") | |
154 | ||
155 | (guix-define-readers | |
156 | :completions-getter guix-graph-type-names | |
157 | :single-reader guix-read-graph-type | |
158 | :single-prompt "Graph node type: ") | |
159 | ||
160 | (guix-define-readers | |
161 | :completions-getter guix-lint-checker-names | |
162 | :multiple-reader guix-read-lint-checker-names | |
163 | :multiple-prompt "Linter,s: " | |
164 | :multiple-separator ",") | |
165 | ||
166 | (guix-define-readers | |
167 | :completions-getter guix-package-names | |
168 | :single-reader guix-read-package-name | |
169 | :single-prompt "Package: " | |
170 | :multiple-reader guix-read-package-names | |
171 | :multiple-prompt "Package,s: " | |
172 | :multiple-separator " ") | |
173 | ||
174 | (provide 'guix-read) | |
175 | ||
176 | ;;; guix-read.el ends here |