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: A problem with read-char。用户问:
工作时是否可以使 read-char 的行为类似于 С 中的 getch
使用交互式流(标准输入)?在 SBCL 中 read-char 想要
"enter" 键从 REPL 中解除挂起,在 C 中 getchar 立即返回
用户按下键盘上的键后。可能可以运行代码
除了 REPL,它使用 read-char 和直接控制台访问?
有四个响应(请参阅thread index 以获取所有响应)。这些解释了为什么观察到这种行为(即,Lisp 进程没有从终端获取原始输入,而是缓冲输入)。 Pascal Bourguignon described the problem,以及一种使用 CLISP 处理此问题的方法(但除了通常的好建议外,并没有提供太多帮助)关于在 SBCL 中解决此问题:
不同之处在于,curses 将终端置于原始模式以能够
一次从键盘接收一个字符,而不是
将终端置于熟模式,unix 驱动程序在此进行缓冲
线条和处理退格,以及其他细节。
…
现在,我不知道 SBCL,(查看 SBCL 的手册)。我只有
我的湿件中加载了 CLISP 的实施说明。在 CLISP 你
可以使用 EXT:WITH-KEYBOARD 宏(而基本输出功能
诅咒由 SCREEN 包提供)。
Rob Warnock's response 包含一些 CMUCL 的变通方法代码,这些代码可能适用于 SBCL,也可能不适用于 SBCL:
我曾经为 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 软件包...
User vippstar's response 提供了可能是最便携的解决方案的链接
由于您想做一些可能无法移植到
微控制器(但好处是更增强的 UI),使用
非标准库,如CL-ncurses。