我正在用 common lisp 编写一个计时器,输出正在标准输出中显示。我想做的是替换输出,而不打印换行符,也不并排打印,而是覆盖以前的输出,从而产生连续性的错觉。
有没有办法在 common lisp 中做到这一点?
最佳答案
好的,看了大家的评论,我更加明白你的意图了。从您最初的问题来看,我假设您想替换/增强其他代码的输出。但现在我明白了,你真正想要的是更新屏幕。仅使用基于流的 IO 无法完成此操作,您需要其他类型的 IO 库,例如 ncurses。
ncurses 的 Common Lisp 绑定(bind)是系统 cl-charms(在 QuickLisp 中可用)。没有 cl-charms 特定文档,但在 C 中使用 ncurses 的文档几乎可以直接应用。这是您所描述的任务的简单实现,即。它会在屏幕左上角显示一个时钟(持续 10 秒):
(defun clock ()
(charms:initscr)
(charms:clear)
(charms:curs-set 0)
(loop with start = (get-universal-time)
do (multiple-value-bind (s m h) (get-decoded-time)
(charms:mvaddstr 0 0 (format nil "~2,'0d:~2,'0d:~2,'0d" h m s)))
(charms:refresh)
until (>= (- (get-universal-time) start) 10))
(charms:endwin))
我遇到的两个问题:
这只适用于终端,不适用于 Emacs slime-repl 缓冲区。
cl-charms 无法自行找到我安装的curses 库。它正在寻找名为“libcurses.so”或“libncurses.so”的库,但在我的系统上,该库仅存在版本化名称。所以我不得不使用
USE-VALUE
在加载库期间重新启动并提供替代值("libncurses.so.5")
获取库名称列表。为了经常使用该库,您可能应该更改库源代码,并可能向开发人员建议补丁。
从 CLiki 链接的 cl-charms 主页不可用,但存储库位于 http://gitorious.org/cl-charms是。
以下是我在示例中使用的 ncurses/cl-charms 函数的简短说明:
-
initscr
初始化 ncurses。 -
clear
清除屏幕。 -
curs-set
设置光标可见性,0表示不可见。 -
mvaddstr
将光标移动到坐标 y、x 并在那里写入一个字符串,替换之前屏幕上的内容。 -
refresh
使屏幕上的更改实际可见。 -
endwin
是当您完成 ncurses 时要调用的清理函数。
<罢工>
如果我正确理解您要做什么,最好的方法似乎是创建一个新的输出流类(即 fundamental-character-output-stream
的子类,假设您的实现支持灰色流)。您可能应该至少为 stream-write-char
提供专门针对您的类的方法和stream-write-string
.罢工>
然后您可以通过重新定义 *standard-output*
来包装代码到你的类的一个实例,有点像这样:
(let ((*standard-output* (make-instance 'your-stream-class
:target *standard-output*)))
(function-to-be-called-with-wrapped-standard-output))
罢工><罢工>罢工>
关于lisp - 替换/覆盖 Lisp 中的标准输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8631802/