|
35 | 35 | (list 'get key)))
|
36 | 36 | (conj path '<unknown>)))
|
37 | 37 |
|
38 |
| -(def ^:private supported-view-modes #{:normal :object :table}) |
| 38 | +(def ^:private supported-view-modes #{:normal :object :table :hex}) |
39 | 39 |
|
40 | 40 | (def ^:private default-inspector-config
|
41 | 41 | "Default configuration values for the inspector."
|
|
121 | 121 | (defn- decide-if-paginated
|
122 | 122 | "Make early decision if the inspected object should be paginated. If so,
|
123 | 123 | assoc the `:chunk` to be displayed to `inspector`."
|
124 |
| - [{:keys [value current-page page-size] :as inspector}] |
125 |
| - (let [pageable? (boolean (#{:list :map :set :array} (object-type value)))] |
| 124 | + [{:keys [value current-page page-size view-mode] :as inspector}] |
| 125 | + (let [pageable? (boolean (#{:list :map :set :array} (object-type value))) |
| 126 | + page-size (if (= view-mode :hex) |
| 127 | + (* page-size 16) ;; In hex view mode, each row is 16 bytes. |
| 128 | + page-size)] |
126 | 129 | (cond-> (assoc inspector :pageable pageable?)
|
127 | 130 | pageable? (merge (pagination-info value page-size current-page)))))
|
128 | 131 |
|
|
653 | 656 | (unindent ins))
|
654 | 657 | inspector))
|
655 | 658 |
|
| 659 | +;; Hex view mode |
| 660 | + |
| 661 | +(defn- byte->ascii [b] |
| 662 | + (let [c (bit-and b 0xFF)] |
| 663 | + (if (and (>= c 32) (<= c 126)) |
| 664 | + (char c) |
| 665 | + ;; Use MIDDLE DOT for non-printed chars as it is distinct from 0x2E. |
| 666 | + \·))) |
| 667 | + |
| 668 | +(defn- format-hex-row |
| 669 | + "Format 16 bytes as hex values." |
| 670 | + [bytes] |
| 671 | + (let [hex-strs (mapv #(format "%02x" (bit-and % 0xFF)) bytes) |
| 672 | + padded (concat hex-strs (repeat (- 16 (count bytes)) " ")) |
| 673 | + [left-half right-half] (split-at 8 padded)] |
| 674 | + (str (str/join " " left-half) " " (str/join " " right-half)))) |
| 675 | + |
| 676 | +(defn format-ascii-row |
| 677 | + "Format 16 bytes as ASCII characters." |
| 678 | + [bytes] |
| 679 | + (str/join (map byte->ascii bytes))) |
| 680 | + |
| 681 | +(defn render-hexdump |
| 682 | + "Render the current array or array chunk as a hexdump-style table." |
| 683 | + [{:keys [value chunk start-idx] :as inspector}] |
| 684 | + (let [start-idx (or start-idx 0) |
| 685 | + lines (eduction (comp (partition-all 16) |
| 686 | + (map-indexed vector)) |
| 687 | + (or chunk value))] |
| 688 | + (as-> inspector ins |
| 689 | + (render-leading-page-ellipsis ins) |
| 690 | + (reduce (fn [ins [i line]] |
| 691 | + (let [addr (+ (* i 16) start-idx)] |
| 692 | + (render-indent-ln |
| 693 | + ins (format "0x%08x │ %s │ %s" addr (format-hex-row line) |
| 694 | + (format-ascii-row line))))) |
| 695 | + ins lines) |
| 696 | + (render-trailing-page-ellipsis ins)))) |
| 697 | + |
656 | 698 | ;; Inspector multimethod
|
657 | 699 | (defn- dispatch-inspect [{:keys [view-mode] :as _ins} obj]
|
658 | 700 | (if (= view-mode :object)
|
|
683 | 725 | (defmethod inspect :map [inspector obj] (inspect-coll inspector obj))
|
684 | 726 |
|
685 | 727 | (defmethod inspect :array [inspector obj]
|
686 |
| - (-> (render-class-name inspector obj) |
687 |
| - (render-counted-length obj) |
688 |
| - (render-labeled-value "Component Type" (.getComponentType (class obj))) |
689 |
| - (render-analytics) |
690 |
| - (render-section-header "Contents") |
691 |
| - (indent) |
692 |
| - (render-collection-paged) |
693 |
| - (unindent) |
694 |
| - (render-datafy) |
695 |
| - (render-page-info))) |
| 728 | + (as-> (render-class-name inspector obj) ins |
| 729 | + (render-counted-length ins obj) |
| 730 | + (render-labeled-value ins "Component Type" (.getComponentType (class obj))) |
| 731 | + (render-analytics ins) |
| 732 | + (render-section-header ins "Contents") |
| 733 | + (indent ins) |
| 734 | + (if (= (:view-mode inspector) :hex) |
| 735 | + (render-hexdump ins) |
| 736 | + (render-collection-paged ins)) |
| 737 | + (unindent ins) |
| 738 | + (render-datafy ins) |
| 739 | + (render-page-info ins))) |
696 | 740 |
|
697 | 741 | (defn- render-var-value [inspector ^clojure.lang.Var obj]
|
698 | 742 | (if-not (.isBound obj)
|
|
0 commit comments