Skip to content
This repository was archived by the owner on Oct 21, 2022. It is now read-only.

Commit 5c24628

Browse files
committed
collapsible exceptions added in a new namespace.
README updated. collapsible.exception TAG added
1 parent faa4b89 commit 5c24628

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ By default, \*.cljc files are identified as Clojure files. Thus when you eval, i
2020
Clojure file. If you'd like to eval as a ClojureScript file, run the command `Editor: Set current
2121
editor syntax`, select `ClojureScript` and then eval.
2222

23+
## Clojure(script) error messages
24+
Currently this plugin supports an experimental feature that allows to change the default exception behavior (showing the complete stacktrace) to an expandable version of the same. Some screenshots of the new behavior can be found [here](https://github.com/LightTable/Clojure/issues/77).
25+
To use the new behavior go to ```User behaviors``` and add the following lines :
26+
27+
```Clojure
28+
; for Clojure
29+
[:editor.clj :-lt.plugins.clojure/clj-exception]
30+
[:editor.clj :lt.plugins.clojure.collapsible-exception/clj-expandable-exception]
31+
32+
; for Clojurescript
33+
[:editor.cljs :-lt.plugins.clojure/cljs-exception]
34+
[:editor.cljs :lt.plugins.clojure.collapsible-exception/cljs-expandable-exception]
35+
```
36+
2337
## First ClojureScript Repl
2438

2539
Welcome first time ClojureScript users! Please see [David Nolen's tutorial](https://github.com/swannodette/lt-cljs-tutorial) to get familiar with ClojureScript and comfortable with LightTable's repl. Note while doing that tutorial you were in a namespace. A namespace is necessary for a LightTable repl. Once you have finished the tutorial, create your own ClojureScript project with `lein new mies my-project` and eval there. If you want to add dependencies to your project, read the [below section](#clojurescript-eval) as that requires a different type of LightTable connection.

clojure.behaviors

+14
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,18 @@
9797

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

0 commit comments

Comments
 (0)