8

Q: How, please, can I incorporate a visual seconds counter that will disappear when an option is selected, or when the clock runs out.

Example -- *Messages* buffer

  • You have 10 seconds to make your selction.

  • You have 9 seconds to make your selection.

  • . . .

  • Time's up!

I have a variable that is called init-variable. When non-nil, Emacs loads with a full configuration of various user customizations. When nil, Emacs loads with the equivalent of Emacs -Q -- i.e., no user customizations are loaded. The function read-char-exclusive has a nice feature for a seconds counter, and I've incorporated that feature into the code snippet below. Option number 1 sets the init-variable to nil; option number 2 or no action result in the default setting of non-nil.

(defvar init-variable t)

(let* (
    (emacs-q (read-char-exclusive nil nil 10)))
  (cond
    ((eq emacs-q ?1)
      (setq init-variable nil)
      (message "Emacs -Q"))
    ((eq emacs-q ?2)
      (message "Regular Loading."))
    (t (message "This is the default.")) ))

1 Answer 1

7

From its docstring, I'm guessing that you can't incorporate the countdown message functionality into read-char-exclusive. However, you can wrap it up in your own timer:

(let ((choice nil)
      (count  3))
  (while (>= count 0)
    (message (format "Seconds left to make your choice: %d" count))
    (setq count (if (setq choice (read-char-exclusive nil nil 1))
                    -1
                  (1- count))))
  (cond ((eq choice ?1)
         (message "You entered 1"))
        ((eq choice ?2)
         (message "You entered 2"))
        (t
         (message "The default"))))

Actually, this might be sufficiently useful to wrap it up in a function. Here's a quick sketch that works for a few functions that take the same arguments in the same order (read-char, read-char-exclusive, read-event, and perhaps others) -- extend as you like to do things with read-string and others that take a different argument list:

(defun countdown-read (fnx &optional prompt inherit-input-method seconds)
  "Reads a character or event and provides a countdown of SECONDS
to provide input.  Return nil if no input arrives in time.

FNX is a function that supports the rest of the
arguments (currently, `read-char', `read-char-exclusive',
`read-event', and maybe others).
If the optional argument PROMPT is non-nil, display that as a
prompt.
If the optional argument INHERIT-INPUT-METHOD is non-nil and some
input method is turned on in the current buffer, that input
method is used for reading a character.
If the optional argument SECONDS is non-nil, it should be a
number specifying the maximum number of seconds to wait for
input (default: 5)."
  (let (choice (seconds (or seconds 5)))
    (while (>= seconds 0)
      (message (format (concat (or prompt "") " (%d): ") seconds))
      (setq seconds (if (setq choice
                              (funcall fnx nil inherit-input-method 1))
                        -1
                      (1- seconds))))
    choice))

Using it would look like:

(countdown-read #'read-char-exclusive "Please enter a character" nil 3)
1
  • Yes, that new function will indeed be very useful! Thank you for extending your answer to include it -- greatly appreciated.
    – lawlist
    Commented Nov 16, 2014 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.