(defun read-line-with-timeout (stream timeout) (let ((deadline (+ (get-internal-real-time) (* timeout internal-time-units-per-second)))) (with-output-to-string (bag) (loop for c = (read-char-no-hang stream nil :eof) until (eql c #\newline) do (case c ((nil) (when (>= (get-internal-real-time) deadline) (return-from read-line-with-timeout :timeout)) (princ ".") (force-output) (sleep 0.5)) ((:eof) (return-from read-line-with-timeout :eof)) (t (princ c bag))))))) ;;(trace read-char-no-hang) ;; ;; NOTE: SBCL as of 2.0.2 will hang in READ-CHAR-NO-HANG, when you ;; type an EOF. ;; (progn (terpri) (write-line ";; I will timeout after 10s, and either return what you said") (write-line ";; or :TIMEOUT, if you're not quick enough, or :EOF on EOF.") (write-line ";;") (write-line ";; A dot is displayed every 1/2s while I wait.") (write-line ";;") (princ "Say something > ") (force-output) (format t "~&;; I got ~S.~%" (read-line-with-timeout *standard-input* 10)) (force-output))