[net.lang.lisp] Pretty-printer

schuh@geowhiz.UUCP (David Schuh) (03/11/86)

*** REPLACE THIS LINE WITH YOUR MESSAGE ***
	Does anyone have a pretty-printer utility for lisp.  C source or
xlisp or whatever would be appreciated.  Something running under unix
would be nicest because we dont have a script utility.  Also an Xlisp(source)
pp would be nice for my macintosh.

Please mail or post if you feel there is enough interest.

PS. I know I should write my own but I really dont have time, and not
only that but I really dont know the accepted formatting for lisp.


thanks
dave schuh
!uwvax!geowhiz!schuh

roman@sigma.UUCP (Bill Roman) (03/13/86)

In article <384@geowhiz.UUCP> schuh@geowhiz.UUCP (David Schuh) writes:
>	Does anyone have a pretty-printer utility for lisp.  C source or
>xlisp or whatever would be appreciated....   Also an Xlisp(source)
>pp would be nice for my macintosh.

Something out of the depths of my archives... hope this is of
sufficient interest to warrant a reposting.

The original article was:

Mod.sources:  Volume 2, Issue 36
Submitted by: Mike Meyer <ucbvax!ucbjade!ucbopal:mwm>

---------------------------------cut-here------------------------------
;
; a pretty-printer, with hooks for the editor
;

; First, the terminal width and things to manipulate it
(setq pp$terminal-width 79)

(defmacro get-terminal-width nil
  pp$terminal_width)

(defmacro set-terminal-width (new-width)
  (let ((old-width pp$terminal-width))
    (setq pp$terminal-width new-width)
    old-width))
;
; Now, a basic, simple pretty-printer
; pp$pp prints expression, indented to indent-level, assuming that things
; have already been indented to indent-so-far. It *NEVER* leaves the cursor
; on a new line after printing expression. This is to make the recursion
; simpler. This may change in the future, in which case pp$pp could vanish.
;
(defun pp$pp (expression indent-level indent-so-far)
; Step one, make sure we've indented to indent-level
  (dotimes (x (- indent-level indent-so-far)) (princ " "))
; Step two, if it's an atom or it fits just print it
  (cond ((or (not (consp expression))
	     (> (- pp$terminal-width indent-level) (flatsize expression)))
	 (prin1 expression))
; else, print open paren, the car, then each sub expression, then close paren
	(t (princ "(")
	   (pp$pp (car expression) (1+ indent-level) (1+ indent-level))
	   (if (cadr expression)
	       (progn
		 (if (or (consp (car expression))
			 (> (/ (flatsize (car expression)) 3)
			    pp$terminal-width))
		     (progn (terpri)
			    (pp$pp (cadr expression) 
				   (1+ indent-level)
				   0))
		     (pp$pp (cadr expression)
			    (+ 2 indent-level (flatsize (car expression)))
			    (+ 1 indent-level (flatsize (car expression)))))
		 (dolist (current-expression (cddr expression))
			 (terpri)
			 (pp$pp current-expression
				(+ 2 indent-level 
				   (flatsize (car expression)))
				0))))
	   (princ ")")))
  nil)
;
; Now, the thing that outside users should call
; We have to have an interface layer to get the final terpri after pp$pp.
; This also allows hiding the second and third args to pp$pp. Said args
; being required makes the pp recursion loop run faster (don't have to map
; nil's to 0).
;	The where arg to pp is ingnored, as the obvious hack to pp$pp [adding
; an extra arg to every call to a print routine or pp$pp] doesn't work,
; printing nothing when where is nil.
;
(defun pp (expression &optional where)
"Print EXPRESSION on STREAM, prettily"
  (pp$pp expression 0 0)
  (terpri))
-- 
Bill Roman	{ihnp4,decvax,allegra,...}!uw-beaver!tikal!sigma!roman

Summation, Inc.
18702 142nd Ave NE
Woodinville, WA 98072
(206) 486-0991

pollack@uicsl.UUCP (03/17/86)

Here is a minimal recursive pretty-printer translated into XLISP 1.4.
As proof, the function printed itself into this file.
Unfortunately, XLISP threw away all the comments!

Jordan
------------------------------

(defun pp (expr &optional sink indent &aux moreindent newlineflag)
          (or indent (setq indent 0))
          (or sink (setq sink *standard-output*))
          (setq moreindent 0)
          (princ "(" sink)
          (setq indent (1+ indent))
          (do ((tail expr (cdr tail)))
              ((null tail))
              (cond ((atom (car tail))
                     (cond (newlineflag (setq moreindent 0)))
                     (prin1 (car tail)
                      sink)
                     (setq moreindent (+ moreindent 1 (flatc (car tail))))
                     (cond ((cdr tail)
                            (spaces 1 sink)))
                     (setq newlineflag nil))
                    (t (cond (newlineflag (spaces moreindent sink)))
                       (pp (car tail)
                        sink (+ indent moreindent))
                       (cond ((cdr tail)
                              (terpri sink)
                              (spaces indent sink)))
                       (setq newlineflag t))))
          (princ ")" sink)
 nil)

(defun spaces (n &optional sink)
              (or sink (setq sink *standard-output*))
              (dotimes (i n)
                       (princ " " sink)))