Fork me on GitHub
#cursive
<
2019-11-01
>
cfleming00:11:01

@ssanders Yes, you can do this. I don’t have much documentation for this yet, but I spoke a couple of years ago about the debugger, and I demo exactly what you’re asking about: https://www.youtube.com/watch?v=ql77RwhcCK0

ssdev01:11:02

@U0567Q30W thanks for this. I actually watched this video (most of it) a few weeks ago and have been loving the use of the debugger in cursive. My particular use case though, hasn't been seeming to work.. if I set up a super simple ring web server and place a linebreak in the editor, then use a curl to hit the server, I can see the response in the terminal where I issued the curl command, but I don't see the linebreaks stopping the code execution. Think I may be missing something super obvious but can't put my finger on it

cfleming01:11:03

Do you see the breakpoint being active in the gutter? If IntelliJ can’t find the corresponding bytecode to the line, it’ll be like a grey crossed out circle.

ssdev01:11:38

It does look like it's getting greyed out once I start the debugger

ssdev01:11:31

Is there a way to help intellij find the bytecode?

cfleming01:11:45

One thing to try is setting the breakpoint, then starting your app and then re-loading the file containing the breakpoint.

cfleming01:11:05

That will cause Clojure to re-compile the file exactly matching what’s in your editor.

cfleming01:11:05

Re-loading the file is also required if you’ve just switched locals clearing off.

ssdev02:11:10

It's weird. The second I send the file to the repl I see a red message in the repl window and then the line break goes away.

Loading src/clj_ring/core.clj... 2019-10-31 22:00:13.209:INFO::nRepl-session-99305752-ae04-43f3-bf11-5b9398ba6c43: Logging initialized @17709ms to org.eclipse.jetty.util.log.StdErrLog

cfleming02:11:56

Hmm, that’s very strange.

cfleming02:11:20

Debugging can be very strange, and I can’t always explain what I see either, but that sounds stranger than usual.

ssdev02:11:40

I'm actually just trying it with a simple hello world -

(ns clj_ring.core
  (:use ring.adapter.jetty))

(defn handler [request]
  {:status 200}
  :headers {"Content-Type" "text/plain"}
  :body "Hello World")

(run-jetty handler {:port 8080})

cfleming02:11:15

Where are you putting the breakpoint? On the map inside the handler?

ssdev02:11:02

yeah, or .. on the defn handler line

cfleming02:11:49

Try doing something like:

(let [result {your map here...}]
  result)

cfleming02:11:20

And then putting the breakpoint on the let line. I’m actually not sure what executable bytecode Clojure generates when just returning a constant map like that.

cfleming02:11:01

There may not be enough for the debugger to hang off.

cfleming02:11:38

IIRC constant maps are generated just as constants in the class pool, and the code to return that may not be generated with line info.

ssdev02:11:03

blerg. no luck there

cfleming02:11:54

Would you mind uploading your hello world project to GH or somewhere so I can try it out?

ssdev02:11:05

sure thing

cfleming02:11:39

Thanks, give me a moment to wrap up what I’m doing.

ssdev02:11:25

Absolutely. Thanks for your help

cfleming02:11:35

You’re right, I cannot for the life of me get that to stop in the handler.

cfleming02:11:18

I made a few changes, I put your run-jetty in a comment block like this:

(comment
  (jetty/run-jetty handler {:port 3000 :join? false}))

cfleming02:11:39

That then means that it won’t run Jetty and block until it finishes when you load the file.

cfleming02:11:33

So you can then reload the file, and just use “Run top form” to start the Jetty server. It won’t block when you execute that because of the :join? false so you can then continue to use the REPL.

cfleming02:11:46

I see the problem

cfleming02:11:12

Your namespace is called clj_ring.core - it should be called clj-ring.core.

cfleming02:11:51

So when Clojure compiles, it can’t use - in package names because Java. So it maps them to _. But that’s a lossy transformation, so Cursive (and a lot of other tooling) assumes that when it sees a compiled class with an underscore in the name, that it comes from a namespace/function with a dash in the original name.

cfleming02:11:13

There’s no way to tell which of the two the original was named.

cfleming02:11:22

I need an inspection to warn about that, clearly.

cfleming03:11:11

You can just change the name in the ns form, and then everything works. The name of the directory on the filesystem should remain the same (with _)

ssdev03:11:30

no no, that's something I should have seen, I'm just extreme noob. But I've just changed that and still seeing the line break getting greyed out, is that not happening for you?

cfleming03:11:53

Did you re-load the file after changing the name?

cfleming03:11:12

Wait a minute, I’m now not seeing it work either.

cfleming03:11:44

I swear that worked a minute ago.

cfleming03:11:44

Ok, if I completely shut down and then re-start the REPL, it works for me.

cfleming03:11:57

There must have been something a bit funky in the debugger state.

cfleming03:11:05

There’s still something weird going on, though. It now makes my breakpoint into a circle with a tick, which means that it’s found the bytecode corresponding to the line information. But when I hit the server it doesn’t stop.

cfleming03:11:28

Ok, here’s what’s going on. When the server is started, it must be getting the actual function instance of the handler function rather than the var, and caches that. So then when I re-load the namespace, that function object is not updated.

cfleming03:11:43

If I re-start the server, it then stops correctly.

ssdev03:11:30

It's weird I still haven't been able to make it stop

ssdev03:11:16

And yes, I think I should have been more descriptive, I think that's the same circle logo I'm seeing - with a tick

cfleming03:11:54

This is what the breakpoint should look like.

cfleming03:11:16

So I have seen it stop, but I can’t make it do it again.

cfleming03:11:25

There’s something strange going on, but I don’t know what.

cfleming03:11:22

I thought that by passing the var (`#'handler`) to run-jetty that it would then re-load since it will then look up the function every time it’s invoked.

cfleming03:11:45

Similarly with what I’m doing there delegating through handler-fn.

cfleming03:11:52

But neither of those work reliably.

cfleming03:11:14

Ok, it’s something to do with the let block, for some reason.

cfleming03:11:43

Here’s what works for me. Make sure you pass the var itself to run-jetty like this:

(comment
  (def server (jetty/run-jetty #'handler {:port 3000 :join? false})))

cfleming03:11:24

That will cause the function stored in the handler var to be looked up each time it’s called, which will allow you to re-load the code without restarting the server.

cfleming03:11:59

Then, if I make my handler look like this:

(defn handler [request]
  (println "Hello")
  (let [result {:status  200
                :headers {"Content-Type" "text/plain"}
                :body    "Hello World"}]
    result))

cfleming03:11:09

Then it will break reliably on the println line.

ssdev03:11:41

oh snap, I see it now.

cfleming03:11:45

I guess the code generated for the let returning a constant map doesn’t generate any line numbers in the bytecode or something.

ssdev03:11:54

But weird that the let isn't working... yeah

cfleming03:11:23

Let me know if that works for you.

ssdev03:11:48

but yeah this works for me, I can totally use it in my project. Just need a way to step in.

ssdev03:11:52

Thanks a mil!

cfleming03:11:33

No problem! That was a combination of weird things. Once you have some actual code in your handler, everything should hopefully work.

sogaiu00:11:43

the debugger is wonderful 🙂

cfleming00:11:02

@sogaiu Thanks, I also like it 🙂

cfleming00:11:09

I use it all the time.

sogaiu00:11:52

it's really great for learning about clojure internals too! it's a gem of the clojure tooling world, imho.

dmarjenburgh08:11:22

I have a maybe slighty annoying request. Whenever you paste text that has some html tags, Cursive shows a popup asking to convert it to Hiccup. This seemed like a nice unexpected feature, but I paste HTML multiple times a day, but don’t use hiccup at all, so I have to click away the alert every time. It would be nice to have the option to not show it again or something…

onetom09:11:59

I'm guessing, that is a so called Intention which you can disable in preferences, although when I search for hiccup in preferences, nothing turns up 😕

cfleming20:11:28

No, it’s not an intention. I’ll add the ability to disable that.

cfleming20:11:13

@U05469DKJ Would you prefer the ability to convert to something other than hiccup? Why are you pasting HTML into Clojure code?

dmarjenburgh21:11:02

We are storing user created content, which is rich formatted text. This is stored as simple HTML (just some <p>,<b>,<i>,etc tags). I often copy and paste an example input in the REPL.

dmarjenburgh21:11:54

I don’t need to convert it. An option to disable it would be great

salam22:11:42

instead of converting html into hiccup automatically (and having an option to enable/disable it), it would be great if cursive offered a context menu item such as "Paste HTML as Hiccup", something like this: https://support.office.com/en-us/article/Paste-Special-e03db6c7-8295-4529-957d-16ac8a778719

cfleming03:11:07

I could do that, but I think it would affect the discoverability. I could perhaps have both, where the explicit “Paste as Hiccup” option wouldn’t prompt, and the prompt for the standard paste could have a “Don’t ask me this again” option.

👍 4
4
Ben Hammond14:11:59

is there a way to interrupt the repl from displaying the last form I pressed 'Interrupt Current Evaluation` button and now I'm waiting for e n o r m o u s form to be written to the repl a 'don't bother writing the rest of tthis to the repl` button would be extremely helpful

cfleming20:11:11

Well, rather, no, there isn’t a way to do it, but it’s something I’m going to add 🙂

Ben Hammond14:11:33

(I'm going to kill that repl java process now)

Adrian Smith22:11:57

How do I get cursive to start understanding some of these symbols?

Adrian Smith22:11:42

oh the pom file from running shadow-cljs pom and then the mavern plugin has helped somewhat

Adrian Smith22:11:49

oh and I think from the sounds of it I need a fake project.clj for cursive to understand what a phaser is?

p-himik19:11:15

I also use shadow-cljs, and I find it much easier to work with Cursive when I use deps.edn and add :deps true to shadow-cljs.edn.