changeset 698: | 96958d3eb5b0 |
parent: | ebe3315b7add |
author: | Richard Westhaver <ellis@rwest.io> |
date: | Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: | -rw-r--r-- |
description: | fixes |
5 | 1 | ;;; std/fmt.lisp --- printer and format utils |
2 | ||
3 | ;;; Code: |
|
291 | 4 | (in-package :std/fmt) |
5 | 5 | |
6 | (defun iprintln (x &optional (n 2) stream) |
|
7 | (println (format nil "~A~A" (make-string n :initial-element #\Space) x) stream)) |
|
8 | ||
9 | (defun printer-status () |
|
10 | (format t ";; *print-array* = ~a~%" *print-array*) |
|
11 | (format t ";; *print-base* = ~a~%" *print-base*) |
|
12 | (format t ";; *print-case* = ~a~%" *print-case*) |
|
13 | (format t ";; *print-circle* = ~a~%" *print-circle*) |
|
14 | (format t ";; *print-escape* = ~a~%" *print-escape*) |
|
15 | (format t ";; *print-gensym* = ~a~%" *print-gensym*) |
|
16 | (format t ";; *print-length* = ~a~%" *print-length*) |
|
17 | (format t ";; *print-level* = ~a~%" *print-level*) |
|
18 | (format t ";; *print-lines* = ~a~%" *print-lines*) |
|
19 | (format t ";; *print-miser-width* = ~a~%" *print-miser-width*) |
|
20 | (format t ";; *print-pprint-dispatch* = ~a~%" *print-pprint-dispatch*) |
|
21 | (format t ";; *print-pretty* = ~a~%" *print-pretty*) |
|
22 | (format t ";; *print-radix* = ~a~%" *print-radix*) |
|
23 | (format t ";; *print-readably* = ~a~%" *print-readably*) |
|
24 | (format t ";; *print-right-margin* = ~a~%" *print-right-margin*)) |
|
25 | ||
685
ebe3315b7add
evdev/kbd fully operational, rustls and blake3 cleanups
Richard Westhaver <ellis@rwest.io>
parents:
291
diff
changeset
|
26 | (defun fmt-row (data &optional stream) |
ebe3315b7add
evdev/kbd fully operational, rustls and blake3 cleanups
Richard Westhaver <ellis@rwest.io>
parents:
291
diff
changeset
|
27 | (format stream "| ~{~A~^ | ~} |~%" data)) |
5 | 28 | |
685
ebe3315b7add
evdev/kbd fully operational, rustls and blake3 cleanups
Richard Westhaver <ellis@rwest.io>
parents:
291
diff
changeset
|
29 | (defun format-sxhash (code &optional stream) |
5 | 30 | "Turn the fixnum value CODE into a human-friendly string. CODE should |
31 | be produced by `sxhash'." |
|
32 | (let (r) |
|
33 | (dotimes (i 8 r) |
|
34 | (push (ldb (byte 8 (* i 8)) code) r)) |
|
35 | (format |
|
685
ebe3315b7add
evdev/kbd fully operational, rustls and blake3 cleanups
Richard Westhaver <ellis@rwest.io>
parents:
291
diff
changeset
|
36 | stream |
5 | 37 | "~{~A~^-~}" |
38 | (mapcar |
|
39 | (lambda (x) (format nil "~{~(~2,'0x~)~}" x)) |
|
40 | (group r 2))))) |
|
41 | ||
282 | 42 | ;;; Trees |
5 | 43 | |
44 | ;; from https://gist.github.com/WetHat/9682b8f70f0241c37cd5d732784d1577 |
|
45 | ||
46 | ;; Example: |
|
47 | ||
48 | ;; (let ((tree '(A B1 B2 (B3 C1) C2))) |
|
49 | ;; ; enumerate all layout options and draw the tree for each one. |
|
50 | ;; (dolist (layout '(:up :centered :down)) |
|
51 | ;; (format t "Layout = :~A~%" layout) |
|
52 | ;; (fmt-tree t tree :layout layout))) |
|
53 | ||
54 | ;; Layout = :UP |
|
55 | ;; ╭─ C2 |
|
56 | ;; │ ╭─ C1 |
|
57 | ;; ├─ B3 |
|
58 | ;; ├─ B2 |
|
59 | ;; ├─ B1 |
|
60 | ;; A |
|
61 | ;; Layout = :CENTERED |
|
62 | ;; ╭─ B2 |
|
63 | ;; ├─ B1 |
|
64 | ;; A |
|
65 | ;; ├─ B3 |
|
66 | ;; │ ╰─ C1 |
|
67 | ;; ╰─ C2 |
|
68 | ;; Layout = :DOWN |
|
69 | ;; A |
|
70 | ;; ├─ B1 |
|
71 | ;; ├─ B2 |
|
72 | ;; ├─ B3 |
|
73 | ;; │ ╰─ C1 |
|
74 | ;; ╰─ C2 |
|
75 | ||
76 | ;; Unicode plain ASCII representation |
|
77 | (defvar *space* " ") |
|
78 | (defvar *upper-knee* " ╭─ ") ; " .- " |
|
79 | (defvar *pipe* " │ ") ; " | " |
|
80 | (defvar *tee* " ├─ ") ; " +- " |
|
81 | (defvar *lower-knee* " ╰─ ") ; " '- " |
|
82 | ||
83 | (defun format-tree-segments (node &key (layout :centered) |
|
84 | (node-formatter #'write-to-string)) |
|
85 | (unless node |
|
86 | (return-from format-tree-segments nil)) ; nothing to do here |
|
87 | (setq node (ensure-cons node)) |
|
88 | (flet ((prefix-node-strings (child-node &key layout node-formatter |
|
89 | (upper-connector *pipe*) |
|
90 | (root-connector *tee*) |
|
91 | (lower-connector *pipe*)) |
|
92 | "A local utility to add connectors to a string representation |
|
93 | of a tree segment to connect it to other tree segments." |
|
94 | (multiple-value-bind (u r l) |
|
95 | (format-tree-segments child-node |
|
96 | :layout layout |
|
97 | :node-formatter node-formatter) |
|
98 | ; prefix tree segment with connector glyphs to connect it to |
|
99 | ; other segments. |
|
100 | (nconc |
|
101 | (mapcar |
|
102 | (lambda (str) (concatenate 'string upper-connector str)) |
|
103 | u) |
|
104 | (list (concatenate 'string root-connector r)) |
|
105 | (mapcar |
|
106 | (lambda (str) (concatenate 'string lower-connector str)) |
|
107 | l))))) |
|
108 | (let* ((children (rest node)) |
|
109 | (pivot (case layout ; the split point of the list of children |
|
110 | (:up (length children)) ; split at top |
|
111 | (:down 0) ; split at bottom |
|
112 | (otherwise (round (/ (length children) 2))))) ; bisect |
|
113 | (upper-children (reverse (subseq children 0 pivot))) ; above root |
|
114 | (lower-children (subseq children pivot))) ; nodes below root |
|
115 | (values ; compile multiple value return of upper-children root lower children |
|
116 | (when upper-children |
|
117 | (loop with top = (prefix-node-strings (first upper-children) |
|
118 | :layout layout |
|
119 | :node-formatter node-formatter |
|
120 | :upper-connector *space* |
|
121 | :root-connector *upper-knee*) ; top node has special connectors |
|
122 | for child-node in (rest upper-children) |
|
123 | nconc (prefix-node-strings child-node |
|
124 | :layout layout |
|
125 | :node-formatter node-formatter) |
|
126 | into strlist |
|
127 | finally (return (nconc top strlist)))) |
|
128 | (let ((root-name (funcall node-formatter (car node)))) ; root node |
|
129 | (if (= 1 (length root-name)) |
|
130 | (concatenate 'string " " root-name) ; at least 2 chars needed |
|
131 | ;else |
|
132 | root-name)) |
|
133 | (when lower-children |
|
134 | (loop for (head . tail) on lower-children |
|
135 | while tail ; omit the last child |
|
136 | nconc (prefix-node-strings head |
|
137 | :layout layout |
|
138 | :node-formatter node-formatter) |
|
139 | into strlist |
|
140 | finally (return |
|
141 | (nconc |
|
142 | strlist |
|
143 | ; bottom node has special connectors |
|
144 | (prefix-node-strings head |
|
145 | :layout layout |
|
146 | :node-formatter node-formatter |
|
147 | :root-connector *lower-knee* |
|
148 | :lower-connector *space*))))))))) |
|
149 | ||
150 | (defun fmt-tree (stream root &key |
|
151 | (plist nil) |
|
152 | (layout :centered) |
|
153 | (node-formatter #'write-to-string)) |
|
154 | (multiple-value-bind (u r l) |
|
155 | (format-tree-segments (if plist (cons (car root) (group (cdr root) 2)) root) |
|
156 | :layout layout |
|
157 | :node-formatter node-formatter) |
|
158 | (format stream "~{~A~%~}" (nconc u (list r) l)))) |