read-char
不要求你按回车键.例如,
CL-USER> (with-input-from-string (x "hello") (print (read-char x))) #\h
同样,如果您从命令行向 SBCL 发送一些输入,它将在没有换行符的情况下被读取:
$ echo -n hello | sbcl --eval "(print (read-char))" … #\h
阅读和打印后#\h
,SBCL看到了ello
:
* debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING {1002979011}>: The variable ELLO is unbound.
我认为这足以证实它不需要read-char
换行,而是输入的缓冲是问题所在.我认为这是2008年comp.lang.lisp线程中描述的相同问题(或非问题):Re:read-char的问题.用户问:
在使用交互式流(标准输入)时,是否可以使read-char表现得像С中的getch ?在SBCL中,read-char希望"输入"键从REPL取消,在用户按下键盘后,C getchar立即返回.除了REPL之外,可能运行使用read-char和直接控制台访问的代码?
有四个响应(请参阅线程索引以获取所有这些响应).这些解释了为什么观察到这种行为(即,Lisp进程没有从终端获得原始输入,而是缓冲输入). Pascal Bourguignon描述了这个问题,并且通过CLISP处理这个问题的方法(除了通常的好建议之外没有提供太多帮助)关于在SBCL中解决这个问题:
不同之处在于,curses将终端置于原始模式,以便能够一次一个地从键盘接收字符,而不是让终端处于熟化模式,其中unix驱动程序缓冲行并处理退格,以及其他细节.
...
现在,我不知道SBCL,(查看SBCL手册).我只在我的湿件中加载了CLISP的实施说明.在CLISP中,您可以使用EXT:WITH-KEYBOARD宏(而curses的基本输出功能由SCREEN包提供).
Rob Warnock的回复包括一些可能或可能不适用于SBCL的CMUCL解决方法代码:
我曾经为CMUCL编写了以下内容,以便能够在不弄乱终端屏幕的情况下为提示键入单个字符响应的应用程序:
(defun read-char-no-echo-cbreak (&optional (stream *query-io*)) (with-alien ((old (struct termios)) (new (struct termios))) (let ((e0 (unix-tcgetattr 0 old)) (e1 (unix-tcgetattr 0 new)) (bits (logior tty-icanon tty-echo tty-echoe tty-echok tty-echonl))) (declare (ignorable e0 e1)) ;[probably should test for error here] (unwind-protect (progn (setf (slot new 'c-lflag) (logandc2 (slot old 'c-lflag) bits)) (setf (deref (slot new 'c-cc) vmin) 1) (setf (deref (slot new 'c-cc) vtime) 0) (unix-tcsetattr 0 tcsadrain new) (read-char stream)) (unix-tcsetattr 0 tcsadrain old)))))SBCL在这方面可能与CMUCL有很大分歧,但类似的东西应该与SBCL相似.首先查看SB-UNIX或SB-POSIX包......
用户vippstar的响应提供了可能是最便携的解决方案的链接
由于您想要做一些可能无法移植到微控制器上的东西(但是好处是增强的UI),使用非标准库,例如CL-ncurses.