谁在Funcalls中经过溪流



我正在使用cl-who(通过hunchentoot),到目前为止,我完全成功地,但是我不知道一件事,我的解决方法很丑陋,所以我希望有一个简单的修复。我的Hunchentoot轻松处理程序调用看起来像这样的功能:

(defun foo ()
 (with-html-output-to-string
   (*standard-output* nil :prologue t)
   (:html
    (:body (htm :br :hr "foo" :hr ...etc...))))

一切都很好。

但是,当我想从foo内调用辅助功能以做...无论我想做什么子工作,我都无法弄清楚如何使cl-谁的HTM上下文通过呼叫进行。例如,这很好:

(defun foo ()
  (with-html-output-to-string
   (*standard-output* nil :prologue t)
   (:html
    (:body (htm :br :hr "foo" :hr (bar)))))
(defun bar ()
   (format t "This will show up in the html stream"))

但这不起作用:

(defun bar ()
  (with-html-output-to-string
   (*standard-output* nil :prologue t)
   (htm "This will NOT show up in the html stream")))

(我尝试过各种操纵,无济于事。)

我确定我在做一些简单的事情;必须恢复以在任何子fn中格式化,尤其是。BCS我无法使用方便的HTML宏。

cl-谁基于生成写语句的宏,所有以关键字开头的表单都是自动打印的,以及参数值。其他形式仅评估(例如,副作用),并且不会自动打印。这就是为什么Cl-谁介绍strfmteschtm宏观的 CC_1,强迫打印其论点(不同)。

您的代码:

(defun bar ()
  (with-html-output-to-string
   (*standard-output* nil :prologue t)
   (htm "This will NOT show up in the html stream")))

返回值是字符串,因为您使用的是with-html-output-to-string*standard-output*暂时绑定到一个流,与外部bar不同,只是构建返回到呼叫者的字符串,此处foo。字符串未打印(仅打印在内容位置中的恒定字符串的表格)。

您可以使用str强制撰写返回的生成的HTML,但是恕我直言,最好的选择是直接写入与呼叫者的输出流,而不是构建中间字符串。

直接写入流

基本上,使用with-html-output

  • 我更喜欢不使用*standard-output*,而是仅用于HTML的流。这样可以防止其他库写入HTML页面不希望的内容。您也可以将流传递到每个辅助功能,但在这些情况下更好地使用特殊变量。

  • 让我们使用简单的宏来具有较轻的语法并执行我们自己的惯例。

以下定义了一个软件包,并配置了cl-谁发出HTML5代码。这必须在扩展宏之前完成,因为在宏扩展过程中使用了特殊的变量:

(defpackage :web (:use :cl :cl-who))
(in-package :web)
;; Evaluate before CL-WHO macro are expanded
(eval-when (:compile-toplevel :load-toplevel :execute)
  (setf (html-mode) :html5))

定义我们可以控制的流,默认情况下,当我们 open 流中时(不是当我们定义变量时):

(defvar *html-output* (make-synonym-stream '*standard-output*)
  "Use a dedicated stream variable for html")

另外,定义一个共同的压痕级:

(defvar *indent* 2
  "Default indentation")

有两个宏,一个用于嵌入在辅助功能中的摘要,它们在我们的流中写入,一个用于顶级HTML页面,返回字符串。

(defmacro with-html (&body body)
  "Establish an HTML context (intended for auxiliary functions)."
  `(with-html-output (*html-output* nil :indent *indent*)
     ,@body))
(defmacro with-html-page (&body body)
  "Return an HTML string (intended for top-level pages)."
  `(with-html-output-to-string (*html-output* nil :prologue t :indent *indent*)
     ,@body))

示例用法:

(defun my-section (title)
  (with-html
    (:h1 (esc title))
    (:p "lorem ipsum")))
(defun my-page ()
  (with-html-page
    (my-section "title")))

呼叫(my-page)返回:

"<!DOCTYPE html>
<h1>title
</h1>
<p>lorem ipsum
</p>"

另请参见鲜为人知的https://github.com/ruricolist/spinneret。

我不清楚您要做什么。如果要在"零件"中撰写网页,通过函数,一个页面的产品部分,可以在调用其中一个功能之一时使用str,例如:

(defun f1 ()
  (with-html-output-to-string (*output-string*)
    (:p "some text")))
(defun f2 ()
  (with-html-output-to-string (*output-string*)
       (:body (:p "some other text") (str (f1)))))
(f2)
"<body><p>some other text</p><p>some text</p></body>"

手册:

看起来像(str form)的形式将用(let ((result form)) (when result (princ result s)))

代替

如果您不使用str,则结果不包含在HTML输出中:

(defun f3 ()
  (with-html-output-to-string (*output-string*)
       (:body (:p "some other text") (f1))))
(f3)
"<body><p>some other text</p></body>"

最新更新