From: John Thingstad
Subject: pretty printing, a lost art?
Date: 
Message-ID: <op.ucwq1yelut4oq5@pandora.alfanett.no>
Just read through the document "XP A Common Lisp Pretty Printing system"  
(http://dspace.mit.edu/handle/1721.1/6503)

Wrote this trivial test:

Given a the factulty of 100 print the digits in groups of 3 seperated by  
space so that they fill the line.
If the number sequence is less than 3 digits like 10! = 3628800 print it  
"003 628  300"

(defpackage :my-user (:use :cl :iterate :split-sequence))
(in-package :my-user)

(defun fact (n)
   (check-type n (integer 0 *))
   (if (< n 2)
     1
     (iter
       (for i from 2 to n)
       (multiplying i))))

(defun print-fact (n)
   (let* ((fact (fact n))
          (fact-string (format nil "~:D" fact))
          (fact-list (split-sequence #\, fact-string)))
     (format t "~&~<~{~3,,,··@A~^~4T~:_~}~:>" (list fact-list))
   (values)))

Ok so
compute fact 10! = 3628300
print it with , separator 362800 = "3,628,300"
split it on , to a list ("3" "628" "300")

Now ~< ... ~:> sais to use the pretty printer (pprint-logical-block).
It opens the list but provides no way to iterate through it.
Thus (list fact-list) is needed to give ~{...~^...~} something to work on.  
(iterate through a list using the bit after ~^ as seperator)
~3,,,··@A sais: 3 - width 3, '0 - fill empty places with 0, @ - right  
allign, princ it
~4T - tab to next width is 4
~:_  - fill to end of line but break on whole triplet

MY-USER 49 > (print-fact 10)
003 628 800

MY-USER 54 > (print-fact 100)
093 326 215 443 944 152 681 699 238 856 266 700 490 715 968 264 381 621  
468 592 963 895 217 599 993 229 915 608
941 463 976 156 518 286 253 697 920 827 223 758 251 185 210 916 864 000  
000 000 000 000 000 000 000

Well particularly readable it isn't but quite powerful.
Anyone else using the pretty printer for printing data?

--------------
John Thingstad

From: Rob Warnock
Subject: Re: pretty printing, a lost art?
Date: 
Message-ID: <mbudnVpUvZKbC8XVnZ2dnUVZ_vudnZ2d@speakeasy.net>
John Thingstad <·······@online.no> wrote:
+---------------
| Just read through the document "XP A Common Lisp Pretty Printing system"  
| (http://dspace.mit.edu/handle/1721.1/6503)
| Wrote this trivial test:
| ...
| MY-USER 54 > (print-fact 100)
| 093 326 215 443 944 152 681 699 238 856 266 700 490 715 968 264 381 621  
| 468 592 963 895 217 599 993 229 915 608
| 941 463 976 156 518 286 253 697 920 827 223 758 251 185 210 916 864 000  
| 000 000 000 000 000 000 000
| 
| Well particularly readable it isn't but quite powerful.
+---------------

Cool!

Hmmm... Some manipulation of *PRINT-RIGHT-MARGIN* [also see
*PRINT-MISER-WIDTH* and/or *PRINT-LENGTH*, in some cases]
might be able to get rid of those annoying short wraps:

    > (let ((*print-right-margin* 40)) ; try for 10 groups per line
	   (print-fact 100))

    093 326 215 443 944 152 681 699 238 856
    266 700 490 715 968 264 381 621 468 592
    963 895 217 599 993 229 915 608 941 463
    976 156 518 286 253 697 920 827 223 758
    251 185 210 916 864 000 000 000 000 000
    000 000 000
    > 

+---------------
| Anyone else using the pretty printer for printing data?
+---------------

I tend to use it a lot for generating C source files,
e.g., this bit clipped from a previous article of mine
<·····································@speakeasy.net> [Sept'07]:

    I use it [the |0X| printing function shown earlier]
    a lot when building data initialization tables in C code:

    > (let ((data (loop for i below 24 nconc (list (random 0x100000000)
                                                   (random 256))))
            (instance "georgey"))
        (format t "~%foo_t ~a_foos[~d] = {~
              ~%~{~<~%~1,68:;  {~/0x/, ~2/0x/}~>~^,~}~%};~%"
              instance (/ (length data) 2) data))

    foo_t georgey_foos[24] = {
      {0x21a41a5c, 0x87},  {0x1c63b86e, 0xb4},  {0x894c25d5, 0xa1},
      {0x9979b7fe, 0xbb},  {0xc2ad44aa, 0x4d},  {0xe2826239, 0x70},
      {0x053b537e, 0x05},  {0x6ac226e8, 0xbe},  {0x1252ea73, 0x20},
      {0xe3001d4a, 0x12},  {0x9a006313, 0x31},  {0x299d2f64, 0x54},
      {0x90feb745, 0xda},  {0xc7ed257b, 0xc1},  {0xa6e8e18a, 0x51},
      {0x0fdb8569, 0xed},  {0x713c27e0, 0xa8},  {0xd975dbac, 0x2d},
      {0xb4263772, 0x85},  {0xe6cdaaa9, 0x48},  {0x7db24d29, 0xf8},
      {0x87e5aa36, 0xa3},  {0xb56e3dd7, 0xe2},  {0x3cf23443, 0x4e}
    };
    NIL
    > 


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Marco Antoniotti
Subject: Re: pretty printing, a lost art?
Date: 
Message-ID: <6abc505f-5001-49b1-a090-c499e112f344@m3g2000hsc.googlegroups.com>
http://www.merl.com/papers/TR93-17/

is always a good start when talking about the Pretty Printer. :)

Cheers
--
Marco





On Jun 18, 6:58 am, ····@rpw3.org (Rob Warnock) wrote:
> John Thingstad <·······@online.no> wrote:
>
> +---------------
> | Just read through the document "XP A Common Lisp Pretty Printing system"  
> | (http://dspace.mit.edu/handle/1721.1/6503)
> | Wrote this trivial test:
> | ...
> | MY-USER 54 > (print-fact 100)
> | 093 326 215 443 944 152 681 699 238 856 266 700 490 715 968 264 381 621  
> | 468 592 963 895 217 599 993 229 915 608
> | 941 463 976 156 518 286 253 697 920 827 223 758 251 185 210 916 864 000  
> | 000 000 000 000 000 000 000
> |
> | Well particularly readable it isn't but quite powerful.
> +---------------
>
> Cool!
>
> Hmmm... Some manipulation of *PRINT-RIGHT-MARGIN* [also see
> *PRINT-MISER-WIDTH* and/or *PRINT-LENGTH*, in some cases]
> might be able to get rid of those annoying short wraps:
>
>     > (let ((*print-right-margin* 40)) ; try for 10 groups per line
>            (print-fact 100))
>
>     093 326 215 443 944 152 681 699 238 856
>     266 700 490 715 968 264 381 621 468 592
>     963 895 217 599 993 229 915 608 941 463
>     976 156 518 286 253 697 920 827 223 758
>     251 185 210 916 864 000 000 000 000 000
>     000 000 000
>     >
>
> +---------------
> | Anyone else using the pretty printer for printing data?
> +---------------
>
> I tend to use it a lot for generating C source files,
> e.g., this bit clipped from a previous article of mine
> <·····································@speakeasy.net> [Sept'07]:
>
>     I use it [the |0X| printing function shown earlier]
>     a lot when building data initialization tables in C code:
>
>     > (let ((data (loop for i below 24 nconc (list (random 0x100000000)
>                                                    (random 256))))
>             (instance "georgey"))
>         (format t "~%foo_t ~a_foos[~d] = {~
>               ~%~{~<~%~1,68:;  {~/0x/, ~2/0x/}~>~^,~}~%};~%"
>               instance (/ (length data) 2) data))
>
>     foo_t georgey_foos[24] = {
>       {0x21a41a5c, 0x87},  {0x1c63b86e, 0xb4},  {0x894c25d5, 0xa1},
>       {0x9979b7fe, 0xbb},  {0xc2ad44aa, 0x4d},  {0xe2826239, 0x70},
>       {0x053b537e, 0x05},  {0x6ac226e8, 0xbe},  {0x1252ea73, 0x20},
>       {0xe3001d4a, 0x12},  {0x9a006313, 0x31},  {0x299d2f64, 0x54},
>       {0x90feb745, 0xda},  {0xc7ed257b, 0xc1},  {0xa6e8e18a, 0x51},
>       {0x0fdb8569, 0xed},  {0x713c27e0, 0xa8},  {0xd975dbac, 0x2d},
>       {0xb4263772, 0x85},  {0xe6cdaaa9, 0x48},  {0x7db24d29, 0xf8},
>       {0x87e5aa36, 0xa3},  {0xb56e3dd7, 0xe2},  {0x3cf23443, 0x4e}
>     };
>     NIL
>     >
>
> -Rob
>
> -----
> Rob Warnock                     <····@rpw3.org>
> 627 26th Avenue                 <URL:http://rpw3.org/>
> San Mateo, CA 94403             (650)572-2607
From: Rob Warnock
Subject: Re: pretty printing, a lost art?
Date: 
Message-ID: <a8udnTsQgMU5bsXVnZ2dnUVZ_srinZ2d@speakeasy.net>
Marco Antoniotti  <·······@gmail.com> wrote:
+---------------
| > John Thingstad <·······@online.no> wrote:
| > +---------------
| > | Just read through the document "XP A Common Lisp Pretty Printing system" 
| > | (http://dspace.mit.edu/handle/1721.1/6503)
...
| http://www.merl.com/papers/TR93-17/
| 
| is always a good start when talking about the Pretty Printer. :)
+---------------

To start with, yes, but there's only about 7 pages on the Pretty Printer
in TR93-17, whereas the one John quoted [which is really AIM-1102,
after you drill down through the DSpace re-org of the AI docs!] has
the full 46-page original "XP" paper.


-Rob

p.s. Of course, TR93-17 *also* has the MACROEXPAND-ALL tutorial...

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: John Thingstad
Subject: Re: pretty printing, a lost art?
Date: 
Message-ID: <op.ucx3g0ufut4oq5@pandora.alfanett.no>
P� Wed, 18 Jun 2008 13:38:12 +0200, skrev Rob Warnock <····@rpw3.org>:

> Marco Antoniotti  <·······@gmail.com> wrote:
> +---------------
> | > John Thingstad <·······@online.no> wrote:
> | > +---------------
> | > | Just read through the document "XP A Common Lisp Pretty Printing  
> system"
> | > | (http://dspace.mit.edu/handle/1721.1/6503)
> ...
> | http://www.merl.com/papers/TR93-17/
> |
> | is always a good start when talking about the Pretty Printer. :)
> +---------------
>
> To start with, yes, but there's only about 7 pages on the Pretty Printer
> in TR93-17, whereas the one John quoted [which is really AIM-1102,
> after you drill down through the DSpace re-org of the AI docs!] has
> the full 46-page original "XP" paper.
>

OPPs just noticed this is AIM-1102 and I was reading AIM-1102A that came  
out a half year later and contains modifications made by demand of the  
ANSI committee.

http://dspace.mit.edu/handle/1721.1/6504

I suggest reading that instead because
1. the #" reader macro isn't defined in CL
2. define-print-dispatch is replaced by set-pprint-dispatch

--------------
John Thingstad
From: Matthew D Swank
Subject: Re: pretty printing, a lost art?
Date: 
Message-ID: <3Dl6k.69$1W4.49@newsfe02.lga>
On Wed, 18 Jun 2008 14:54:26 +0200, John Thingstad wrote:

> På Wed, 18 Jun 2008 13:38:12 +0200, skrev Rob Warnock <····@rpw3.org>:
> 
>> Marco Antoniotti  <·······@gmail.com> wrote: +---------------
>> | > John Thingstad <·······@online.no> wrote: | > +---------------
>> | > | Just read through the document "XP A Common Lisp Pretty Printing
>> system"
>> | > | (http://dspace.mit.edu/handle/1721.1/6503) ...
>> | http://www.merl.com/papers/TR93-17/ |
>> | is always a good start when talking about the Pretty Printer. :)
>> +---------------
>>
>> To start with, yes, but there's only about 7 pages on the Pretty
>> Printer in TR93-17, whereas the one John quoted [which is really
>> AIM-1102, after you drill down through the DSpace re-org of the AI
>> docs!] has the full 46-page original "XP" paper.
>>
>>
> OPPs just noticed this is AIM-1102 and I was reading AIM-1102A that came
> out a half year later and contains modifications made by demand of the
> ANSI committee.
> 
> http://dspace.mit.edu/handle/1721.1/6504
> 

Since it's glossed over in the memo, and was non trivial to dig up (five 
minutes on google instead of two), here is a link to a version of the 
basic algorithm used by XP, authored by Derek C. Oppen.

ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/79/770/CS-TR-79-770.pdf

Matt

-- 
"You do not really understand something unless you can explain it to your 
grandmother." -- Albert Einstein.
From: Matthew D Swank
Subject: Re: pretty printing, a lost art?
Date: 
Message-ID: <Fh_6k.279$c72.77@newsfe05.lga>
On Thu, 19 Jun 2008 04:53:19 +0000, Matthew D Swank wrote:

> On Wed, 18 Jun 2008 14:54:26 +0200, John Thingstad wrote:
> 

...


>> I was reading AIM-1102A that came out a half year later and contains
>> modifications made by demand of
>> the ANSI committee.
>> 
>> http://dspace.mit.edu/handle/1721.1/6504
>> 
>> 
> Since it's glossed over in the memo, and was non trivial to dig up (five
> minutes on google instead of two), here is a link to a version of the
> basic algorithm used by XP, authored by Derek C. Oppen.
> 
> ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/79/770/CS-
TR-79-770.pdf
> 

The ps/pdf of the Oppen paper suffers from some OCR mutilation which can 
be cleared up (for the most part) by looking at gifs of the original 
scans.

http://infolab.stanford.edu/pub/cstr/reports/cs/tr/79/770/

Matt

-- 
"You do not really understand something unless you can explain it to your 
grandmother." -- Albert Einstein.
From: ········@gmail.com
Subject: Re: pretty printing, a lost art?
Date: 
Message-ID: <60443e91-508e-48db-bfff-9e605ec895b8@56g2000hsm.googlegroups.com>
On Jun 17, 2:28 pm, "John Thingstad" <·······@online.no> wrote:

> Anyone else using the pretty printer for printing data?

I use it a lot in my SVG library to produce XML that is at least
a *little* more likely to be readable by humans.  Another thing I've
become fond of is generic functions in ~/ formats.

Because SVG is pretty verbose as it is, by default I want to pull
back on the precision of the many floating point numbers in the
XML attribute values used to describe SVG shapes:

(defmethod pp-xml-value ((s stream) value &optional colon-p at-p)
  (declare (ignore colon-p at-p))
  (format s "~A" value))

(defmethod pp-xml-value ((s stream) (value float) &optional colon-p at-
p)
  (declare (ignore colon-p at-p))
  (format s "~v$" *float-format-precision* value))

With this in place, I can take a property list and yack out *slightly*
more restrained XML properties:

(defun element->xml (stream element properties)
  ;; FORMAT ~/ functions not in CL-USER have to state their package.
  (format
   stream
   "~v,0T<~A ·@<~{~/cl-svg:pp-xml-attr/=\"~/cl-svg:pp-xml-value/\"~^
····@>/>~&"
   *indent-level*
   element
   properties))

So, this
~v,T - tabs out to the appropriate *indentation-level*
·@< ... ··@>  - does nice paragraph filling; it'll keep the
indentation
    in mind, too
~{ ... ~} - looping over the plist
~/pp-xml-attr/ and ~/pp-xml-value/ - filtering property and values as
    needed

Here's the beginning of a huge SVG file with an example of the
resulting
formatting:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewbox="0 0 700 700" width="700" height="700" version="1.1"
id="toplevel"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <radialGradient id="radialGradient2143" cx="50%" cy="50%" r="50%">
      <stop stop-color="rgb(32, 38, 0)" stop-opacity="1.00"
offset="0%"/>
      <stop stop-color="rgb(13, 15, 0)" stop-opacity="1.00"
offset="100%"/>
    </radialGradient>
  </defs>
  <rect x="0" y="0" height="100%" width="100%"
fill="url(#radialGradient2143)"/>
  <g stroke="rgb(114, 204, -152)" fill="rgb(114, 204, -152)"
opacity="1.00"
    stroke-width="3.50" fill-opacity="0.60" stroke-linecap="round">
    <circle cx="358" cy="356" r="14.00" stroke="none" fill="black"/>
    <line x1="350" y1="350" x2="309.84" y2="337.72"/>
    <circle cx="350" cy="350" r="10.50"/>
  </g>

--
wm
From: Daniel Weinreb
Subject: Re: pretty printing, a lost art?
Date: 
Message-ID: <O9N6k.412$fi.114@trnddc03>
John Thingstad wrote:

> 
> Well particularly readable it isn't but quite powerful.
> Anyone else using the pretty printer for printing data?

Yes, mainly because the SLIME environment does pretty-printing
in some places.

Indeed, it's hard to write a very good pretty-printer.  It's
an interesting programming challenge, especially if you want
it to scale up to larger and larger lists without getting
very slow (computational complexity).  I'm going to take
a look at all those papers referenced in this thread, one
of these days.
From: Steven M. Haflich
Subject: Re: pretty printing, a lost art?
Date: 
Message-ID: <5_08k.11077$N87.3451@nlpi068.nbdc.sbc.com>
Daniel Weinreb wrote:
> Indeed, it's hard to write a very good pretty-printer.  It's
> an interesting programming challenge, especially if you want
> it to scale up to larger and larger lists without getting
> very slow (computational complexity).  I'm going to take
> a look at all those papers referenced in this thread, one
> of these days.

Dick Waters' XP, which was adopted basically intact as the pretty 
printer for ANSI CL, has roughly linear performance in the number of 
nodes in the tree.  Can't do much better than that...  I can remember 
using pretty printers in the early 1970's that had worse than O^2 
performance, and basically you don't want to go there.

Waters' solution is very effective, allowing a less-than-optimal 
arrangement of the output, but allowing customized control and, as 
mentioned above, essentially linear execution time.  This is such a 
reasonable tradeoff that since it was adopted by X3J13 I have heard 
essentially zero discussion about how pretty printing should be done.
IIRC Waters' document on XP was reproduced nearly intact in CLtL2, which 
is a good source for understanding it.

To return to the original query in this thread, some time back I wrote 
an XML generator that uses the CL pretty printer.  For most XML 
applications, extra whitespace or even line breaks are a complete waste, 
unless you are a human trying to debug the output.  Pretty printing and 
hierarchical indenting allows generated XML to be read easily, and when 
debugging is finished *print-pretty* can be bound to nil and much of the 
  speed recovered.

Combined with a simple reader macro, the xml generator allowed xml 
generation to be intermixed with lisp code.  For example, the following 
code would do the obvious thing as xhtml:

!(ul (dolist (x list-of-links)  ; alist of uris and text descriptions
        !(li !((a @href (car x)) @(cdr x)))))