|
2 | 2 | "Format and output exceptions in a pretty (structured, formatted) way."
|
3 | 3 | (:require [clojure.pprint :as pp]
|
4 | 4 | [clojure.set :as set]
|
| 5 | + [clojure.string :as string] |
5 | 6 | [clojure.string :as str]
|
6 | 7 | [clj-commons.ansi :refer [compose]]
|
7 | 8 | [clj-commons.pretty-impl :refer [padding]])
|
|
102 | 103 | ;; (seq m) is necessary because the source is via (bean), which returns an odd implementation of map
|
103 | 104 | (reduce (fn [result [k v]] (if (f v) (conj result k) result)) [] (seq m)))
|
104 | 105 |
|
| 106 | +(def ^{:added "3.2.0"} default-frame-rules |
| 107 | + "The set of rules that forms the default for [[*default-frame-rules*]], and the |
| 108 | + basis for [[*default-frame-filter*]], as a vector of vectors. |
105 | 109 |
|
106 |
| -(def ^{:added "0.1.18" |
107 |
| - :dynamic true} |
108 |
| - *default-frame-rules* |
109 |
| - "The set of rules that forms the basis for [[*default-frame-filter*]], as a vector of vectors. |
| 110 | + Each rule is a vector of three values: |
110 | 111 |
|
111 |
| - Each rule is a vector of three values: |
| 112 | + * A function that extracts the value from the stack frame map (typically, this is a keyword such |
| 113 | + as :package or :name). The value is converted to a string. |
| 114 | + * A string or regexp used for matching. Strings must match exactly. |
| 115 | + * A resulting frame visibility (:hide, :omit, :terminate, or :show). |
112 | 116 |
|
113 |
| - * A function that extracts the value from the stack frame map (typically, this is a keyword such |
114 |
| - as :package or :name). The value is converted to a string. |
115 |
| - * A string or regexp used for matching. Strings must match exactly. |
116 |
| - * A resulting frame visibility (:hide, :omit, :terminate, or :show). |
| 117 | + The default rules: |
117 | 118 |
|
118 |
| - The default rules: |
119 |
| -
|
120 |
| - * omit everything in `clojure.lang`, `java.lang.reflect`, and the function `clojure.core/apply` |
121 |
| - * hide everything in `sun.reflect` |
122 |
| - * terminate at `speclj.*`, `clojure.main/main*`, `clojure.main/repl/read-eval-print`, or `nrepl.middleware.interruptible-eval` |
123 |
| - " |
| 119 | + * omit everything in `clojure.lang`, `java.lang.reflect`, and the function `clojure.core/apply` |
| 120 | + * hide everything in `sun.reflect` |
| 121 | + * terminate at `speclj.*`, `clojure.main/main*`, `clojure.main/repl/read-eval-print`, or `nrepl.middleware.interruptible-eval` |
| 122 | + " |
124 | 123 | [[:package "clojure.lang" :omit]
|
125 | 124 | [:package #"sun\.reflect.*" :hide]
|
126 | 125 | [:package "java.lang.reflect" :omit]
|
|
130 | 129 | [:name #"clojure\.main/repl/read-eval-print.*" :terminate]
|
131 | 130 | [:name #"clojure\.main/main.*" :terminate]])
|
132 | 131 |
|
| 132 | +(def ^{:added "0.1.18" |
| 133 | + :dynamic true} |
| 134 | + *default-frame-rules* |
| 135 | + "The set of rules that forms the basis for [[*default-frame-filter*]], as a vector of vectors, |
| 136 | + initialized from [[default-frame-rules]]." |
| 137 | + default-frame-rules) |
| 138 | + |
133 | 139 | (defn- apply-rule
|
134 | 140 | [frame [f match visibility :as rule]]
|
135 | 141 | (let [value (str (f frame))]
|
136 | 142 | (cond
|
137 | 143 | (string? match)
|
138 |
| - (if (= match value) visibility) |
| 144 | + (when (= match value) visibility) |
139 | 145 |
|
140 | 146 | (instance? Pattern match)
|
141 |
| - (if (re-matches match value) visibility) |
| 147 | + (when (re-matches match value) visibility) |
142 | 148 |
|
143 | 149 | :else
|
144 | 150 | (throw (ex-info "unexpected match type in rule"
|
145 | 151 | {:rule rule})))))
|
146 | 152 |
|
147 | 153 | (defn *default-frame-filter*
|
148 |
| - "Default stack frame filter used when printing REPL exceptions, driven by [[*default-frame-rules*]]." |
| 154 | + "Default stack frame filter used when printing REPL exceptions; default value is derived from [[*default-frame-rules*]]." |
149 | 155 | {:added "0.1.16"
|
150 | 156 | :dynamic true}
|
151 | 157 | [frame]
|
|
738 | 744 |
|
739 | 745 | Properties of exceptions will be output using Clojure's pretty-printer, but using
|
740 | 746 | this namespace's versions of [[*print-length*]] and [[*print-level*]], which default to
|
741 |
| - 10 and 2, respectively. |
| 747 | + 10 and 5, respectively. |
742 | 748 |
|
743 | 749 | The `*fonts*` var contains a map from output element names (as :exception or :clojure-frame) to
|
744 | 750 | a font def used with [[compose]]; this allows easy customization of the output."
|
|
886 | 892 | exceptions stack-trace stack-trace-batch)
|
887 | 893 | (recur :start lines
|
888 | 894 | exceptions stack-trace stack-trace-batch)))))))
|
| 895 | + |
| 896 | +(defn format-stack-trace-element |
| 897 | + "Formats a stack trace element into a single string identifying the Java method or Clojure function being executed." |
| 898 | + {:added "3.2.0"} |
| 899 | + [^StackTraceElement e] |
| 900 | + (let [{:keys [class method names]} (transform-stack-trace-element current-dir-prefix (volatile! {}) e)] |
| 901 | + (if (empty? names) |
| 902 | + (str class "." method) |
| 903 | + (->> names counted-terms (map counted-frame-name) (string/join "/"))))) |
0 commit comments