cl-who 在函数调用中传递流
cl-who passing stream in funcalls
我正在使用 cl-who(通过 hunchentoot),到目前为止完全成功,但有一件事我想不通,而且我的解决方法很糟糕,所以我希望有一个简单的修复方法.我的 hunchentoot easy handlers 调用的函数看起来像这样:
(defun foo ()
(with-html-output-to-string
(*standard-output* nil :prologue t)
(:html
(:body (htm :br :hr "foo" :hr ...etc...))))
一切都很好。
但是,当我想从 foo 中调用辅助函数以执行...无论我想执行什么子工作时,我无法弄清楚如何让 CL-WHO 的 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")))
(我尝试过各种操作,但无济于事。)
我确定我做错了一些简单的事情;必须在任何 subfn 中恢复格式 t 是非常丑陋的,尤其是。 bcs 我不能使用 cl-who 方便的 html 宏。
我不清楚你想做什么。如果你想将网页分成“片段”,通过函数生成页面的各个部分,你可以在调用其中一个函数时使用 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>"
来自manual:
Forms that look like (str form)
will be substituted with (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>"
CL-WHO 基于生成写入语句的宏,自动打印所有以关键字开头的表格,以及参数值。其他形式仅被评估(例如,副作用),并且不会自动打印。这就是为什么 CL-WHO 引入了 str
、fmt
、esc
和 htm
macrolets,强制打印他们的论点(不同)。
您的代码:
(defun bar ()
(with-html-output-to-string
(*standard-output* nil :prologue t)
(htm "This will NOT show up in the html stream")))
return 值是一个字符串,因为您使用的是 with-html-output-to-string
。 *standard-output*
临时绑定到一个流,与外部 bar
不同,只是为了构建一个 returned 给调用者的字符串,这里是 foo
。
不打印字符串(只打印内容位置为常量字符串的形式)。
您可以使用 str
强制写入 returned 生成的 HTML,但恕我直言,最好的选择是直接写入与调用者相同的输出流,而不是构建中间字符串。
直接写入流
基本上,使用with-html-output
:
我不喜欢使用*standard-output*
,而是只用于html的流。这可以防止其他库向 HTML 页面写入任何不需要的内容。您也可以将流向下传递给每个辅助函数,但在这些情况下最好使用特殊变量。
让我们使用简单的宏来简化语法并强制执行我们自己的约定。
下面定义了一个包并配置 CL-WHO 以发出 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))
定义一个我们可以控制的流,当我们打开流(而不是当我们定义变量时)时,默认绑定到*standard-output*
绑定的任何东西:
(defvar *html-output* (make-synonym-stream '*standard-output*)
"Use a dedicated stream variable for html")
此外,定义一个通用的缩进级别:
(defvar *indent* 2
"Default indentation")
有两个宏,一个用于辅助函数中嵌入的片段,写入我们的流中,另一个用于顶级html页面,其中return一个字符串。
(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)
returns:
"<!DOCTYPE html>
<h1>title
</h1>
<p>lorem ipsum
</p>"
我正在使用 cl-who(通过 hunchentoot),到目前为止完全成功,但有一件事我想不通,而且我的解决方法很糟糕,所以我希望有一个简单的修复方法.我的 hunchentoot easy handlers 调用的函数看起来像这样:
(defun foo ()
(with-html-output-to-string
(*standard-output* nil :prologue t)
(:html
(:body (htm :br :hr "foo" :hr ...etc...))))
一切都很好。
但是,当我想从 foo 中调用辅助函数以执行...无论我想执行什么子工作时,我无法弄清楚如何让 CL-WHO 的 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")))
(我尝试过各种操作,但无济于事。)
我确定我做错了一些简单的事情;必须在任何 subfn 中恢复格式 t 是非常丑陋的,尤其是。 bcs 我不能使用 cl-who 方便的 html 宏。
我不清楚你想做什么。如果你想将网页分成“片段”,通过函数生成页面的各个部分,你可以在调用其中一个函数时使用 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>"
来自manual:
Forms that look like
(str form)
will be substituted with(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>"
CL-WHO 基于生成写入语句的宏,自动打印所有以关键字开头的表格,以及参数值。其他形式仅被评估(例如,副作用),并且不会自动打印。这就是为什么 CL-WHO 引入了 str
、fmt
、esc
和 htm
macrolets,强制打印他们的论点(不同)。
您的代码:
(defun bar ()
(with-html-output-to-string
(*standard-output* nil :prologue t)
(htm "This will NOT show up in the html stream")))
return 值是一个字符串,因为您使用的是 with-html-output-to-string
。 *standard-output*
临时绑定到一个流,与外部 bar
不同,只是为了构建一个 returned 给调用者的字符串,这里是 foo
。
不打印字符串(只打印内容位置为常量字符串的形式)。
您可以使用 str
强制写入 returned 生成的 HTML,但恕我直言,最好的选择是直接写入与调用者相同的输出流,而不是构建中间字符串。
直接写入流
基本上,使用with-html-output
:
我不喜欢使用
*standard-output*
,而是只用于html的流。这可以防止其他库向 HTML 页面写入任何不需要的内容。您也可以将流向下传递给每个辅助函数,但在这些情况下最好使用特殊变量。让我们使用简单的宏来简化语法并强制执行我们自己的约定。
下面定义了一个包并配置 CL-WHO 以发出 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))
定义一个我们可以控制的流,当我们打开流(而不是当我们定义变量时)时,默认绑定到*standard-output*
绑定的任何东西:
(defvar *html-output* (make-synonym-stream '*standard-output*)
"Use a dedicated stream variable for html")
此外,定义一个通用的缩进级别:
(defvar *indent* 2
"Default indentation")
有两个宏,一个用于辅助函数中嵌入的片段,写入我们的流中,另一个用于顶级html页面,其中return一个字符串。
(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)
returns:
"<!DOCTYPE html>
<h1>title
</h1>
<p>lorem ipsum
</p>"