forked from LightTable/Clojure
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcollapsible_exception.cljs
100 lines (91 loc) · 4.55 KB
/
collapsible_exception.cljs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
(ns lt.plugins.clojure.collapsible-exception
(:require [lt.util.dom :as dom]
[lt.object :as object]
[lt.objs.editor :as ed]
[lt.objs.notifos :as notifos]
[crate.binding :refer [bound]])
(:require-macros [lt.macros :refer [defui behavior]]))
(def ^:private ^:const NOT_FOUND -1)
(defn truncate
"truncate a string at newline or at 100 characters long"
[text]
(when-not (empty? text)
(if (= NOT_FOUND (.indexOf text "\n"))
(subs text 0 100); take 100 characters
(first (clojure.string/split-lines text)))))
(defn ->collapse-class [this summary]
(str "inline-exception result-mark"
(when (:open this) " open")))
(defui collapsible-exception-UI [this info]
(let [stacktrace (:result info)
summary (str (:summary info) " ...")]
[:span {:class (bound this #(->collapse-class % summary))
:style "background: #73404c; color: #ffa6a6;
max-width:initial; max-height:initial"}
[:span.truncated summary]
[:span.full stacktrace]])
:mousewheel (fn [e] (dom/stop-propagation e))
:click (fn [e] (dom/prevent e)
(object/raise this :click))
:contextmenu (fn [e] (dom/prevent e)
(object/raise this :menu! e))
:dblclick (fn [e] (dom/prevent e)
(object/raise this :double-click)))
(object/object* ::collapsible-exception
:triggers #{:click :double-click :clear!}
:tags #{:inline :collapsible.exception}
:init
(fn [this info]
(when-let [ed (ed/->cm-ed (:ed info))]
(let [content (collapsible-exception-UI this info)]
(object/merge! this (assoc info
:widget (ed/line-widget (ed/->cm-ed (:ed info)) (:line (:loc info))
content, {:coverGutter false})))
content))))
(behavior ::expandable-exceptions
:triggers #{:editor.exception.collapsible}
:reaction
(fn [this summary stack loc]
(let [ed (:ed @this)
line (ed/line-handle ed (:line loc))
ex-obj (object/create ::collapsible-exception
{:ed this, :result stack,
:summary summary
:loc loc, :line line})]
(when-let [prev (get (@this :widgets) [line :inline])]
(when (:open @prev) (object/merge! ex-obj {:open true}))
(object/raise prev :clear!))
(when (:start-line loc)
(doseq [widget (map #(get (@this :widgets) [(ed/line-handle ed %) :inline])
(range (:start-line loc) (:line loc)))
:when widget]
(object/raise widget :clear!)))
(object/update! this [:widgets] assoc [line :inline] ex-obj))))
(behavior ::clj-expandable-exception
:triggers #{:editor.eval.clj.exception}
:reaction (fn [obj res passed?]
(when-not passed?
(notifos/done-working ""))
(let [meta (:meta res)
loc {:line (dec (:end-line meta)) :ch (:end-column meta 0)
:start-line (dec (:line meta 1))}]
(notifos/set-msg! (:result res) {:class "error"})
(object/raise obj :editor.exception.collapsible (:result res) (:stack res) loc))))
(behavior ::cljs-expandable-exception
:triggers #{:editor.eval.cljs.exception}
:reaction (fn [obj res passed?]
(when-not passed?
(notifos/done-working ""))
(let [meta (:meta res)
loc {:line (dec (:end-line meta)) :ch (:end-column meta)
:start-line (dec (:line meta))}
msg (or (:stack res) (truncate (:ex res)))
stack (cond
(:stack res) (:stack res)
(and (:ex res) (.-stack (:ex res))) (.-stack (:ex res))
(and (:ex res) (:verbatim meta)) (:ex res)
(and (:ex res) (not (:verbatim meta))) (pr-str (:ex res))
(not (nil? msg)) (or (:stack res) (:ex res)); untruncated stacktrace
:else "Unknown error")]
(notifos/set-msg! msg {:class "error"})
(object/raise obj :editor.exception.collapsible msg stack loc))))