Discussion:
Macros for outlining
J. K. Cunningham
2010-03-28 20:10:53 UTC
Permalink
I've been playing around with a way to partially automate writing
outline-based pages and run into something I don't know how to do. I'm
hoping someone can perhaps offer a solution or point me in the right
direction. I've reduced the scope to a fairly simple situation which
might seem unmotivated in this form. But if I can find a way to do this,
the rest of what I'm doing will fall into place.

I'd like to be able to write code that looks like this (example):


(let ((hform "A Title"))
(with-html-output (*standard-output* nil :indent 0)
(section (hform)
(:p "A paragraph can go here. ")
(section ("A Subtitle")
"Subsection text goes here."))
(section ("Second Title")
"Any cl-who syntax input here:"
(:ol (:li "Item 1")
(:li "Item 2")))))


where SECTION would be a macro so that it can take CL-WHO syntax
arguments. The idea is that the SECTION macro would expand so that I
ended up effectively with this:


(let ((form "A Title"))
(with-html-output (*standard-output* nil :indent 0)
(:h1 (str form))
(:p "A paragraph can go here. ")
(:h2 "A Subtitle")
"Subsection text goes here."
(:h1 "Second Title")
"Any cl-who syntax input here:"
(:ol (:li "Item 1")
(:li "Item 2"))))


I came up with a helper macro like this to handle the levels as a
variable:


(defmacro hn (level &body body)
``(,(intern (format nil "H~d" ,level) :keyword)
,,@body))

(let ((lvl 2)
(title "A Title"))
(with-html-output (*standard-output*)
(str (hn lvl (:b (str title))))))

;; => <h2><b>A Title</b></h2>


This enables me to write code that looks like this:


(defmacro section ((n &rest heading) &body body)
`(str (with-html-output-to-string (s nil :indent 0)
(str (hn ,n ,@heading))
(str (with-html ,@body)))))

(let ((lvl 1)
(form "A Title"))
(with-html-output (*standard-output* nil :indent 0)
(section (lvl form)
(:p "A paragraph can go here. ")
(section ((1+ lvl) "A Subtitle")
"Subsection text goes here."))
(section (lvl "Second Title")
"Any cl-who syntax input here:"
(:ol (:li "Item 1")
(:li "Item 2")))))


But this leaves me with having to manage the levels manually. What I
can't figure out how to do is write the SECTION macro so it doesn't
require the LVL arguments, incrementing them recursively.

If it could be written as a function, I could use a closure that started
at LVL = 1 and incremented at each level, but I'm not good enough with
macros to see how to do this.


I'm probably looking at this the wrong way. Does anyone have any ideas how to go about this?

Regards,
Jeff Cunningham
Vsevolod Dyomkin
2010-03-28 21:21:50 UTC
Permalink
See this:
http://common-lisp.net/pipermail/cl-who-devel/2010-February/000421.html

Best regards,
Vsevolod

On Sun, Mar 28, 2010 at 11:10 PM, J. K. Cunningham <
Post by J. K. Cunningham
I've been playing around with a way to partially automate writing
outline-based pages and run into something I don't know how to do. I'm
hoping someone can perhaps offer a solution or point me in the right
direction. I've reduced the scope to a fairly simple situation which might
seem unmotivated in this form. But if I can find a way to do this, the rest
of what I'm doing will fall into place.
(let ((hform "A Title")) (with-html-output (*standard-output* nil :indent 0) (section (hform) (:p "A paragraph can go here. ") (section ("A Subtitle") "Subsection text goes here.")) (section ("Second Title") "Any cl-who syntax input here:" (:ol (:li "Item 1") (:li "Item 2")))))
where SECTION would be a macro so that it can take CL-WHO syntax arguments.
The idea is that the SECTION macro would expand so that I ended up
(let ((form "A Title")) (with-html-output (*standard-output* nil :indent 0) (:h1 (str form)) (:p "A paragraph can go here. ") (:h2 "A Subtitle") "Subsection text goes here." (:h1 "Second Title") "Any cl-who syntax input here:" (:ol (:li "Item 1") (:li "Item 2"))))
(let ((lvl 2) (title "A Title")) (with-html-output (*standard-output*) (str (hn lvl (:b (str title))))))
;; => <h2><b>A Title</b></h2>
(let ((lvl 1) (form "A Title")) (with-html-output (*standard-output* nil :indent 0) (section (lvl form) (:p "A paragraph can go here. ") (section ((1+ lvl) "A Subtitle") "Subsection text goes here.")) (section (lvl "Second Title") "Any cl-who syntax input here:" (:ol (:li "Item 1") (:li "Item 2")))))
But this leaves me with having to manage the levels manually. What I can't
figure out how to do is write the SECTION macro so it doesn't require the
LVL arguments, incrementing them recursively.
If it could be written as a function, I could use a closure that started at
LVL = 1 and incremented at each level, but I'm not good enough with macros
to see how to do this.
I'm probably looking at this the wrong way. Does anyone have any ideas how to go about this?
Regards,
Jeff Cunningham
_______________________________________________
cl-who-devel site list
http://common-lisp.net/mailman/listinfo/cl-who-devel
--
vsevolod
J. K. Cunningham
2010-03-28 21:52:55 UTC
Permalink
See
this: http://common-lisp.net/pipermail/cl-who-devel/2010-February/000421.html
I have taken a look at your macro enhancements, Vsevolod, but haven't
yet found a way to use them here. Can you be more specific?

Regards,
Jeff

Loading...