From emailmac at gmail.com Sat May 5 02:26:30 2007
From: emailmac at gmail.com (Mac Chan)
Date: Fri, 4 May 2007 19:26:30 -0700
Subject: [cl-who-devel] semantic for (str NIL) and (esc NIL)
Message-ID: <4877ae640705041926x58627dfbp4ac3cc7dcc90ee08@mail.gmail.com>
Hi all,
This happened to me a couple times where I have a form like this
(with-html
(:html
(:body
(str (get-error-messages)))))
Now if there's no error, (get-error-messages) returns NIL, otherwise
it returns a description of the problem.
This function also serve as a predicate for other code.
But (str (get-error-messages)) actually prints a "NIL" to the browser.
Of course I could replace (str (get-error-messages)) with
(let ((messages (get-error-messages))
(when messages (str messages))))
or
(str (or (get-error-messages) ""))
however it's getting rather verbose.
But the real issue is that the string "NIL" really doesn't make sense
in HTML, XML or JSON.
It's only something that a Lisp programmer would understand.
So I'm purposing to change the substitution of
(str form) => (princ form1 s)
to
(str form) => (let ((#:result form1)) (when #:result (princ #:result s)))
Attached is a diff for this change in case you guys agree that this makes sense.
Thanks,
-- Mac
-------------- next part --------------
diff -r -u cl-who-0.8.1/doc/index.html cl-who-0.8.1patch/doc/index.html
--- cl-who-0.8.1/doc/index.html 2007-04-27 12:09:30.000000000 -0700
+++ cl-who-0.8.1patch/doc/index.html 2007-05-04 18:51:00.000000000 -0700
@@ -400,14 +400,20 @@
A form which is neither a string nor a keyword nor a list beginning with a keyword will be left as is except for the following substitutions:
-
Forms that look like (strform1form*) will be substituted with (princ form1 s). (Note that all forms behind form1 are ignored.)
-
-
(loop for i below 10 do (str i)) => (loop for i below 10 do (princ i s))
+
Forms that look like (strform1form*) will be substituted with
+ (let ((result form1)) (when result (princ result s))).
+ (Note that all forms behind form1 are ignored.)
+
+
(loop for i below 10 do (str i)) =>
+(loop for i below 10 do
+ (let ((#:result i))
+ (when #:result (princ #:result *standard-output*))))
Forms that look like (fmtform*) will be substituted with (format s form*).
(loop for i below 10 do (fmt "~R" i)) => (loop for i below 10 do (format s "~R" i))
-
Forms that look like (escform1form*) will be substituted with (write-string (escape-stringform1) s).
+
Forms that look like (escform1form*) will be substituted with
+ (let ((result form1)) (when result (write-string (escape-string result s)))).
If a form looks like (htmform*) then each of the forms will be subject to the transformation rules we're just describing.
diff -r -u cl-who-0.8.1/who.lisp cl-who-0.8.1patch/who.lisp
--- cl-who-0.8.1/who.lisp 2007-04-27 02:33:42.000000000 -0700
+++ cl-who-0.8.1patch/who.lisp 2007-05-04 18:27:00.000000000 -0700
@@ -373,14 +373,15 @@
(case (first x)
((esc)
;; (ESC form ...) ->
- ;; (WRITE-STRING (ESCAPE-STRING form STREAM))
- (list 'write-string
- (list 'escape-string
- (second x))
- stream))
+ ;; (LET ((RESULT form)) (WHEN RESULT (WRITE-STRING (ESCAPE-STRING RESULT STREAM))))
+ (let ((result (gensym)))
+ `(let ((,result ,(second x)))
+ (when ,result (write-string (escape-string ,result) ,stream)))))
((str)
- ;; (STR form ...) --> (PRINC form STREAM)
- `(princ ,(second x) ,stream))
+ ;; (STR form ...) --> (LET ((RESULT form)) (WHEN RESULT (PRINC RESULT STREAM)))
+ (let ((result (gensym)))
+ `(let ((,result ,(second x)))
+ (when ,result (princ ,result ,stream)))))
((fmt)
;; (FMT form*) --> (FORMAT STREAM form*)
(list* 'format stream (rest x)))))
From yazicivo at ttnet.net.tr Sat May 5 17:21:05 2007
From: yazicivo at ttnet.net.tr (Volkan YAZICI)
Date: Sat, 05 May 2007 20:21:05 +0300
Subject: [cl-who-devel] Re: semantic for (str NIL) and (esc NIL)
In-Reply-To: <4877ae640705041926x58627dfbp4ac3cc7dcc90ee08@mail.gmail.com>
(Mac Chan's message of "Fri\, 4 May 2007 19\:26\:30 -0700")
References: <4877ae640705041926x58627dfbp4ac3cc7dcc90ee08@mail.gmail.com>
Message-ID: <87ps5fp4ou.fsf@ttnet.net.tr>
"Mac Chan" writes:
> But the real issue is that the string "NIL" really doesn't make sense
> in HTML, XML or JSON.
>
> It's only something that a Lisp programmer would understand.
Yes, therefore, IMHO, it's important for a programmer for debugging
purposes. I'm not against the change, but if it would be done, it
should better be controlled by a (yet another annoying) switch.
Regards.
From edi at agharta.de Tue May 8 21:34:19 2007
From: edi at agharta.de (Edi Weitz)
Date: Tue, 08 May 2007 23:34:19 +0200
Subject: [cl-who-devel] New release 0.9.0 (Was: semantic for (str NIL) and
(esc NIL))
In-Reply-To: <4877ae640705041926x58627dfbp4ac3cc7dcc90ee08@mail.gmail.com> (Mac
Chan's message of "Fri, 4 May 2007 19:26:30 -0700")
References: <4877ae640705041926x58627dfbp4ac3cc7dcc90ee08@mail.gmail.com>
Message-ID:
On Fri, 4 May 2007 19:26:30 -0700, "Mac Chan" wrote:
> Attached is a diff for this change in case you guys agree that this
> makes sense.
Yes, I think it makes sense. I've made a new release with your patch
incorporated.
Others, please note that this isn't fully backwards-compatible
although I doubt that serious applications so far relied on the fact
that (STR nil) would produce "NIL" in the output.
Thanks,
Edi.
From ch-tbnl at bobobeach.com Tue May 8 21:38:52 2007
From: ch-tbnl at bobobeach.com (Cyrus Harmon)
Date: Tue, 8 May 2007 14:38:52 -0700
Subject: [cl-who-devel] New release 0.9.0 (Was: semantic for (str NIL) and
(esc NIL))
In-Reply-To:
References: <4877ae640705041926x58627dfbp4ac3cc7dcc90ee08@mail.gmail.com>
Message-ID: <5A30F16A-85BB-49ED-BB8E-142905E03CF3@bobobeach.com>
My only complaint about this, which is a minor one, is that when I
see NIL in my HTML, it's a good sign that I've screwed something up.
Now I won't have that anymore, but that's ok I guess.
Cyrus
On May 8, 2007, at 2:34 PM, Edi Weitz wrote:
> On Fri, 4 May 2007 19:26:30 -0700, "Mac Chan"
> wrote:
>
>> Attached is a diff for this change in case you guys agree that this
>> makes sense.
>
> Yes, I think it makes sense. I've made a new release with your patch
> incorporated.
>
> Others, please note that this isn't fully backwards-compatible
> although I doubt that serious applications so far relied on the fact
> that (STR nil) would produce "NIL" in the output.
>
> Thanks,
> Edi.
> _______________________________________________
> cl-who-devel site list
> cl-who-devel at common-lisp.net
> http://common-lisp.net/mailman/listinfo/cl-who-devel
From scusack at fastmail.com.au Tue May 22 04:03:50 2007
From: scusack at fastmail.com.au (Simon Cusack)
Date: Tue, 22 May 2007 14:03:50 +1000
Subject: [cl-who-devel] escaping attributes question
Message-ID: <1179806630.31395.1191057953@webmail.messagingengine.com>
Hi all,
I have read the syntax and semantics chapter and was just wondering why
values in the attribute position aren't escaped by default? Or is there
something I am missing?
- sim
From emailmac at gmail.com Tue May 22 04:50:12 2007
From: emailmac at gmail.com (Mac Chan)
Date: Mon, 21 May 2007 21:50:12 -0700
Subject: [cl-who-devel] escaping attributes question
In-Reply-To: <1179806630.31395.1191057953@webmail.messagingengine.com>
References: <1179806630.31395.1191057953@webmail.messagingengine.com>
Message-ID: <4877ae640705212150n5b551d3v76efac2fc9a683b0@mail.gmail.com>
On 5/21/07, Simon Cusack wrote:
> I have read the syntax and semantics chapter and was just wondering why
> values in the attribute position aren't escaped by default? Or is there
> something I am missing?
I guess it's the same reason why body text ain't escaped by default,
because the lib can't assume too much about that data that you are
feeding.
In my experience 95% of the time the attribute values are constant
html attributes like :width "100%" or :colspan 2 etc that don't
require escaping.
But your use case might be different.
-- Mac
From scusack at fastmail.com.au Tue May 22 06:02:51 2007
From: scusack at fastmail.com.au (Simon Cusack)
Date: Tue, 22 May 2007 16:02:51 +1000
Subject: [cl-who-devel] escaping attributes question
In-Reply-To: <4877ae640705212150n5b551d3v76efac2fc9a683b0@mail.gmail.com>
References: <1179806630.31395.1191057953@webmail.messagingengine.com>
<4877ae640705212150n5b551d3v76efac2fc9a683b0@mail.gmail.com>
Message-ID: <1179813771.6907.1191067869@webmail.messagingengine.com>
Hi Mac,
>> ----- Original message -----
>> From: "Mac Chan"
>> To: "General interest list about cl-who"
>> Date: Mon, 21 May 2007 21:50:12 -0700
>> Subject: Re: [cl-who-devel] escaping attributes question
>>
>> On 5/21/07, Simon Cusack wrote:
>> > I have read the syntax and semantics chapter and was just wondering why
>> > values in the attribute position aren't escaped by default? Or is there
>> > something I am missing?
>>
>> I guess it's the same reason why body text ain't escaped by default,
>> because the lib can't assume too much about that data that you are
>> feeding.
Values in the attribute position get treated differently to body text
already. They are included in the html stream by default and the
result of lisp forms are emited when used in this position.
It just feels natural to me that it goes the extra step and also
escapes the value so that it is 'safe'.
>> In my experience 95% of the time the attribute values are constant
>> html attributes like :width "100%" or :colspan 2 etc that don't
>> require escaping.
>>
>> But your use case might be different.
>> -- Mac
Well I'm in the unfortunate position where we regularly included the
results of calculations as attributes for a javascript library to hook
into. Something like the following is pretty common.
(defun emit-ajaxy-button (url)
(with-html-output (*html-stream*)
((:input :type :button :onclick (format nil
"javascript:doMyAjaxyThing('~A')" url)) "whatever...")))
It gets pretty messy having to remember which ones to escape all the
time.
I patched my convert-attributes (added calls to escape-string code in
all caps)
to do the following;
(defun convert-attributes (attr-list)
"Helper function for CONVERT-TAG-TO-STRING-LIST which converts the
alist ATTR-LIST of attributes into a list of strings and/or Lisp
forms."
(declare (optimize speed space))
(loop with =var= = (gensym)
with attribute-quote = (string *attribute-quote-char*)
for (attr . val) in attr-list
unless (null val) ;; no attribute at all if VAL is NIL
if (constantp val)
if (and (eq *html-mode* :sgml) (eq val t)) ; special case
for SGML
nconc (list " " (string-downcase attr))
else
nconc (list " "
;; name of attribute
(string-downcase attr)
(format nil "=~C" *attribute-quote-char*)
;; value of attribute
(cond ((stringp val)
;; a string, just use it - this case is
;; actually not necessary because of
;; the last case
(ESCAPE-STRING val))
((eq val t)
;; VAL is T, use attribute's name
(string-downcase attr))
(t
;; constant form, PRINC it -
;; EVAL is OK here because of CONSTANTP
(ESCAPE-STRING (FORMAT NIL "~A" (eval
val)))))
attribute-quote)
end
else
;; do the same things as above but at runtime
nconc (list `(let ((,=var= ,val))
(cond ((null ,=var=))
((eq ,=var= t)
,(case *html-mode*
(:sgml
`(htm ,(format nil " ~A"
(string-downcase
attr))))
;; otherwise default to :xml
mode
(t
`(htm ,(format nil " ~A=~C~A~C"
(string-downcase
attr)
*attribute-quote-char*
(string-downcase
attr)
*attribute-quote-char*)))))
(t
(htm ,(format nil " ~A=~C"
(string-downcase attr)
*attribute-quote-char*)
(STR (ESCAPE-STRING (FORMAT NIL
"~A" ,=var=)))
,attribute-quote)))))))
It seems like a sane thing to do to me but was wondering if I had
missed the CL-WHO way of doing the same thing.
Any comments would be most appreciated.
- sim.
From edi at agharta.de Tue May 22 06:35:58 2007
From: edi at agharta.de (Edi Weitz)
Date: Tue, 22 May 2007 08:35:58 +0200
Subject: [cl-who-devel] escaping attributes question
In-Reply-To: <1179813771.6907.1191067869@webmail.messagingengine.com> (Simon
Cusack's message of "Tue, 22 May 2007 16:02:51 +1000")
References: <1179806630.31395.1191057953@webmail.messagingengine.com>
<4877ae640705212150n5b551d3v76efac2fc9a683b0@mail.gmail.com>
<1179813771.6907.1191067869@webmail.messagingengine.com>
Message-ID:
On Tue, 22 May 2007 16:02:51 +1000, "Simon Cusack" wrote:
> It seems like a sane thing to do to me
Not to me because you never know where the data you feed into the the
macro comes from. It might as well be the case that it is already
escaped. Turning escaping on by default with no means of turning it
off seems very wrong to me.
Cheers,
Edi.
From scusack at fastmail.com.au Tue May 22 07:07:59 2007
From: scusack at fastmail.com.au (Simon Cusack)
Date: Tue, 22 May 2007 17:07:59 +1000
Subject: [cl-who-devel] escaping attributes question
In-Reply-To:
References: <1179806630.31395.1191057953@webmail.messagingengine.com>
<4877ae640705212150n5b551d3v76efac2fc9a683b0@mail.gmail.com>
<1179813771.6907.1191067869@webmail.messagingengine.com>
Message-ID: <1179817679.11649.1191073943@webmail.messagingengine.com>
Hi Edi,
>> ----- Original message -----
>> From: "Edi Weitz"
>> Date: Tue, 22 May 2007 08:35:58 +0200
>> Subject: Re: [cl-who-devel] escaping attributes question
>>
>> On Tue, 22 May 2007 16:02:51 +1000, "Simon Cusack"
>> wrote:
>>
>> > It seems like a sane thing to do to me
>>
>> Not to me because you never know where the data you feed into the the
>> macro comes from. It might as well be the case that it is already
>> escaped. Turning escaping on by default with no means of turning it
>> off seems very wrong to me.
>> Cheers,
>> Edi.
Yeah not being able to control it for special cases is bad.
But you know that all values in the attribute position are always
going to the html output stream and for it to be interpreted properly
it should be escaped.
The decision to always emit to the html stream rather than requiring
an esc, fmt or prn for all attribute values means that the values
being emitted here are already getting special treatment from CL-WHO.
If the default position is a hands off one, then strictly speaking
shouldn't all attribute values them be enclosed in (str ...), etal?
What if it was optional behaviour?
Regards, sim.
From yazicivo at ttnet.net.tr Tue May 22 19:13:58 2007
From: yazicivo at ttnet.net.tr (Volkan YAZICI)
Date: Tue, 22 May 2007 22:13:58 +0300
Subject: [cl-who-devel] MACROLET inside HTM
Message-ID: <87wsz0hds9.fsf@ttnet.net.tr>
Hi,
I've been trying to use MACROLET in HTM with no success:
(with-html-output (*standard-output*)
(:div
(macrolet ((foo (bar) `(:div ,bar)))
(htm
(foo "baz")
(foo "moo")))))
Here's the fully macroexpand result of the above form:
(LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
(PROGN
(WRITE-STRING "
" *STANDARD-OUTPUT*)))
I will be appreciated if anybody would help me to figure out how to
use MACROLET inside HTM bodies.
Regards.
From edi at agharta.de Tue May 22 20:04:43 2007
From: edi at agharta.de (Edi Weitz)
Date: Tue, 22 May 2007 22:04:43 +0200
Subject: [cl-who-devel] escaping attributes question
In-Reply-To: <1179817679.11649.1191073943@webmail.messagingengine.com> (Simon
Cusack's message of "Tue, 22 May 2007 17:07:59 +1000")
References: <1179806630.31395.1191057953@webmail.messagingengine.com>
<4877ae640705212150n5b551d3v76efac2fc9a683b0@mail.gmail.com>
<1179813771.6907.1191067869@webmail.messagingengine.com>
<1179817679.11649.1191073943@webmail.messagingengine.com>
Message-ID:
On Tue, 22 May 2007 17:07:59 +1000, "Simon Cusack" wrote:
> But you know that all values in the attribute position are always
> going to the html output stream and for it to be interpreted
> properly it should be escaped.
>
> The decision to always emit to the html stream rather than requiring
> an esc, fmt or prn for all attribute values means that the values
> being emitted here are already getting special treatment from
> CL-WHO.
>
> If the default position is a hands off one, then strictly speaking
> shouldn't all attribute values them be enclosed in (str ...), etal?
I don't think so. The "evaluation model" (so to say) for the body is
different from the attribute values, because the body can contain
other, nested elements while the attribute values can only be
character content.
From edi at agharta.de Tue May 22 22:10:25 2007
From: edi at agharta.de (Edi Weitz)
Date: Wed, 23 May 2007 00:10:25 +0200
Subject: [cl-who-devel] MACROLET inside HTM
In-Reply-To: <87wsz0hds9.fsf@ttnet.net.tr> (Volkan YAZICI's message of "Tue,
22 May 2007 22:13:58 +0300")
References: <87wsz0hds9.fsf@ttnet.net.tr>
Message-ID:
On Tue, 22 May 2007 22:13:58 +0300, Volkan YAZICI wrote:
> I've been trying to use MACROLET in HTM with no success:
>
> (with-html-output (*standard-output*)
> (:div
> (macrolet ((foo (bar) `(:div ,bar)))
> (htm
> (foo "baz")
> (foo "moo")))))
>
> Here's the fully macroexpand result of the above form:
>
> (LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
> (PROGN
> (WRITE-STRING "
" *STANDARD-OUTPUT*)))
>
> I will be appreciated if anybody would help me to figure out how to
> use MACROLET inside HTM bodies.
You currently can't do that due to the simplistic way CL-WHO expands
the body of WITH-HTML-OUTPUT, and I think there's no easy portable way
to fix that. (Patches welcome, of course.)
You can, however, define your own tags instead:
http://weitz.de/cl-who/#convert-tag-to-string-list
HTH,
Edi.
From scusack at fastmail.com.au Sun May 27 23:41:45 2007
From: scusack at fastmail.com.au (Simon Cusack)
Date: Mon, 28 May 2007 09:41:45 +1000
Subject: [cl-who-devel] convert-tag-to-string-list and *html-empty-tag* bug
maybe :)
Message-ID: <1180309305.29457.1192063515@webmail.messagingengine.com>
Hi,
>From my testing it seems that the default convert-tag-to-string-list
isn't finding the tags in html-empty-tag when it should. It looks like
tag is getting converted to a string but *html-empty-tags* are keywords.
I changed
(member tag *html-empty-tags*)
to
(member tag *html-empty-tags* :test #'string-equal)
and made it happy.
the following test
(in-package :who)
(with-html-output-to-string (blah)
(with-html-output (blah)
(:input :value "test this")
(:div)
(:div "test this")))
Used to produce:
"
test this
"
and now produces;
"
test this
"
From emailmac at gmail.com Mon May 28 03:00:02 2007
From: emailmac at gmail.com (Mac Chan)
Date: Sun, 27 May 2007 20:00:02 -0700
Subject: [cl-who-devel] convert-tag-to-string-list and *html-empty-tag*
bug maybe :)
In-Reply-To: <1180309305.29457.1192063515@webmail.messagingengine.com>
References: <1180309305.29457.1192063515@webmail.messagingengine.com>
Message-ID: <4877ae640705272000n66a9e844ta7b99008b5520602@mail.gmail.com>
Hi Simon,
On 5/27/07, Simon Cusack wrote:
> I changed
> (member tag *html-empty-tags*)
> to
> (member tag *html-empty-tags* :test #'string-equal)
You're right. It was my bad. The patch that I sent in had this bug.
I was too concern about (:div) producing and didn't
manually test the other case.
The browser didn't complain :-(
If I unit test this code I should have caught it. Sorry for the inconvience.
Regards,
-- Mac
From emailmac at gmail.com Mon May 28 04:42:15 2007
From: emailmac at gmail.com (Mac Chan)
Date: Sun, 27 May 2007 21:42:15 -0700
Subject: [cl-who-devel] patch + unit test code (Re: *html-empty-tag* bug)
Message-ID: <4877ae640705272142n38fe7ae5qe52b3e19847da2c4@mail.gmail.com>
Attached is a patch to fix html-empty-tag bug and also some unit test
code to help spotting problems in case there are ignorant people like
me who submit bad code ;-)
Thanks,
-- Mac
-------------- next part --------------
Index: test.lisp
===================================================================
--- test.lisp (revision 0)
+++ test.lisp (revision 0)
@@ -0,0 +1,90 @@
+(in-package #:cl-user)
+
+(defpackage #:cl-who-test
+ (:use #:cl #:cl-who))
+
+(in-package #:cl-who-test)
+
+(defmacro with-html (&body body)
+ `(with-html-output-to-string
+ (*standard-output* nil :prologue nil :indent nil)
+ , at body))
+
+(defmacro test= (result &rest args)
+ `(assert (string= ,result
+ (with-html , at args))))
+
+(defmacro test/= (result &rest args)
+ `(assert (string/= ,result
+ (with-html , at args))))
+
+(format t "~&Start running test...~%")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (setq *downcase-tags-p* t)
+ (setf (html-mode) :xml)
+ (setq *attribute-quote-char* #\')
+ (setq *html-empty-tag-aware-p* t))
+
+(test= "&" (esc "&"))
+(test= "<" (esc "<"))
+(test= ">" (esc ">"))
+(test= "'" (esc "'"))
+(test= """ (esc "\""))
+(test= "✓" (esc (string (code-char #x2713))))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (setf (html-mode) :sgml))
+
+(test= "✓" (esc (string (code-char #x2713))))
+
+(test= ""
+ (:input :type "checkbox" :checked t))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (setf (html-mode) :xml))
+
+(test= ""
+ (:input :type "checkbox" :checked t))
+
+(test= ""
+ (:div))
+
+(test= " "
+ (:br))
+
+(test= ""
+ (:script :src "http://www.yahoo.com/yui.js"))
+
+(defun lookup-author ()
+ (values "Zappa"))
+
+(test= "123456Zappa"
+ (:|Item|
+ (:|ASIN| "123456")
+ (:|Item-Attributes|
+ (:|Author| (str (lookup-author))))))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (setq *downcase-tags-p* nil))
+
+(test= "123456Zappa"
+ (:|Item|
+ (:|ASIN| "123456")
+ (:|Item-Attributes|
+ (:|Author| (str (lookup-author))))))
+
+;; we're generating xml that happens to have these html tags