#!/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