[cl-typesetting-devel] paragraph macro

Marc Battyani marc.battyani at fractalconcept.com
Sat May 5 21:24:41 UTC 2007


"Cyrus Harmon" <ch-lisp at bobobeach.com> wrote:

> First of all, thanks for cl-typesetting and cl-pdf. After spending  the 
> last year or so wrangling my smarkup package into generating  suitable 
> latex for thinks like the UC thesis package and beamer, I've  decided to 
> bite the bullet and try to add a cl-typesetting backend to  smarkup, 
> noticing, of course, that Francois-Rene Rideau has done  something similar 
> for exscribe.

Great. The more user friendly syntaxes the better!

> What strikes me from playing with cl-typesetting is that the  interface, 
> or at least the parts of it I'm looking at, look more like  a DSL than a 
> library. What I mean by this that the macros for things  like paragraph 
> allow for the following:
>
> (paragraph (:h-align :center :font "Helvetica" :font-size 16 :color  '(0.0 
> 0 0.6))
>            "Table of content")
>
> Which is, of course, nice shorthand and saves the user from typing:
>
> (paragraph '(:h-align :center :font "Helvetica" :font-size 16 :color 
> '(0.0 0 0.6))
>            "Table of content")

Looks like some sarcasm here... :)

> which would allow (but certainly other reasons might prevent this  from 
> being the case) for paragraph to be a function instead of a macro.

There are 2 different issues here: Why is it a macro and why style is not 
evaluated at run-time.

The reason why it's a macro is to be able to put arbitrary lisp code in the 
paragraph generation to write stuff like that:
(paragraph ... (loop for ...) ... (if ...)) you can't do that with a 
function.

Why style is used at compile time is to be able to make optimizations at 
compile time. (more on that at the end)

> But the problem comes in when I try to do something like:
>
> (defparameter *default-paragraph-font*
>   '(:font "Times-Roman" :font-size 12))
>
> (defmethod %render-elt ((tag (eql :p)) contents)
>   (tt::paragraph *default-paragraph-font*
>     (tt:put-string (collect-elements contents))))
>
> Now perhaps I'm just showing my lack of mad macro-skillz. I suppose I 
> could rewrite my code as macros that generate the appropriate forms  but 
> then I start to get lost in nested backquotes. It would seem  easier to 
> have something like this:
>
> (defmacro paragraph2 (style &body body)
>   (with-gensyms (top-margin bottom-margin first-line-indent
>                             new-style restore-style first-indent)
>     `(let* ((,top-margin (getf ,style :top-margin 0))
>             (,bottom-margin (getf ,style :bottom-margin 0))
>             (,first-line-indent (getf ,style :first-line-indent 0))
>             (,new-style (apply #'make-instance 'text-style ,style))
>             (,restore-style (make-restore-style ,new-style))
>             (,first-indent ,first-line-indent))
>        (add-box ,new-style)
>        (use-style ,new-style)
>        (add-box (make-instance 'v-spacing :dy ,top-margin))
>        (unless (zerop ,first-indent)
>          (add-box (make-instance 'h-spacing :dx ,first-indent)))
>        ,@(mapcar 'insert-stuff body)
>        (unless (eq (first (boxes-tail *content*)) :eol)
>          (add-box :eol))
>        (add-box (make-instance 'v-spacing :dy ,bottom-margin))
>        (add-box ,restore-style)
>        (use-style ,restore-style))))

If you want to do something like that, you should at least evaluate style 
only once in case it's not just a constant plist.

> but then perhaps I'm missing the point of why style is not evaluated  in 
> the paragraph macro.
>
> Anyway, I see the argument for the shorthand syntax, but it would be  nice 
> if there were an equivalent form that evaluated its arguments so  that one 
> can build functions that call the typesetting functionality.
>
> It's quite possible that I'm 1) completely missing the point here or  that 
> there are some simple macro tricks that render this point moot,  but if so 
> the point or the tricks are not obvious to me.

OK here is some information on why it is like that.

When I started cl-typesetting I wanted to generate reports and documents in 
web applications. I tried to use TeX but it's almost impossible to do simple 
things like nested tables with TeX. Even with the help of a TeX guru! So I 
decided to make one that could be embedded into Lisp so that I would have 
the access to the full power of Common Lisp rather than some lame weird 
macro language. But then there are 2 possible uses of cl-typesetting. The 
first one which, for now is its primary use is to generate automated 
documents and reports in applications. For this you want to be able to 
compile a maximum of things at compile time so that the doc generation is 
fast. Hence the heavy use of macros, the use of style at compile time, etc. 
The second use which is probably what you want to do is to process a 
document description in some kind of markup language at run time and 
generally one time only. For this you should use the functional API. i.e. 
the functions that are called  by the paragraph macro for instance (add-box, 
put-string, use-type, etc.). As I don't use cl-typesetting in that mode, 
there is probably the need for more high level functions.

Of course, as life is too short to write documentation, all this is probably 
not obvious ;-)

Also I didn't find the time to continue the compilation optimization so for 
instance constant strings should be converted to boxes at compile time 
instead of runtime like it is now.

> Thanks again for cl-typesetting and cl-pdf.

Thanks :)
User friendly text markups are welcome!

BTW there a lot of things I wanted to put in cl-typesetting but never found 
the time to do like named styles, finish the math mode (with a TeX 
compatible syntax), optimize the compilation, improve the typesetting 
engine, etc. So even if I'm not working on it at that moment, that  does not 
mean it's finished ;-)
(Right now, I'm still working more than 100% of my time on my FPGA based 
supercomputer project.)

Marc





More information about the cl-typesetting-devel mailing list