This is a refactored swank-clojure, and features sldb integration.
Some highlights:
* line based breakpoints
* stepping
* exception restarts
See the readme at https://github.com/hugoduncan/swank-clj
--
Hugo Duncan
Out of interest, how do swank-clj and swank-clojure (with merged in cdt stuff) compare?
Sam
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
Well, if the exception gets bound to *e, you can use this:
(defn pcause
([]
(pcause *e))
([e]
(if-let [c (.getCause e)]
(recur c)
e)))
...
=> (do-something quux mumble 42)
#<Boom!>
=> (pcause)
Exception java.lang.ArithmeticException: divide by zero
at clojure.lang.Numbers.divide (Numbers.java:138)
at com.mycompany.myproject.foo$hairy_calc.invoke (foo.clj:192)
at ... etc.
or something like it.
If it's not getting bound to *e, the above pcause can still be useful with
(defmacro pe [& body]
`(try
~@body
(catch Throwable t (pcause t))))
...
=> (testing-somefn foo 3.141 xyzzy)
#<Kablooey!>
=> (pe (testing-somefn foo 3.141 xyzzy))
Exception java.io.IOException: stream closed
at java.io.FileInputStream.read (FileInputStream.java:177)
at com.mycompany.myproject.bar$some-func.invoke (bar.clj:211)
at ... etc.
=> (defn some-func ... (doall ... ))
#'com.mycompany.myproject.bar/some-func
=> (pe (testing-somefn foo 3.141 xyzzy))
42
=>
Of course, if the exception is being thrown in some other thread, such
as in the evaluation of a pmap or future, all bets are off. Try
temporarily not using the parallelizing construct. In case of failed
Agents, obviously try (pcause (agent-error agnt)).
--
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.
> Very cool!
Thanks.
> Out of interest, how do swank-clj and swank-clojure (with merged in cdt
> stuff) compare?
I would have to let others comment on the user experience, not having used
the cdt support in swank-clojure. From reading the code, I see two
differences.
i) swank-clj uses SLDB vs the use of GUD in swank-clojure,
ii) swank-clj starts two jvms, one for the debugger and one for the
debuggee. If I understand correctly, CDT uses a single jvm process.
In swank-clj at the moment, a swank server runs in both jvms, but I am
working towards being able to run using just JPDA/JDI to talk to the
debugee. At that point it will be possible to attach the debugger to any
jvm process running with debugging enabled.
--
Hugo Duncan
> 1. The usual repl entry point is not used, and so, e.g., (set! *warn-
> on-reflection* true) fails.
Thanks, I raised an issue to track this
https://github.com/hugoduncan/swank-clj/issues/8
> 2. I could not figure out a way to browse exception chains.
> Typically the "real" stack trace for an exception is reached by
> repeatedly calling .getCause on the exception until the innermost
> exception is reached, but right now I can't see how to access causes
> in the swank-clj debugger. For example try:
There is no support for exception chains. The reasoning behind this is
that swank-clj can catch the original exception, before it gets caught and
re-thrown in the program. At the moment, there is some rigid filtering of
exceptions that means in some cases the original exception is not caught.
I am hoping that improved (user modifiable) filtering of exceptions based
on thrown type, throw location and catch location, will obviate the need
for handling exception chains in the interface. Does that sound
reasonable?
> If you want, I'm happy to help out on these. Thanks for the great
> work!
All help appreciated - if you can, I would prefer pull requests from
feature branches. There is lots to be done, especially around adding test
cases to get the project to the point where we can make changes with
confidence.
Raising issues for broken slime features would also be useful.
--
Hugo Duncan
Thanks for the explanation. I'm relatively new to Emacs - and certainly new to any debugging support. I hadn't heard of the Slime debugger or the "Grand Unified Debugger" before. Given my current understanding of the Emacs ecosystem it doesn't surprise me that there is more than one supported approach to debugging :-)
What I do think is interesting is that there are two different approaches to Clojure debugging within Emacs that are relatively young in terms of implementation maturity. Competing systems can be good for cross-fertilisation and motivation - however they can also be confusing to the newcomer when faced with a choice. Currently I'm that newcomer and I have been using swank-clojure only because it was the only way I knew. George's work on the CDT has been very exciting and I was thrilled to see it get merged in with swank-clojure. However, I now see swank-clj which also seems remarkably exciting - truly cool stuff.
It appears both approaches are incompatible - is this true? If so, I'm wondering what the merits of SLDB over GUD and visa versa are. SLDB sound great cos it has slime in the name and, after all, I'm using slime. However, GUD sounds amazing cos it has the words grand and unified in the title. My initial thoughts are focussed and bespoke vs generalised and abstract. Which personally makes me think SLDB. Clearly choosing purely by name is utter madness though. So if anyone has any more information that can help people decide which approach to invest their time learning that would be much appreciated.
Sam