|
10 | 10 | (:refer-clojure :exclude [print print-str]) |
11 | 11 | (:import |
12 | 12 | (clojure.core Eduction) |
13 | | - (clojure.lang AFunction Compiler IDeref IPending IPersistentMap |
14 | | - IPersistentSet IPersistentVector IRecord Keyword Symbol |
15 | | - TaggedLiteral Var) |
| 13 | + (clojure.lang AFunction Compiler IDeref IPending IPersistentMap MultiFn |
| 14 | + IPersistentSet IPersistentVector IRecord Keyword Namespace |
| 15 | + Symbol TaggedLiteral Var) |
| 16 | + (java.io Writer) |
16 | 17 | (java.util List Map Map$Entry) |
17 | 18 | (mx.cider.orchard TruncatingStringWriter |
18 | 19 | TruncatingStringWriter$TotalLimitExceeded)) |
|
50 | 51 | (defn- print-coll-item |
51 | 52 | "Print an item in the context of a collection. When printing a map, don't print |
52 | 53 | `[]` characters around map entries." |
53 | | - [^TruncatingStringWriter w, x, map?] |
| 54 | + [^Writer w, x, map?] |
54 | 55 | (if (and map? (instance? Map$Entry x)) |
55 | 56 | (do (print (.getKey ^Map$Entry x) w) |
56 | 57 | (.write w " ") |
|
60 | 61 | (defn- print-coll |
61 | 62 | ([w x sep prefix suffix] |
62 | 63 | (print-coll w x sep prefix suffix false)) |
63 | | - ([^TruncatingStringWriter w, ^Iterable x, ^String sep, ^String prefix, |
| 64 | + ([^Writer w, ^Iterable x, ^String sep, ^String prefix, |
64 | 65 | ^String suffix, map?] |
65 | 66 | (let [level *print-level*] |
66 | 67 | (when-not (nil? level) |
|
89 | 90 | (finally (when-not (nil? level) |
90 | 91 | (set! *print-level* level))))))) |
91 | 92 |
|
92 | | -(defmethod print nil [_ ^TruncatingStringWriter w] |
| 93 | +(defmethod print nil [_ ^Writer w] |
93 | 94 | (.write w "nil")) |
94 | 95 |
|
95 | | -(defmethod print :string [^String x, ^TruncatingStringWriter w] |
| 96 | +(defmethod print :string [^String x, ^Writer w] |
96 | 97 | (let [len (.length x) |
97 | 98 | max-len *max-atom-length* |
98 | 99 | truncate? (and max-len (< max-len len)) |
|
106 | 107 | (.write w "...")) |
107 | 108 | (.append w \"))) |
108 | 109 |
|
109 | | -(defmethod print :scalar [^Object x, ^TruncatingStringWriter w] |
| 110 | +(defmethod print :scalar [^Object x, ^Writer w] |
110 | 111 | (.write w (.toString x))) |
111 | 112 |
|
112 | 113 | (defmethod print :persistent-map [x w] |
|
132 | 133 | (defmethod print :map [^Map x, w] |
133 | 134 | (print-map x w)) |
134 | 135 |
|
135 | | -(defmethod print :record [x, ^TruncatingStringWriter w] |
| 136 | +(defmethod print :record [x, ^Writer w] |
136 | 137 | (.write w "#") |
137 | 138 | (.write w (.getSimpleName (class x))) |
138 | 139 | (print-map x w)) |
139 | 140 |
|
140 | | -(defmethod print :array [x, ^TruncatingStringWriter w] |
| 141 | +(defmethod print :array [x, ^Writer w] |
141 | 142 | (let [ct (.getName (or (.getComponentType (class x)) Object)) |
142 | 143 | as-seq (seq x)] |
143 | 144 | (.write w ct) |
144 | 145 | (if as-seq |
145 | 146 | (print-coll w as-seq ", " "[] {" "}") |
146 | 147 | (.write w "[] {}")))) |
147 | 148 |
|
148 | | -(defmethod print IDeref [^IDeref x, ^TruncatingStringWriter w] |
| 149 | +(defmethod print IDeref [^IDeref x, ^Writer w] |
149 | 150 | (let [pending (and (instance? IPending x) |
150 | 151 | (not (.isRealized ^IPending x))) |
151 | 152 | [ex val] |
152 | 153 | (when-not pending |
153 | 154 | (try [false (deref x)] |
154 | 155 | (catch Throwable e |
155 | | - [true e])))] |
| 156 | + [true e]))) |
| 157 | + full-name (.getName (class x)) |
| 158 | + name (cond (str/starts-with? full-name "clojure.core$future_call") "future" |
| 159 | + (str/starts-with? full-name "clojure.core$promise") "promise" |
| 160 | + :else (str/lower-case (.getSimpleName (class x))))] |
156 | 161 | (.write w "#") |
157 | | - (.write w (.getSimpleName (class x))) |
| 162 | + (.write w name) |
158 | 163 | (print [(cond (or ex |
159 | 164 | (and (instance? clojure.lang.Agent x) |
160 | 165 | (agent-error x))) |
|
168 | 173 | (defmethod print Class [x w] |
169 | 174 | (print-method x w)) |
170 | 175 |
|
171 | | -(defmethod print AFunction [x, ^TruncatingStringWriter w] |
| 176 | +(defmethod print AFunction [x, ^Writer w] |
172 | 177 | (.write w "#function[") |
173 | 178 | (.write w (Compiler/demunge (.getName (class x)))) |
174 | 179 | (.write w "]")) |
175 | 180 |
|
| 181 | +(def ^:private multifn-name-field |
| 182 | + (delay (doto (.getDeclaredField MultiFn "name") |
| 183 | + (.setAccessible true)))) |
| 184 | + |
| 185 | +(defn- multifn-name [^MultiFn mfn] |
| 186 | + (try (.get ^java.lang.reflect.Field @multifn-name-field mfn) |
| 187 | + (catch SecurityException _ "_"))) |
| 188 | + |
| 189 | +(defmethod print MultiFn [x, ^Writer w] |
| 190 | + ;; MultiFn names are not unique so we keep the identity to ensure it's unique. |
| 191 | + (.write w (format "#multifn[%s 0x%x]" |
| 192 | + (multifn-name x) (System/identityHashCode x)))) |
| 193 | + |
176 | 194 | (defmethod print TaggedLiteral [x w] |
177 | 195 | (print-method x w)) |
178 | 196 |
|
179 | | -(defmethod print Throwable [^Throwable x, ^TruncatingStringWriter w] |
180 | | - (.write w "#Error[") |
| 197 | +(defmethod print Namespace [x, ^Writer w] |
| 198 | + (.write w "#namespace[") |
| 199 | + (.write w (str (ns-name x))) |
| 200 | + ;; MultiFn names are not unique so we keep the identity to ensure it's unique. |
| 201 | + (.write w "]")) |
| 202 | + |
| 203 | +(defmethod print Throwable [^Throwable x, ^Writer w] |
| 204 | + (.write w "#error[") |
181 | 205 | (.write w (str (.getName (class x)) " ")) |
182 | 206 | (loop [cause x, msg nil] |
183 | 207 | (if cause |
|
191 | 215 | (print (str first-frame) w)) |
192 | 216 | (.write w "]")) |
193 | 217 |
|
194 | | -(defmethod print :default [^Object x, ^TruncatingStringWriter w] |
| 218 | +(defmethod print :default [^Object x, ^Writer w] |
195 | 219 | (.write w (.toString x))) |
196 | 220 |
|
197 | 221 | (defn print-str |
|
0 commit comments