Skip to content

Commit

Permalink
[Inspector] Configure truncation limits
Browse files Browse the repository at this point in the history
The limits after which the inspector truncates collection members are now
configurable. Previously they were hardcoded to 5 and 150 for collection and
atom (non-collection) members.
  • Loading branch information
pdbrown committed Apr 9, 2021
1 parent a233ee6 commit bf6a4cd
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 21 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## master (unreleased)

### New features

* [#111](https://github.com/clojure-emacs/orchard/pull/111): [Inspector] Configure truncation limits

### Changes

* The _class info cache_ is now initialized silently by default. This results in less confusing output.
* You can now `@orchard.java/cache-initializer` for deterministically waiting for this cache workload to complete.
* You can control its verbosity by setting `"-Dorchard.initialize-cache.silent=false"` (or `[...]=true`).
Expand Down
60 changes: 41 additions & 19 deletions src/orchard/inspect.clj
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,18 @@
:page-size new-page-size
:current-page 0)))

(defn set-max-atom-length
"Set the maximum length of atomic collection members before they're truncated."
[inspector max-atom-length]
{:pre [(integer? max-atom-length)]}
(inspect-render (assoc inspector :max-atom-length max-atom-length)))

(defn set-max-coll-size
"Set the maximum number of nested collection members to print before truncating."
[inspector max-coll-size]
{:pre [(integer? max-coll-size)]}
(inspect-render (assoc inspector :max-coll-size max-coll-size)))

(defn eval-and-inspect
"Evaluate the given expression where `v` is bound to the currently inspected
value. Open the evaluation result in the inspector."
Expand Down Expand Up @@ -167,16 +179,22 @@
(s/join sep)
(format fmt))))

(defn- short? [coll]
(<= (count coll) 5))
(def ^:private ^:dynamic *max-atom-length* 150)
(def ^:private ^:dynamic *max-coll-size* 5)

(def ^:private truncate-max-length 150)
(defn- short? [coll]
;; Prefer `bounded-count` if available (clojure 1.9+) or fall back to `count`.
(let [len (if-let [bounded-count (some-> (resolve 'clojure.core/bounded-count)
(var-get))]
(bounded-count (inc *max-coll-size*) coll)
(count coll))]
(<= len *max-coll-size*)))

(defn- truncate-string [s]
(when s
(let [len (count s)]
(if (> len truncate-max-length)
(str (subs s 0 (- truncate-max-length 2)) "...")
(if (> len *max-atom-length*)
(str (subs s 0 (max (- *max-atom-length* 3) 0)) "...")
s))))

(defn value-types [value]
Expand Down Expand Up @@ -228,33 +246,34 @@
(safe-pr-seq value "[ %s ]"))

(defmethod inspect-value :vector-long [value]
(safe-pr-seq (take 5 value) "[ %s ... ]"))
(safe-pr-seq (take *max-coll-size* value) "[ %s ... ]"))

(defmethod inspect-value :lazy-seq [value]
(let [first-six (take 6 value)]
(if (= (count first-six) 6)
(safe-pr-seq (take 5 value) "( %s ... )")
(safe-pr-seq first-six "( %s )"))))
(let [prefix-length (inc *max-coll-size*)
prefix (take prefix-length value)]
(if (= (count prefix) prefix-length)
(safe-pr-seq (take *max-coll-size* value) "( %s ... )")
(safe-pr-seq prefix "( %s )"))))

(defmethod inspect-value :list [value]
(safe-pr-seq value "( %s )"))

(defmethod inspect-value :list-long [value]
(safe-pr-seq (take 5 value) "( %s ... )"))
(safe-pr-seq (take *max-coll-size* value) "( %s ... )"))

(defmethod inspect-value :set [value]
(safe-pr-seq value "#{ %s }"))

(defmethod inspect-value :set-long [value]
(safe-pr-seq (take 5 value) "#{ %s ... }"))
(safe-pr-seq (take *max-coll-size* value) "#{ %s ... }"))

(defmethod inspect-value :array [value]
(let [ct (.getName (or (.getComponentType (class value)) Object))]
(safe-pr-seq value ", " (str ct "[] { %s }"))))

(defmethod inspect-value :array-long [value]
(let [ct (.getName (or (.getComponentType (class value)) Object))]
(safe-pr-seq (take 5 value) ", " (str ct "[] { %s ... }"))))
(safe-pr-seq (take *max-coll-size* value) ", " (str ct "[] { %s ... }"))))
(defmethod inspect-value java.lang.Class [value]
(pr-str value))

Expand Down Expand Up @@ -531,12 +550,15 @@

(defn inspect-render
([inspector] (inspect-render inspector (:value inspector)))
([inspector value] (-> (reset-index inspector)
(assoc :rendered [])
(assoc :value value)
(render-reference)
(inspect value)
(render-path))))
([inspector value]
(binding [*max-atom-length* (or (:max-atom-length inspector) *max-atom-length*)
*max-coll-size* (or (:max-coll-size inspector) *max-coll-size*)]
(-> (reset-index inspector)
(assoc :rendered [])
(assoc :value value)
(render-reference)
(inspect value)
(render-path)))))

;; Get a human readable printout of rendered sequence
(defmulti inspect-print-component first)
Expand Down
35 changes: 33 additions & 2 deletions test/orchard/inspect_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

(def inspect-result-with-nil ["(\"Class\" \": \" (:value \"clojure.lang.PersistentVector\" 0) (:newline) \"Contents: \" (:newline) \" \" \"0\" \". \" (:value \"1\" 1) (:newline) \" \" \"1\" \". \" (:value \"2\" 2) (:newline) \" \" \"2\" \". \" (:value \"nil\" 3) (:newline) \" \" \"3\" \". \" (:value \"3\" 4) (:newline))"])

(def inspect-result-configure-length ["(\"Class\" \": \" (:value \"clojure.lang.PersistentVector\" 0) (:newline) \"Contents: \" (:newline) \" \" \"0\" \". \" (:value \"[ 1... 2222 333 ... ]\" 1) (:newline))"])

(def eval-and-inspect-result ["(\"Class\" \": \" (:value \"java.lang.String\" 0) (:newline) \"Value: \" \"\\\"1001\\\"\")"])

(def java-hashmap-inspect-result ["(\"Class\" \": \" (:value \"java.util.HashMap\" 0) (:newline) \"Contents: \" (:newline) \" \" (:value \":b\" 1) \" = \" (:value \"2\" 2) (:newline) \" \" (:value \":c\" 3) \" = \" (:value \"3\" 4) (:newline) \" \" (:value \":a\" 5) \" = \" (:value \"1\" 6) (:newline))"])
Expand All @@ -27,7 +29,7 @@
(def long-vector (vec (range 70)))
(def long-map (zipmap (range 70) (range 70)))
(def long-nested-coll (vec (map #(range (* % 10) (+ (* % 10) 80)) (range 200))))
(def truncated-string (str "\"" (apply str (repeat 147 "a")) "..."))
(def truncated-string (str "\"" (apply str (repeat 146 "a")) "..."))

(defn inspect
[value]
Expand Down Expand Up @@ -264,13 +266,42 @@
"{ :a 1, :b 2 }" (java.util.HashMap. {:a 1 :b 2})
"long[] { 1, 2, 3, 4 }" (long-array [1 2 3 4])
"java.lang.Long[] { 0, 1, 2, 3, 4 ... }" (into-array Long (range 10))
"#<MyTestType test1>" (MyTestType. "test1"))))
"#<MyTestType test1>" (MyTestType. "test1")))

(testing "inspect-value adjust length and size"
(binding [inspect/*max-atom-length* 6
inspect/*max-coll-size* 2]
(are [result form] (= result (inspect/inspect-value form))
"1" 1
"nil" nil
"\"2\"" "2"
":ab..." :abc/def
"( :a :b )" '(:a :b)
"[ 1 2 ... ]" [1 2 3]
"{ :a 1, :b 2 }" {:a 1 :b 2}
"( 1 1 ... )" (repeat 1)
"[ ( 1 1 ... ) ]" [(repeat 1)]
"{ :a { ( 0 1 ... ) \"ab..., ... } }" {:a {(range 10) "abcdefg", 2 3, 4 5, 6 7, 8 9, 10 11}}
"java.lang.Long[] { 0, 1 ... }" (into-array Long (range 10))))
(binding [inspect/*max-coll-size* 6]
(are [result form] (= result (inspect/inspect-value form))
"[ ( 1 1 1 1 1 1 ... ) ]" [(repeat 1)]
"{ :a { ( 0 1 2 3 4 5 ... ) 1, 2 3, 4 5, 6 7, 8 9, 10 11 } }" {:a {(range 10) 1, 2 3, 4 5, 6 7, 8 9, 10 11}}))))

(deftest inspect-coll-test
(testing "inspect :coll prints contents of the coll"
(is (= inspect-result-with-nil
(render (inspect/start (inspect/fresh) [1 2 nil 3]))))))

(deftest inspect-configure-length-test
(testing "inspect respects :max-atom-length and :max-coll-size configuration"
(is (= inspect-result-configure-length
(render (-> (inspect/fresh)
(assoc :max-atom-length 4
:max-coll-size 3)
(inspect/start [[111111 2222 333 44 5]])))))))


(deftest inspect-java-hashmap-test
(testing "inspecting java.util.Map descendendants prints a key-value coll"
(is (= java-hashmap-inspect-result
Expand Down

0 comments on commit bf6a4cd

Please sign in to comment.