#!/usr/bin/env newlisp
;; @module prettyprint-css.lsp
;; @description experimental formatting/colouring for newLISP source
;; @version 0.0.1 of 2007-11-30 13:53:01
;; @author cormullion
; format the text using some simple rules
; restrictions: comments at the end of a line are moved to the next line
; usage
; (context MAIN)
; (load {tokenizer.lsp})
; (Pretty:pretty-output (Tokenize (read-file {source-file.lsp})))
(context 'Pretty)
(set 'depth 0 'tab-width 4 'output-buffer {} 'html-format true)
(define (format-code-element k)
; return list of three strings: startmarkup, element, end markup
(let ((result '())
(code-element-string k)
)
(if (or
(= k "fn" )
(= k "lambda")
(= k "lambda-macro"))
(set 'result (list {} code-element-string {}))
(cond
((= k "'")
(set 'result (list {} code-element-string {})))
(true
(set 'type-number (& 15 (nth 1 (dump (eval-string k)))))
(case type-number
(0 (set 'result (list {} code-element-string {}))) ; nil
(1 (set 'result (list {} code-element-string {}))) ; true
(2 (set 'result (list {} code-element-string {}))) ; int
(3 (set 'result (list {} code-element-string {}))) ; float
(4 (set 'result (list {} code-element-string {}))) ; string
(5 (set 'result (list {} code-element-string {}))) ; sym
(6 (set 'result (list {} code-element-string {}))) ; ctx
(7 (set 'result (list {} code-element-string {}))) ; pri
(8 (set 'result (list {} code-element-string {}))) ; pri
(9 (set 'result (list {} code-element-string {}))) ; pri
(10 (set 'result (list {} code-element-string {}))) ; quote
(11 (set 'result (list {} code-element-string {}))) ; list
(12 (set 'result (list {} code-element-string {}))) ; lambda
(13 (set 'result (list {} code-element-string {}))) ; macro
(14 (set 'result (list {} code-element-string {}))) ; array
(true (set 'result (list {} code-element-string {})))))))
result))
(define (tab)
(dup { } (- (* depth tab-width) 1)))
(define (escape-html txt)
(if txt
(begin
(replace {&} txt {&} 0)
(replace {<} txt {<} 0)
(replace {>} txt {>} 0)))
txt)
(define (output start-markup s end-markup)
; push the string into a buffer
(if html-format
(set 's (string start-markup (escape-html s) end-markup))
(set 's (string s )))
(push s output-buffer -1))
(define (pretty-output list-of-tokens (use-CSS true))
(set 'depth 0 'tab-width 4 'output-buffer {} 'html-format use-CSS)
(dolist (t list-of-tokens)
(set 'type
(first t))
(set 'data
(last t))
(set 'previous-type
(first
(list-of-tokens
(- $idx 1))))
(set 'previous-data
(last
(list-of-tokens
(- $idx 1))))
(cond
((= type "right-paren")
(if (and (= previous-type "comment") (>= depth 1))
(output "" "" ""))
; add right paren to stack of previous
(if (and (= previous-type "right-paren") (>= depth 1))
(output {} {)} {})
(output {} {)} {}))
(if (<= depth 1)
(output "" "\n" "")
(output "" "" ""))
(if (<= depth 0)
(output "" "?" ""))
(dec 'depth)
)
((= type "left-paren" )
; no newline/indent before left paren ...
(if (not
(or
; not after some functions
(find previous-data '("define" "let" "letn" "set" "lambda" "fn" "push" "'" "if" "(" "dolist" "unless" "for" "while" "dotree"))
; not if previous line was a comment
(= previous-type "comment")
(= previous-type "white-space")
; and not if we're following a very short function/operator
(and
(<= (length previous-data) 2)
(= previous-type "code")))
; newline and indent...
(begin
(output "" "\n" "")
(output "" (tab) ""))))
; no space if following left paren or ' or comment
(if (or
(= previous-type "left-paren")
(= previous-data "'" )
(= previous-type "comment")
(= depth 0))
(output "" "" "")
(output "" " " ""))
(output (string {}) {(} {})
(inc 'depth))
((and (= type "comment") (!= data ""))
; newline before comment unless the shebang line
(if (not
(or (starts-with data {#!/usr/bin})
(= previous-type "comment")
(= previous-type "white-space")
))
(output "" "\n" ""))
(if (starts-with data ";;" )
; two or more semicolons, so start at beginning of line
(begin
(output {} data (string {}))
(output {} "\n" {}))
; other comments start indented at current level
(begin
; indent to current level
(if (not (= previous-type "white-space"))
(output "" (tab) ""))
; output the comment
(output {} data (string {}))
; start the next line, and indent to current level again
; ready for next
(output "" (string "\n" (tab)) "")
)))
((= type "code" )
(cond
((= data "'")
(output "" " " "")
(apply output (format-code-element data )))
((= data ":")
(apply output (format-code-element data)))
((or
(= previous-type "left-paren" )
(= previous-data ":" )
(= previous-data "'" ))
(output "" "" "")
(apply output (format-code-element data)))
(true
(output "" " " "")
(apply output (format-code-element data )))))
((= type "braced-string")
(if (not (= previous-type "left-paren"))
(output "" " " ""))
(apply output (list (string {}) data (string {}))))
((= type "quoted-string")
; space before the string/double quote char
(if (not (= previous-type "left-paren"))
(output "" " " ""))
(apply output (list (string {}) data (string {}))))
((= type "bracketed-string" )
; space before
(if (not (= previous-type "left-paren"))
(output "" " " ""))
(apply output (list (string {}) data {})))))
output-buffer
)
; eof