Pretty-printing this map comes out pretty ugly:
{:type :move,
:name :boost,
:from
{:nodeid :plus,
:name :left-operand,
:value
{:args [:result :right-operand],
:f
#object[fargish.workspace_test$fn__159675$fn__159678 0xb3f518f "fargish.workspace_test$fn__159675$fn__159678@b3f518f"]},
:dockclass :input,
:ref [:plus :left-operand]},
:to
{:nodeid :source11,
:name :output,
:value 11,
:dockclass :output,
:ref [:source11 :output]},
:do
#object[fargish.workspace$do_boost 0x179d226e "fargish.workspace$do_boost@179d226e"],
:do-hypothetically
#object[fargish.workspace$do_hypothetical_boost 0x68d6475a "fargish.workspace$do_hypothetical_boost@68d6475a"]}
Most of the time, I don't need to see most of that. I'd like it to look something roughly like this:
#boost{:from [:plus :left-operand] :to [:source11 :output]}
Does Clojure provide a hook to let me insert code so that if the value of a map's :type
key is :move
, str
will call a function I write to generate the string?
I've looked into print-method
. If I understand it correctly, that would extend a multimethod that dispatches on the type of the argument, viz. clojure.lang.PersistentArrayMap, not the :type
of the map. AFAIK, there's no way to "forward" to the previously defined multimethod, or else I could write a print-method
for clojure.lang.PersistentArrayMap that looked at :type
and then called the generic method if its value isn't :move
.
Even just customizing pprint
would be helpful. Theoretically, pprint
is very customizable, but I haven't found documentation that explains how. This is incomplete and suggests that pprint
isn't really done.
Affecting the output of pprint
would be nice but it isn't strictly necessary. Just being able to affect str
and print
would be a great help.
print-method
already looks at the :type
key on the metadata of your object. Just arrange for :type
to be in the metadata rather than (or in addition to) the actual map itself, and you can define your own print-method.
There is a pretty printing package called zprint which you can use that will get you very close to what you want, and still get you the benefits of pretty printing when your output is large and hard to visually comprehend. I've given some examples below:
; Basic zprint pretty-print of a similar map. Note that it orders the keys
; alphabetically
user=> (zprint soq)
{:do #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>,
:do-hypothetically #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>,
:from {:dockclass :input,
:name :left-operand,
:nodeid :plus,
:ref [:plus :left-operand],
:value {:args [:result :right-operand],
:f #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>}},
:name :boost,
:to {:dockclass :output,
:name :output,
:nodeid :source11,
:ref [:source11 :output],
:value 11},
:type :move}
; You can order the keys so the ones you care about come in the order
; you want.
user=> (zprint soq {:map {:key-order [:name :from :to]}})
{:name :boost,
:from {:name :left-operand,
:dockclass :input,
:nodeid :plus,
:ref [:plus :left-operand],
:value {:args [:result :right-operand],
:f #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>}},
:to {:name :output,
:dockclass :output,
:nodeid :source11,
:ref [:source11 :output],
:value 11},
:do #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>,
:do-hypothetically #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>,
:type :move}
; You can get zprint to ignore keys completely
user=> (zprint soq {:map {:key-order [:name :from :to] :key-ignore-silent [[:from :name] :dockclass :nodeid :value :do :do-hypothetically :type [:to :name]]}})
{:name :boost,
:from {:ref [:plus :left-operand]},
:to {:ref [:source11 :output]}}
; You can configure zprint to do this all the time
user=> (zprint.core/set-options! {:map {:key-order [:name :from :to] :key-ignore-silent [[:from :name] :dockclass :nodeid :value :do :do-hypothetically :type [:to :name]]}})
; Now you just zprint it...
user=> (zprint soq)
{:name :boost,
:from {:ref [:plus :left-operand]},
:to {:ref [:source11 :output]}}
You can configure zprint with a ~/.zprintrc
file to do this all the time.
You can also use czprint to get it colored, and you can color the keys any way you want too with a :key-color map. I find this useful when I look at a whole sequence of maps -- changing the color of one key and ordering the keys in the way I want allows me to comprehend a sequence of maps much more easily.
It would be simple to build a function to look at the :type
and then call zprint
with whatever options were appropriate for that type. Of course, the :ref is still in there, but the tradeoff comes when you have a lot of output, and the zprint pretty printing kicks in and it is just easier to read and understand.