changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate lisp/std/fmt.lisp

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