【问题标题】:replacing/overwriting standard-output in lisp在 lisp 中替换/覆盖标准输出
【发布时间】:2012-01-27 17:49:58
【问题描述】:

我正在用普通的 lisp 编写计时器,输出显示在标准输出中。我想要做的是替换输出而不打印换行符,也没有并排打印,而是覆盖以前的输出,所以会有连续性的错觉。

在 common lisp 中有没有办法做到这一点?

【问题讨论】:

  • 标准输出是什么?一份文件?网络连接?终端?什么样的终端?

标签: lisp overwrite


【解决方案1】:

好的,看完了cmets,我更了解你的意图了。从你原来的问题,我假设你想替换/增加一些其他代码的输出。但现在我明白了,您真正想要的是更新屏幕。这不能仅使用基于流的 IO 来完成,您需要一些其他类型的 IO 库,例如 ncurses。

用于 ncurses 的 Common Lisp 绑定是系统 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-charstream-write-string 提供专门为您的班级提供的方法。

然后您可以将带有 *standard-output* 重定义的代码包装到您的类的实例中,有点像这样:

(let ((*standard-output* (make-instance 'your-stream-class
                                        :target *standard-output*)))
  (function-to-be-called-with-wrapped-standard-output))

【讨论】:

  • 我对 lisp 类非常陌生,从未使用过 CLOS,只关注函数式方法。有什么资源可以让我了解您的方法吗?
  • 如果您更具体地描述了您想要做什么,我可能会对如何在没有 CLOS 的情况下做到这一点有所了解。但是如果你想尝试这种方法,你绝对应该了解 CLOS,例如 Practical Common Lisp (gigamonkeys.com/book) 的第 16 和 17 章。之后,您可以查阅有关 Gray Streams 的实施文档。
  • 所以我试图让计时器显示如下内容: 0:hours 0:minutes 11:seconds 。然后继续显示 0:小时 0:分钟 12:秒,依此类推.. 但在前一个显示的同一空间上,而不是在另一行上,或并排等。我在 python 中做了这个当我写一个 Life 模拟器,通过在循环构造的每次传递后在 bash 中调用 clear screen。
  • 好吧,你可以用 Lisp 做同样的事情(在 bash 中清除屏幕)。你必须从 bash 运行你的 Lisp 脚本(就像在 python 中一样)。在 SBCL 中,clear 的外壳将如下所示:(sb-ext:run-program "clear" '() :search t :output t)
  • 是的,但现在我只是想替换递增的整数,而不是整行。这只会让它在 bash 中工作。我正在尝试找到一个更通用的解决方案(如果存在的话)。
猜你喜欢
  • 2010-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多