Skip to content

Commit

Permalink
Add :class-lookup option for local extensibility
Browse files Browse the repository at this point in the history
Based off of the fressian API.
  • Loading branch information
gfredericks committed Oct 5, 2015
1 parent 5491c2c commit d87687c
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 2 deletions.
32 changes: 32 additions & 0 deletions src/puget/class_lookup.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
(ns puget.class-lookup
"Class-based lookup, algorithm based on
https://github.com/Datomic/fressian/blob/32a833ba5adce9cd14365ff64b8b42a8569b7916/src/org/fressian/impl/InheritanceLookup.java")

(defn check-base-classes
[m ^Class the-class]
(loop [c (.getSuperclass the-class)]
(when-not (= Object c)
(or (get m c)
(recur (.getSuperclass c))))))

(defn check-base-interfaces
[m ^Class the-class]
(let [possibles (java.util.HashMap.)]
(loop [c the-class]
(when-not (= Object c)
(doseq [itf (.getInterfaces c)]
(when-let [impl (get m itf)]
(.put possibles itf impl)))
(recur (.getSuperclass c))))
(case (.size possibles)
0 nil
1 (first (vals possibles))
(throw (ex-info "More than one interface match for class"
{:class the-class})))))

(defn lookup-impl
[m the-class]
(or (get m the-class)
(check-base-classes m the-class)
(check-base-interfaces m the-class)
(get m Object)))
27 changes: 25 additions & 2 deletions src/puget/printer.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[clojure.string :as str]
[fipp.printer :as fipp]
(puget
[class-lookup :as class-lookup]
[color :as color]
[data :as data]
[order :as order])
Expand Down Expand Up @@ -87,6 +88,7 @@
:map-coll-separator " "
:escape-types nil
:print-fallback nil
:class-lookup nil
:print-meta nil
:print-color false
:color-markup :ansi
Expand All @@ -109,6 +111,14 @@
:class-delimiter [:blue]
:class-name [:bold :blue]}})

(defn add-class-lookup-cache
[opts]
(if-let [class-lookup (:class-lookup opts)]
(assoc opts :cached-class-lookup (memoize
(fn [the-class]
(class-lookup/lookup-impl class-lookup
the-class))))
opts))

(defn merge-options
"Merges maps of printer options, taking care to combine the color scheme
Expand All @@ -122,7 +132,7 @@
"Executes the given expressions with a set of options merged into the current
option map."
[opts & body]
`(binding [*options* (merge-options *options* ~opts)]
`(binding [*options* (add-class-lookup-cache (merge-options *options* ~opts))]
~@body))


Expand Down Expand Up @@ -192,11 +202,16 @@
notation are rendered as tagged literals; others are dispatched on their
`type`."
[value]
(let [class-sym (some-> value class .getName symbol)]
(let [the-class (class value)
class-sym (some-> the-class .getName symbol)]
(cond
(contains? (:escape-types *options*) class-sym)
:default

(let [f (:cached-class-lookup *options*)]
(and f (f the-class)))
::class-lookup-tagged-literal

(satisfies? data/ExtendedNotation value)
::tagged-literal

Expand Down Expand Up @@ -406,6 +421,14 @@
(if (coll? form) :line " ")
(format-doc form)]))

(defmethod format-doc ::class-lookup-tagged-literal
[value]
(let [{:keys [tag form]} (((:cached-class-lookup *options*) (class value)) value)]
[:span
(color-doc :tag (str \# tag))
(if (coll? form) :line " ")
(format-doc form)]))


(defmethod format-doc :default
[value]
Expand Down

0 comments on commit d87687c

Please sign in to comment.