Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
;; This file: ;; http://anggtwu.net/luatree/lisptree.lisp.html ;; http://anggtwu.net/luatree/lisptree.lisp ;; (find-angg "luatree/lisptree.lisp") ;; Author: Eduardo Ochs <eduardoochs@gmail.com> ;; License: Public Domain ;; Date: 2024oct29 ;; ;; The functions in this library do these conversions, ;; ;; (("f" "__.") f__. ;; ("|" " " "|") | | ;; (f a (g b c)) ==> ("a" " " "g" "__.") ==> a g__. ;; ("|" " " "|") | | ;; ("b" " " "c")) b c ;; ;; Lispy tree ==> lines ==> 2D tree ;; ;; from "Lispy trees" to a "lines object" and then to a "2D tree", ;; that is a string with newlines. ;; ;; They were inspired by this Emacs package: ;; http://anggtwu.net/show-conses.html ;; but here we don't support text properties. ;; ;; This is the inner part of LispTree. ;; The other parts are here: ;; middle: (find-lisptree "lisptree-middle.lisp") ;; outer: (find-lisptree "lisptree.mac") ;; ;; (find-showconses "show-conses.el" "lr") ;; (find-es "lisp" "mapconcat") ;; «.package» (to "package") ;; «.mapconcat» (to "mapconcat") ;; «.demo-lines» (to "demo-lines") ;; «.toplain» (to "toplain") ;; «.width» (to "width") ;; «.pad» (to "pad") ;; «.lr» (to "lr") ;; «.tree» (to "tree") ;; «package» (to ".package") ;; (defpackage :lisptree (:use :common-lisp)) (in-package :lisptree) ;; «mapconcat» (to ".mapconcat") ;; (defvar newline (format nil "~%")) (defun concat (&rest strs) (apply 'concatenate 'string strs)) (defun mapconcat (f as sep) (if (eq () as) "" (let* ((bs (map 'list f as)) (sbs (loop for b in (cdr bs) collect sep collect b)) (bsbs (cons (car bs) sbs))) (apply 'concat bsbs)))) #| * (eepitch-sly) * (eepitch-kill) * (eepitch-sly) (load "lisptree.lisp") (in-package :lisptree) (defun f (o) (format nil "[~a]" o)) (mapconcat #'f '(2 3 4) "_") (mapconcat #'f '(2 3 4) newline) |# ;; «demo-lines» (to ".demo-lines") ;; (find-showconses "show-conses.el" "demo-lines") ;; (defvar demo-lines-1) (setq demo-lines-1 '(("a" "__" "b") ("|") ("c"))) ;; «toplain» (to ".toplain") ;; (find-showconses "show-conses.el" "toplain") ;; (defun toplain-line (line) (apply 'concat line)) (defun toplain-lines (lines) (mapconcat 'toplain-line lines newline)) #| * (eepitch-sly) * (eepitch-kill) * (eepitch-sly) (load "lisptree.lisp") (in-package :lisptree) (toplain-line (car demo-lines-1)) (toplain-lines demo-lines-1) |# ;; «width» (to ".width") ;; (find-showconses "show-conses.el" "width") (defun width-line (line) (length (toplain-line line))) (defun widths-of-lines (lines) (mapcar 'width-line lines)) (defun width-lines (lines) (apply 'max (widths-of-lines lines))) #| * (eepitch-sly) * (eepitch-kill) * (eepitch-sly) (load "lisptree.lisp") (in-package :lisptree) (width-lines demo-lines-1) |# ;; «pad» (to ".pad") ;; (find-showconses "show-conses.el" "pad") (defun pad-line (wtotal line &optional char) "Pad LINE to the width WTOTAL." (let* ((wleft (width-line line)) (wright (- wtotal wleft)) (spaces (make-string wright :initial-element (or char #\ )))) (if (< wleft wtotal) (append line (list spaces)) line))) (defun pad-lines (lines) (let ((maxwidth (width-lines lines))) (loop for line in lines collect (pad-line maxwidth line)))) #| * (eepitch-sly) * (eepitch-kill) * (eepitch-sly) (load "lisptree.lisp") (in-package :lisptree) (pad-lines demo-lines-1) |# ;; «lr» (to ".lr") ;; (defun add-pin (newtopline lines) `(,newtopline ("|") ,@lines)) (defun add-hline (lines &optional wtotal) (setq wtotal (or wtotal (+ 2 (width-lines lines)))) (let* ((topline (car lines)) (otherlines (cdr lines)) (newtopline (pad-line wtotal topline #\_))) `(,newtopline ,@otherlines))) (defun pad-bottom (lines newheight) (let ((currentheight (length lines))) (if (>= currentheight newheight) lines (let ((newlines (make-list (- newheight currentheight) :initial-element ()))) `(,@lines ,@newlines))))) (defun lr (leftlines rightlines) (let* ((leftheight (length leftlines)) (rightheight (length rightlines)) (maxheight (max leftheight rightheight)) (leftlines2 (pad-bottom leftlines maxheight)) (rightlines2 (pad-bottom rightlines maxheight)) (leftlines3 (pad-lines leftlines2))) (loop for l in leftlines3 for r in rightlines2 collect `(,@l ,@r)))) (defun l_r (leftlines rightlines) (let ((leftlines_ (add-hline leftlines))) (lr leftlines_ rightlines))) #| * (eepitch-sly) * (eepitch-kill) * (eepitch-sly) (load "lisptree.lisp") (in-package :lisptree) (defvar demo-lines-2) (setq demo-lines-2 (l_r '(("d")) demo-lines-1)) (toplain-lines demo-lines-2) (princ (toplain-lines demo-lines-2)) (if t 1 2 3) |# ;; «tree» (to ".tree") ;; (defun lispytree-atom (o) "Convert a Lispy tree atom `o' to a lines object." (if (stringp o) `((,o)) `((,(format nil "~s" o))))) (defun lispytree-opargs (op args) "Convert a Lispy tree of the form (op arg1 arg2 ...) to a lines object." (let* ((pin (car (lispytree-atom op))) (nargs (length args))) (if (eq nargs 0) (let* ((down (lispytree-atom " "))) (add-pin pin down)) (let* ((down (lispytree (car args))) (ltree (add-pin pin down))) (if (eq nargs 1) ltree (let ((rtree (lispytree-opargs "." (cdr args)))) (l_r ltree rtree))))))) (defun lispytree (o) "Convert a Lispy tree `o' to a lines object." (if (listp o) (lispytree-opargs (car o) (cdr o)) (lispytree-atom o))) #| * (eepitch-sly) * (eepitch-kill) * (eepitch-sly) (load "lisptree.lisp") (add-pin "*" '()) (lispytree-atom "*") (lispytree-atom " ") (lispytree-opargs "*" '(2 3)) (lispytree-opargs "*" '(2)) (lispytree-opargs "*" '()) (length '(a b c d)) '() () (lispytree 2) (lispytree '(2 3)) (lispytree '(2 3 4)) (lispytree '(2 3 (4 5 6))) (toplain-lines (lispytree '(2 3 (4 5 6)))) (toplain-lines (lispytree '(2 3 (4 5 "6")))) |# ;; Local Variables: ;; coding: utf-8-unix ;; End: