[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to read an integer from the minibuffer

From: Emanuel Berg
Subject: Re: How to read an integer from the minibuffer
Date: Fri, 12 Nov 2021 01:28:32 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux)

Gregory Heytings wrote:

>> Cool (honestly). But do show how to use that to read an
>> integer and only an integer ...
> You mean, how these two answers can be combined?

Nope, I don't like the first solution since it disallows
certain input chars, that feels like the shell would disallow
-j after 'ls' just because there is no such option to ls(1)
... i.e., that doesn't feel good.

This time try it for real:

  (read-number "try enter a string: ")

That's better.

Rather, I meant show how to use the second solution to solve
the OPs example, i.e. to read an integer and only an integer.

> (defun restricted-read-from-minibuffer (prompt regexp &optional allowed-chars)
>   "Read a string from the minibuffer, with additional constraints.
> If the input does not match REGEXP, read a string again.
> If ALLOWED-CHARS is a string, the only allowed characters are those in
> that string."
>   (let ((map nil)
>       (string nil))
>     (when (stringp allowed-chars)
>       (let ((m (make-keymap)))
>       (define-key m [t]
>                   (lambda ()
>                     (interactive)
>                     (message "Character not allowed")))
>       (define-key m (kbd "RET") #'exit-minibuffer)
>       (define-key m (kbd "<return>") #'exit-minibuffer)
>       (define-key m (kbd "C-j") #'exit-minibuffer)
>       (define-key m (kbd "C-g") #'abort-minibuffers)
>       (dolist (c (split-string allowed-chars "" t))
>         (define-key m c #'self-insert-command))
>       (setq map m)))
>     (while (progn
>            (setq string (read-from-minibuffer prompt nil map))
>            (when regexp
>              (unless (string-match regexp string nil t)
>                (message "Unexpected input.")
>                (sit-for 1)
>                t))))
>     string))
> With this,
> (restricted-read-from-minibuffer "Integer? " "^[0-9][0-9]*$" "0123456789")

I get

  if: Wrong number of arguments: string-match, 4

but that's a minor bug I suspect ...

You can also write the integer regexp like below

  (string-match "^[0-9]\\{1,\\}$" "99") ; 0, The Great One
  (string-match "^[0-9]\\{1,\\}$" "88") ; 0, Big Eric

or maybe "^[1-9][0-9]*$" ...

> will read "an integer and only an integer".  And you can wrap
> it into a string-to-number to get the integer itself.
> (BTW, it seems that there's no way in Elisp to "expand"
> a regexp charset, e.g. "[0-9]" into "0123456789".  That would
> make the ALLOWED-CHARS argument easier to type in.)

There is such a package, xr - the reverse of rx, LOL :)

underground experts united

reply via email to

[Prev in Thread] Current Thread [Next in Thread]