diff options
| author | Lars Ingebrigtsen | 2016-02-04 19:51:54 +1100 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2016-02-04 19:52:07 +1100 |
| commit | 4531b03ec98b50fc61baad2b75f6faf439894583 (patch) | |
| tree | 480bd9f181799d8cf9dba26860360b57131820b9 | |
| parent | d95c7bb472cd259661dfed41ccfe534f9026c826 (diff) | |
| download | emacs-4531b03ec98b50fc61baad2b75f6faf439894583.tar.gz emacs-4531b03ec98b50fc61baad2b75f6faf439894583.zip | |
New function read-multiple-choice
* doc/lispref/commands.texi (Reading One Event): Document
read-multiple-choice.
* lisp/faces.el (read-multiple-choice-face): New face.
* lisp/subr.el (read-multiple-choice): New function.
| -rw-r--r-- | doc/lispref/commands.texi | 21 | ||||
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | lisp/faces.el | 6 | ||||
| -rw-r--r-- | lisp/subr.el | 114 |
4 files changed, 145 insertions, 0 deletions
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 9c1df895161..1964ec8e3fe 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi | |||
| @@ -2617,6 +2617,27 @@ causes it to evaluate @code{help-form} and display the result. It | |||
| 2617 | then continues to wait for a valid input character, or keyboard-quit. | 2617 | then continues to wait for a valid input character, or keyboard-quit. |
| 2618 | @end defun | 2618 | @end defun |
| 2619 | 2619 | ||
| 2620 | @defun read-multiple-choice prompt choices | ||
| 2621 | Ask user a multiple choice question. @var{prompt} should be a string | ||
| 2622 | that will be displayed as the prompt. | ||
| 2623 | |||
| 2624 | @var{choices} is an alist where the first element in each entry is a | ||
| 2625 | character to be entered, the second element is a short name for the | ||
| 2626 | entry to be displayed while prompting (if there's room, it might be | ||
| 2627 | shortened), and the third, optional entry is a longer explanation that | ||
| 2628 | will be displayed in a help buffer if the user requests more help. | ||
| 2629 | |||
| 2630 | The return value is the matching value from @var{choices}. | ||
| 2631 | |||
| 2632 | @lisp | ||
| 2633 | (read-multiple-choice | ||
| 2634 | "Continue connecting?" | ||
| 2635 | '((?a "always" "Accept this certificate this session and for all future sessions.") | ||
| 2636 | (?s "session only" "Accept this certificate this session only.") | ||
| 2637 | (?n "no" "Refuse to use this certificate, and close the connection."))) | ||
| 2638 | @end lisp | ||
| 2639 | @end defun | ||
| 2640 | |||
| 2620 | @node Event Mod | 2641 | @node Event Mod |
| 2621 | @subsection Modifying and Translating Input Events | 2642 | @subsection Modifying and Translating Input Events |
| 2622 | @cindex modifiers of events | 2643 | @cindex modifiers of events |
| @@ -283,6 +283,10 @@ selected window is strongly dedicated to its buffer. | |||
| 283 | `even-window-sizes' and now handles window widths as well. | 283 | `even-window-sizes' and now handles window widths as well. |
| 284 | 284 | ||
| 285 | +++ | 285 | +++ |
| 286 | ** New function `read-multiple-choice' use to prompt for | ||
| 287 | multiple-choice questions, with a handy way to display help texts. | ||
| 288 | |||
| 289 | +++ | ||
| 286 | ** terpri gets an optional arg ENSURE to conditionally output a newline. | 290 | ** terpri gets an optional arg ENSURE to conditionally output a newline. |
| 287 | 291 | ||
| 288 | +++ | 292 | +++ |
diff --git a/lisp/faces.el b/lisp/faces.el index 612bd1677bb..d80a557feb5 100644 --- a/lisp/faces.el +++ b/lisp/faces.el | |||
| @@ -2670,6 +2670,12 @@ It is used for characters of no fonts too." | |||
| 2670 | :version "24.1" | 2670 | :version "24.1" |
| 2671 | :group 'basic-faces) | 2671 | :group 'basic-faces) |
| 2672 | 2672 | ||
| 2673 | (defface read-multiple-choice-face | ||
| 2674 | '((t (:inherit bold))) | ||
| 2675 | "Face for the symbol name in Apropos output." | ||
| 2676 | :group 'basic-faces | ||
| 2677 | :version "25.2") | ||
| 2678 | |||
| 2673 | ;; Faces for TTY menus. | 2679 | ;; Faces for TTY menus. |
| 2674 | (defface tty-menu-enabled-face | 2680 | (defface tty-menu-enabled-face |
| 2675 | '((t | 2681 | '((t |
diff --git a/lisp/subr.el b/lisp/subr.el index c685f95f56f..db1baf09c43 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -2233,6 +2233,120 @@ keyboard-quit events while waiting for a valid input." | |||
| 2233 | (message "%s%s" prompt (char-to-string char)) | 2233 | (message "%s%s" prompt (char-to-string char)) |
| 2234 | char)) | 2234 | char)) |
| 2235 | 2235 | ||
| 2236 | (defun read-multiple-choice (prompt choices) | ||
| 2237 | "Ask user a multiple choice question. | ||
| 2238 | PROMPT should be a string that will be displayed as the prompt. | ||
| 2239 | |||
| 2240 | CHOICES is an alist where the first element in each entry is a | ||
| 2241 | character to be entered, the second element is a short name for | ||
| 2242 | the entry to be displayed while prompting (if there's room, it | ||
| 2243 | might be shortened), and the third, optional entry is a longer | ||
| 2244 | explanation that will be displayed in a help buffer if the user | ||
| 2245 | requests more help. | ||
| 2246 | |||
| 2247 | The return value is the matching entry from the CHOICES list. | ||
| 2248 | |||
| 2249 | Usage example: | ||
| 2250 | |||
| 2251 | \(read-multiple-choice \"Continue connecting?\" | ||
| 2252 | '((?a \"always\") | ||
| 2253 | (?s \"session only\") | ||
| 2254 | (?n \"no\")))" | ||
| 2255 | (let* ((altered-names nil) | ||
| 2256 | (full-prompt | ||
| 2257 | (format | ||
| 2258 | "%s (%s, ?): " | ||
| 2259 | prompt | ||
| 2260 | (mapconcat | ||
| 2261 | (lambda (elem) | ||
| 2262 | (let* ((name (cadr elem)) | ||
| 2263 | (pos (seq-position name (car elem))) | ||
| 2264 | (altered-name | ||
| 2265 | (cond | ||
| 2266 | ;; Not in the name string. | ||
| 2267 | ((not pos) | ||
| 2268 | (format "[%c] %s" (car elem) name)) | ||
| 2269 | ;; The prompt character is in the name, so highlight | ||
| 2270 | ;; it on graphical terminals... | ||
| 2271 | ((display-graphic-p) | ||
| 2272 | (setq name (copy-sequence name)) | ||
| 2273 | (put-text-property pos (1+ pos) | ||
| 2274 | 'face 'read-multiple-choice-face | ||
| 2275 | name) | ||
| 2276 | name) | ||
| 2277 | ;; And put it in [bracket] on non-graphical terminals. | ||
| 2278 | (t | ||
| 2279 | (concat | ||
| 2280 | (substring name 0 pos) | ||
| 2281 | "[" | ||
| 2282 | (upcase (substring name pos (1+ pos))) | ||
| 2283 | "]" | ||
| 2284 | (substring name (1+ pos))))))) | ||
| 2285 | (push (cons (car elem) altered-name) | ||
| 2286 | altered-names) | ||
| 2287 | altered-name)) | ||
| 2288 | choices ", "))) | ||
| 2289 | tchar buf) | ||
| 2290 | (save-window-excursion | ||
| 2291 | (save-excursion | ||
| 2292 | (while (not tchar) | ||
| 2293 | (message "%s" full-prompt) | ||
| 2294 | (setq tchar (condition-case nil | ||
| 2295 | (read-char) | ||
| 2296 | (error nil))) | ||
| 2297 | ;; The user has entered an invalid choice, so display the | ||
| 2298 | ;; help messages. | ||
| 2299 | (when (not (assq tchar choices)) | ||
| 2300 | (setq tchar nil) | ||
| 2301 | (with-help-window (setq buf (get-buffer-create | ||
| 2302 | "*Multiple Choice Help*")) | ||
| 2303 | (with-current-buffer buf | ||
| 2304 | (erase-buffer) | ||
| 2305 | (pop-to-buffer buf) | ||
| 2306 | (insert prompt "\n\n") | ||
| 2307 | (let* ((columns (/ (window-width) 25)) | ||
| 2308 | (fill-column 21) | ||
| 2309 | (times 0) | ||
| 2310 | (start (point))) | ||
| 2311 | (dolist (elem choices) | ||
| 2312 | (goto-char start) | ||
| 2313 | (unless (zerop times) | ||
| 2314 | (if (zerop (mod times columns)) | ||
| 2315 | ;; Go to the next "line". | ||
| 2316 | (goto-char (setq start (point-max))) | ||
| 2317 | ;; Add padding. | ||
| 2318 | (while (not (eobp)) | ||
| 2319 | (end-of-line) | ||
| 2320 | (insert (make-string (- (* (mod times columns) | ||
| 2321 | (+ fill-column 4)) | ||
| 2322 | (current-column)) | ||
| 2323 | ?\s)) | ||
| 2324 | (forward-line 1)))) | ||
| 2325 | (setq times (1+ times)) | ||
| 2326 | (let ((text | ||
| 2327 | (with-temp-buffer | ||
| 2328 | (insert (format | ||
| 2329 | "%c: %s\n" | ||
| 2330 | (car elem) | ||
| 2331 | (cdr (assq (car elem) altered-names)))) | ||
| 2332 | (fill-region (point-min) (point-max)) | ||
| 2333 | (when (nth 2 elem) | ||
| 2334 | (insert (nth 2 elem)) | ||
| 2335 | (unless (bolp) | ||
| 2336 | (insert "\n")) | ||
| 2337 | (fill-region start (point-max))) | ||
| 2338 | (buffer-string)))) | ||
| 2339 | (goto-char start) | ||
| 2340 | (dolist (line (split-string text "\n")) | ||
| 2341 | (end-of-line) | ||
| 2342 | (if (bolp) | ||
| 2343 | (insert line "\n") | ||
| 2344 | (insert line)) | ||
| 2345 | (forward-line 1))))))))))) | ||
| 2346 | (when (buffer-live-p buf) | ||
| 2347 | (kill-buffer buf)) | ||
| 2348 | (assq tchar choices))) | ||
| 2349 | |||
| 2236 | (defun sit-for (seconds &optional nodisp obsolete) | 2350 | (defun sit-for (seconds &optional nodisp obsolete) |
| 2237 | "Redisplay, then wait for SECONDS seconds. Stop when input is available. | 2351 | "Redisplay, then wait for SECONDS seconds. Stop when input is available. |
| 2238 | SECONDS may be a floating-point value. | 2352 | SECONDS may be a floating-point value. |