Fork me on GitHub
#cursive
<
2020-09-10
>
Jakub Holý (HolyJak)13:09:06

How is it possible that I def-ine a var in the REPL window but it is then undefined? My session:

*ns* 
=> #object[clojure.lang.Namespace 0xfcdc79d "user"]
(def s1 "To work with module.rds-st2.module.rds.random_string.suffix its original") 
=> #'user/s1
(re-find #"To work with (module[^ ]+)" s1)
Execution error (ClassCastException) at user/eval72482 (form-init11451571577345478644.clj:1).
class clojure.lang.Var$Unbound cannot be cast to class java.lang.CharSequence (clojure.lang.Var$Unbound is in unnamed module of loader 'app'; java.lang.CharSequence is in module java.base of loader 'bootstrap')
(re-find #"To work with (module[^ ]+)" user/s1)
Execution error (ClassCastException) at user/eval72486 (form-init11451571577345478644.clj:1).
class clojure.lang.Var$Unbound cannot be cast to class java.lang.CharSequence (clojure.lang.Var$Unbound is in unnamed module of loader 'app'; java.lang.CharSequence is in module java.base of loader 'bootstrap')
s1
=> "To work with module.rds-st2.module.rds.random_string.suffix its original"
user/s1 
=> #object[clojure.lang.Var$Unbound 0x2363d6f "Unbound: #'user/s1"]
Update It seems it was Shadow-cljs' cljs REPL and the app has likely not been running anymore so that could perhaps explain it...

manutter5113:09:18

That was definitely a weird one

kennytilton14:09:27

Is there any way for us to extend the Cursive editor? On of the great tricks I learned thanks to an old skool Lisper was a surprising mouse-copy command that at first seemed bizarre and then became pretty much how I edited, esp. when refactoring: https://github.com/vsedach/mouse-copy We leave the insertion point where we want to (in effect) paste some code, then control-click or alt-control-click what we want to copy. Utterly counterintuitive and utterly addictive. Cursive rocks, but I miss this! 🙂

cfleming00:09:12

Ok, I’m going to have a quick go at implementing this. When you say copy, does the original stay in place or get deleted?

cfleming00:09:56

And I guess you’re talking about the sexp surrounding the point you click on, correct?

cfleming01:09:10

Ok, the mouse handling here is trickier than I expected. I’ll ask JetBrains how to best handle this.

cfleming04:09:32

Give that a try! I’m unlikely to support it much, but if it doesn’t work let me know and I’ll see if I can take a look. That was definitely harder than I expected.

kennytilton07:09:08

Sorry, I was away…thanks!!! Too awesome for words. Don’t know if you solved it already, but c-leftclick copies (leaving the original intact) and c-m-leftclick moves the original. I will give it a try now. If it needs work/support I will give it a shot. I guess my bigger Q was how to modify Cursive. Brilliant! 🙏

cfleming07:09:15

@U0PUGPSFR Great! Let me know if you have questions. If you want a copying and a cutting version, I’d create separate actions and factor the common code out, so you can assign different shortcuts. Ctrl-leftclick is probably caught at a very low level, particularly on OSX, for showing context menus. The other thing you might want is reformatting either the source or destination locations after pasting, let me know if that’s something you might want, it’s pretty easy to implement. Don’t be afraid to ask if you have questions!

cfleming07:09:13

Note that this doesn’t extend Cursive directly at all, just uses standard IntelliJ machinery. So you can also use this to do the same in e.g. Java if the mood takes you 🙂

kennytilton07:09:56

OK, right, I have to fight the Mac for the keychords. 🙂 I guess it could be the right or middle button if I go get a 3-button mouse. I have an Apple mouse which at least has the right click. Thx again for the effort. I know this is a counterintuitive mouse gesture but once I got into it it was all I did while refactoring.

cfleming08:09:19

Not only the Mac but also IntelliJ, that has actions bound to all the common key combinations with the left click, at least.

cfleming08:09:21

I’m actually not sure if you can reuse Ctrl-click if you have an external mouse connected, you’ll probably need to play around with that and maybe look in the debugger to see what the events end up looking like.

cfleming08:09:19

That code is pending a code review from the guy at JetBrains who was helping me with it, I’ll let you know if there are changes to it.

kennytilton08:09:02

Oh, wow, this is great support. I had to upgrade to 2020.1 and have encouraging results, with some issues: • the context menu still pops up; and • the text is copied where the click (to copy) is made, not to where I left the insertion point. I am starting to dig into the JB doc, but quickly: is it possible to develop interactively, or is the flow to edit, rebuild plugin, and re-import? Thx again for the effort and JB’s effort as well.

kennytilton13:09:22

Ah, you mentioned a debugger, sounds like I could hack interactively. I will dig into the docs.

kennytilton16:09:16

OK, not sure what I did but while thrashing I also got Kotlin upgraded to 1.4, maybe that helped. Anyway, text is indeed now copied to the current point. Also, I stole option-click for this feature and that works without kicking off other things. Sweet, I will try to work this much into fingers’ keychord repertoire. Thx again.

kennytilton16:09:45

I have a couple of feature tweaks that would be nice. Should I put them up on the repo as “issues” or just mention them here?

kennytilton18:09:10

OK, @U0567Q30W, by hook or by crook I am able to generate debug prints from the plugin. 🎉 First RFE will be to allow copy from a right brace back to the matching left.

kennytilton18:09:31

btw, I use the “runIde” task to bring up a whole IDE. Is there a simpler/faster way to iterate?

cfleming20:09:33

@U0PUGPSFR Great! Glad you’re getting into the swing (ha ha) of things. Yes, runIde is what you want, and you want to run it in debug mode. The only interactive option, sadly, is to change the code and then recompile (Build | Build Project), and if you’re lucky the debugger will offer to reload the new classes for you.

cfleming20:09:14

WRT your two issues above - here’s a bit of background. Normally to add a new action, you’d define an AnAction subclass like the Copy one in this plugin, declare it in the plugin.xml and be on your merry way. This one is more complicated because we need to capture the Swing events very early in the process so that the IDE doesn’t perform other actions based on the mouse click, like moving the caret. So if we don’t intercept the events early, what will happen is that they’ll propagate through the IDE, the editor will move the caret and then eventually our action will be invoked. That will cause this issue: “text is copied where the click (to copy) is made, not to where I left the insertion point”, because the editor moves the caret before our action is invoked.

cfleming20:09:23

So what I suspect is happening is that for some reason the event dispatcher is not catching your event early, or your action is disabled for some reason. You’ll need to debug to figure that out - put the breakpoint here: https://github.com/cursive-ide/mouse-copy/blob/master/src/main/kotlin/mouse/Copy.kt#L127 - that’s the most likely point for the interception of the events to fail.

cfleming20:09:44

Assuming you catch the event there, debug down to here https://github.com/cursive-ide/mouse-copy/blob/master/src/main/kotlin/mouse/Copy.kt#L150, step in until you reach our update() method here: https://github.com/cursive-ide/mouse-copy/blob/master/src/main/kotlin/mouse/Copy.kt#L82 and make sure that isEnabled is coming out true.

cfleming20:09:01

BTW for debug logging, your best option is to set a breakpoint which doesn’t suspend, but which does log to the console (see under Breakpoints’ properties -> Suspend and Logging options here: https://www.jetbrains.com/help/idea/using-breakpoints.html#breakpoint-properties)

kennytilton22:09:27

Thanks for all that! It started copying to the right place. Only thing that changed was a Kotlin upgrade to 1.4. shrug. And I managed to do print debugging by creating a run config from the runIDE task. A bit heavy handed but it let me explore a little. 🙂 I studied your code and looked at the API, and just played with normal editing. I noticed the Kotlin editor does not support double-click select on a right brace. Started getting pessimistic, then I had an insight.

kennytilton22:09:57

What is needed is exactly the logic that determines the range to select when we double-click. In IJ/Cursive that will either identify a grouping (brace, bracket, or parens) or a word. If we can pilfer that logic, it will identify precisely what to copy or move to “point”. Is that logic (that decides the double-click range) also outside Cursive? In com.code.Insight? If you can help me track that down I’ll work on this next weekend. Meanwhile I’ll have fun with the copy off the left parens. 🙂

cfleming23:09:09

I’m not sure what you mean by the logic to select the right brace - what is it you’re trying to achieve there?

kennytilton14:09:52

Well, we can double-click just to the right of a right parens/bracket/brace in a Clojure file and it will select the whole form to the left. Perfect for a Lispy language. In a Kotlin file the editor selects just the character to the right of the closing brace, which actually makes sense typographically given that we prolly are in the bounding box of that glyph when we click to the right of a parens et al. So I think leveraging the codeInsights library may not work for a Lispy language. But something is! The double-click selection range in Clojure is just what we need for mouse-copy. We will not actually get that as a selection and that is good, because any existing selection needs to be replaced by whatever we click (so we need to know what it is). Hmm, I am about to fire up the Lisp editor I use that has this implemented. Should I capture a movie?

cfleming20:09:17

I see, that demo was very helpful, thanks. So that doesn’t work quite how I envisioned, I thought it worked only for sexps but it also works for other types of form too.

cfleming03:09:05

Ok, I’ve investigated this a bit, and added some features to Cursive along the way that I’ve wanted to do for a while. The double-click form selection is driven by the same logic as the Extend Selection command, which is quite easy to hook into. But I don’t think that’s actually what you want, since that will select various types of intermediate things which are not actually single forms but which are useful to select sometimes, like words in strings and sub-parts of qualified keywords and symbols. I think you’d only ever want a complete atom for this, correct?

kennytilton04:09:03

Sorry, I was lost in the history of Lisp over here: http://www.softwarepreservation.org/projects/LISP/resource/#Bibliographies_ I never knew that resource existed! There goes the next month. As for words in strings, (a) lemme check that lisp (btw, that is the AllegorCL IDE on Windoze, they have a free version, but there is an internal flag we have to toggle to get the behavior — I will dig that up, as well) and (b) picking up the whole string would be amazing, but if we fall short of that it is not the end of the world. ISTR just sucking it up when edge cases like that did not quite work. eg, “Fine, I will click the open or close quote” 🙂. brb

kennytilton04:09:16

ps. just option-clicking left-groupers is already a delight. Thx!

kennytilton04:09:00

Ok, here is the magic incantation on AllegroCL for Windows if you want to go that far: (setf (cg.base::use-mouse-clicks-to-copy-lisp-forms (configuration cg.base::*system*)) t) And here is that version: https://franz.com/products/express/

kennytilton04:09:28

Meanwhile, yeah, the AllegroCL implementation is not smart enough to jump out to the whole string, it just copies the word I click. It can also do insane things if invoked within a comment. Basically my attitude was "do not get carried away, and be ready to revert the file". (The undo in that editor barely works.) As for parts of namespaced keywords, heh-heh, that gets me even now when double-clicking, so I am used to the disappointment. 🙂 But yes, I think most users would be trying to copy the whole atom. Good for the "nice to have" category, but not at all essential in my heavy experience of this feature.

cfleming04:09:14

@U0PUGPSFR I’ve often thought I should download the CL IDEs to try them out, but it comes with a difficult first step which is “Learn Common Lisp” 🙂

cfleming04:09:07

I don’t think those modifications are hard, I’ll try to make the changes in the next day or two.

🎉 3
🙏 3
kennytilton05:09:29

Heheh, CL is a lot different than Clojure, though also much the same. In my experience, that AllegroCL Windoze version is far and away the best. The Lispworks Free version is also a GUI-ish IDE. ClozureCL no longer works for me, too bad, it was good, too. Overall, I think EMACS+Slime is the predominant favorite by far. btw, the only reason I use Windoze is for that AllegroCL IDE. Their port to *nix did not pan out, and with everyone using emacs anyway….

cfleming05:09:03

Looks like they have a Mac version though? Is that buggier than the Windows version?

kennytilton05:09:05

Lemme give it a try. I thought they had given up on the IDE aspect….well, it bravely starts up, has me install GTk, then I just see squares where chars should be. YMMV. The Lisp REPL should be fine, but we’re after the editor.

Jeff Evans15:09:02

is it possible to run cljs tests (via lein-doo) in Cursive directly?

cfleming23:09:10

No, unfortunately Cursive doesn’t support running CLJS tests yet.

plins18:09:14

hello everyone, is there a way to override cursive’s formatting? force it to use a tool like clj-fmt/zprint?

cfleming23:09:46

There isn’t, no. This is because the formatting engine is pretty deeply embedded into IntelliJ, and is used in a lot of actions (for example, when you press Enter it’s used to figure out where in the next line the caret should go).

Eric Casteleijn18:09:31

👋 another formatting related question: when you tell cursive to format a macro in a particular way, (say, ‘Resolve as let’), where is that setting stored, and is it exportable, or shareable with others in some way?

cfleming23:09:20

The formatting (“Configure indentation for….“) and resolution (“Resolve … as…“) are stored in different places, but they both use IntelliJ’s schemes mechanism. So under Preferences | Editor | Code Style | Clojure or Preferences | Languages &amp; Frameworks | Clojure | Symbol Resolution, you can choose to share them with the project, export them etc.

🙏 3
Eric Casteleijn18:09:13

Oops asked too soon, my colleauge told me: Preferences > Languages & Frameworks > Clojure > Symbol Resolution shows it.

Eric Casteleijn18:09:24

@plins if you have either of them as a command line tool, you can configure an ‘External Tool’ to run it.

Eric Casteleijn18:09:06

I haven’t tried, but I suspect you could then run it automatically on save if you install the Save Actions plug-in.

plins18:09:39

thanks for the directions, ill try to see if I can make it behave properly

Eric Casteleijn18:09:48

(Honestly I find configuring Vim easier than Intellij. ;)