prompt-for

2022-07-08

Type safe user input.

Upstream URL

github.com/hyotang666/prompt-for

Author

SATO Shinichi

License

MIT
README

PROMPT-FOR 2.0.0

What is this?

Type safe user input.

Alternatives and differences.

duologueprompt-for
coloring*
completion*
choosing*
email*
url*
datetime*
secretsbcl with unix os only
typesinteger pathnameany-lisp-types
interactstandard-ioquery-io

See also.

Usage

* (prompt-for:prompt-for 'integer "~&Input integer> ")

Input integer> not-integer

NOT-INTEGER is type of SYMBOL, not INTEGER
Input integer> 0
0

For detail, see spec file.

TIPS

PROMPT-FOR is a generic function. If the first argument is a function, it checks user input with it.

* (prompt-for:prompt-for #'evenp "~&Input even integer>> ")

Input even integer>> 1

1 is type of BIT, not satisfies #<FUNCTION EVENP>.
Input even integer>> 2
2

Note that the lambda function will be useless as a message for users when failed.

* (prompt-for:prompt-for (lambda (x) (evenp x)) "~&Input even integer>> ")

Input even integer>> 1

1 is type of BIT, not satisfies #<FUNCTION (LAMBDA (X)) {...}>.

In such a case, the local function may help you.

* (flet ((my-evenp (x) (evenp x)))
    (prompt-for:prompt-for #'my-evenp "~&Input even integer>> "))

Input even integer>> 1

1 is type of BIT, not satisfies #<FUNCTION (FLET MY-EVENP) {...}>.

Note that these examples are in SBCL. Other implementations may prints function in other ways.

If you want maximum portability, or customize the message, you need to use the intermediate object and override method.

(defstruct fun sym)

(defmethod prompt-for:prompt-for ((f fun) &rest args)
  (loop :for input = (progn (apply #'uiop:format! *query-io* args)
                            (read *query-io*))
        :when (funcall (fun-sym f) input)
	  :return input
	:else :do (format *query-io* "~&WTF dude! It does not satisfy ~S!" (fun-sym f))))

* (prompt-for:prompt-for (make-fun :sym 'evenp) "~&Input even integer>> ")

Input even integer>> 1

WTF dude! It does not satisfy EVENP!
Input even integer>>

TIPS

prompt-for returns user input.

* (prompt-for:prompt-for #'find-class "~&Input class name >> ")
Input class name >> stream
STREAM

If you want e.g. stream object rather than a name even if user input is a class name, you can use prompt-for:*default-reader*.

* (let ((prompt-for:*default-reader*
          (lambda (input) (find-class (read input)))))
    (prompt-for:prompt-for t "~&Input class name >> "))
Input class name >> stream
#<SB-PCL:SYSTEM-CLASS COMMON-LISP:STREAM>

From developer

Product's goal

Already?

License

MIT

Tested with

  • SBCL/2.2.4
  • CCL/1.12
  • CLISP/2.49
  • ECL/21.2.1
  • Allegro/10.1
  • CMUCL/21D
  • ABCL/1.9.0

Dependencies (2)

  • jingoh
  • uiop

Dependents (1)

  • GitHub
  • Quicklisp