@cgrand any reason why you used (System/identityHashCode x)
and not (hash x)
in https://github.com/cgrand/unrepl/blob/master/src/unrepl/print.clj#L103
ah nvm .. its for Object
Yes I wanted identity and a bad hash
may never return
So I changed my mind on how to plug log libs in: unrepl exposes two functions and the client (repl frontend not user) has to create an appender on top of that
I started writing the custom object printer that would be equivalent to the thing that makes the js/console
work
@thheller whatโs missing?
nothing really, just exploring a different approach
I hate *print-length*
.. that is pretty much it
but what I want expects a rich GUI, so the output is not strictly human-readable edn-ish
ie. printing {:foo ["hello" 1 'two (list 1 2 3) #{1 2 3}]}
produces
[:collection
{:type :map}
[:entry
{}
[:named {:type :keyword} nil "foo"]
[:ref
{:id -994784545}
[:span {:type :list} "clojure.lang.PersistentVector [count: 5]"]]]]
so its hiccup-like markup
you can then use the :ref
id to get the "body" of the ref -994784545
which would be
[:collection
{:type :vector}
[:entry {} [:number 0] [:string "hello"]]
[:entry {} [:number 1] [:number 1]]
[:entry {} [:number 2] [:named {:type :symbol} nil "two"]]
[:entry
{}
[:number 3]
[:ref
{:id 736442005}
[:span {:type :list} "clojure.lang.PersistentList [count: 3]"]]]
[:entry
{}
[:number 4]
[:ref
{:id 439094965}
[:span {:type :list} "clojure.lang.PersistentHashSet [count: 3]"]]]]
and so on
so it always only prints one value and leaves references for you to get later
[:collection props entry-1 entry-2 ...]
[:entry props key value]
keywords, symbols are [:named props namespace name]
it is basically what the js/console
custom formatters do
A link to these custom formatters?
https://docs.google.com/document/d/1FTascZXT9cxfetuPRT2eXPQKXui4nWFivUnS_335T3U/preview
with my impl https://github.com/thheller/shadow-devtools/blob/master/src/main/shadow/cljs/devtools/client/console.cljs for js
meanwhile in a repl:
user=> (unrepl.repl/start)
[:unrepl/hello {:session :session474, :actions {:exit (unrepl.repl/exit! :session474), :log-eval (clojure.core/some-> :session474 unrepl.repl/session :log-eval), :log-all (clojure.core/some-> :session474 unrepl.repl/session :log-all), :set-source (unrepl.repl/set-file-line-col :session474 <#C4C63FWP5|unrepl>/param :unrepl/sourcename <#C4C63FWP5|unrepl>/param :unrepl/line <#C4C63FWP5|unrepl>/param :unrepl/column)}}]
[:prompt {:file "unrepl-session", :line 1, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user, clojure.core/*warn-on-reflection* false}]
[:prompt {:file "unrepl-session", :line 2, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user, clojure.core/*warn-on-reflection* false}]
(def log (let [w (clojure.core/some-> :session474 unrepl.repl/session :log-eval)] (fn [& args] (into [:trace (-> *ns* ns-name name) (java.util.Date.)] args))))
[:echo {:from [2 1], :to [3 1]} 1]
[:started-eval {:actions {:interrupt (unrepl.repl/interrupt! :session474 1), :background (unrepl.repl/background! :session474 1)}} 1]
[:eval <#C4C63FWP5|unrepl>/object [#unrepl.java/class clojure.lang.Var "0x27b6fd39" {:unrepl.ref/status :ready, :unrepl.ref/val <#C4C63FWP5|unrepl>/object [#unrepl.java/class user$fn__477$fn__479 "0x628a2e2d" "user$fn__477$fn__479@628a2e2d"]}] 1]
[:prompt {:file "unrepl-session", :line 3, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user, clojure.core/*warn-on-reflection* false}]
So we defined user/log
and we are going to use it:
(log "hello" :thheller {:foo 42} (range))
[:echo {:from [4 1], :to [5 1]} 3]
[:started-eval {:actions {:interrupt (unrepl.repl/interrupt! :session474 3), :background (unrepl.repl/background! :session474 3)}} 3]
[:eval [:trace "user" <#C4C63FWP5|unrepl>/object [#unrepl.java/class java.util.Date "0x7ae3e597" "Tue Apr 04 13:44:08 CEST 2017"] "hello" :thheller {:foo 42} (0 1 2 3 4 5 6 7 8 9 <#C4C63FWP5|unrepl>/... {:get (unrepl.repl/fetch :G__486)})] 3]
[:prompt {:file "unrepl-session", :line 5, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user, clojure.core/*warn-on-reflection* false}]
hmm oops a bug
so the custom formatters have the concept of a header and a body
header is basically the "short" version
[:span {:type :list} "clojure.lang.PersistentList [count: 3]"]
this is the header
ooops should not be :span
๐
anyways
but the body is the [:collection ...]
ok, without forgetting the call to the logger:
(def log (let [w (clojure.core/some-> :session474 unrepl.repl/session :log-eval)] (fn [& args] (w (into [:trace (-> *ns* ns-name name) (java.util.Date.)] args)))))
[:echo {:from [5 1], :to [6 1]} 4]
[:started-eval {:actions {:interrupt (unrepl.repl/interrupt! :session474 4), :background (unrepl.repl/background! :session474 4)}} 4]
[:eval <#C4C63FWP5|unrepl>/object [#unrepl.java/class clojure.lang.Var "0x27b6fd39" {:unrepl.ref/status :ready, :unrepl.ref/val <#C4C63FWP5|unrepl>/object [#unrepl.java/class user$fn__487$fn__489 "0x7b3d57bf" "user$fn__487$fn__489@7b3d57bf"]}] 4]
[:prompt {:file "unrepl-session", :line 6, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user, clojure.core/*warn-on-reflection* false}]
user/log
ise defined
(log "hello" :thheller {:foo 42} (range))
[:echo {:from [6 1], :to [7 1]} 5]
[:started-eval {:actions {:interrupt (unrepl.repl/interrupt! :session474 5), :background (unrepl.repl/background! :session474 5)}} 5]
[:log [:trace "user" <#C4C63FWP5|unrepl>/object [#unrepl.java/class java.util.Date "0x1f892f92" "Tue Apr 04 13:48:42 CEST 2017"] "hello" :thheller {:foo 42} (0 1 2 3 4 5 6 7 8 9 <#C4C63FWP5|unrepl>/... {:get (unrepl.repl/fetch :G__494)})] 5]
[:eval nil 5]
thanks for the link
the problem I have with the normal print is that it still can get too long
even with *print-length*
10 or so
case in point: the cljs.anaylzer AST ๐
set everything to 1 (length & depth)
itโs not because you get too much that you have to display it
hmm yeah dunno .. your print is probably better since it is still somewhat readable without a tool
I documented how to hook up unrepl browseable log to timbre: https://github.com/cgrand/unrepl#log-eval-and-log-all
Finally think I get this repl vs tooling thing now. So it would be acceptable to have a mimic/similar protocol that was used for other needs.