calva

pez 2025-05-21T06:17:36.991199Z

I wonder what we could do to help beginners to quicker find their footing in structural editing. https://www.reddit.com/r/Clojure/comments/1kou2xm/coding_clojure_in_vscode_is_a_cramp/

Tommi Martin 2025-05-21T06:39:55.670499Z

This is an incredibly good question. I wonder if my understanding of the root cause is correct. "The pain points are • A user the boots up vs code to code clojure doesn't know the hotkeys ◦ Or the hotkeys are uncomfortable / or deviating from the norm. • The user doesn't have the knowledge or understanding of why it works that way, making it frustrating. My personal feeling is that the answer would be education. As for what form it takes I'm not entirely sure. A wild idea: This is a complete fantasy talk with no regard to what is actually possible to vs code and it's derivatives, pinch of salt please. Would we be able to use the vscode popups to educate the user let's say during the first 14 days they've got calva installed we track the following: • if user presses backspace or delete and the deleted character would be () [] or {} ◦ Show a popup that either recommends holding alt to force the action or instructs in barf usage. Intent: this is very very brief, like a hotkey reminder. • when user adds brackets infront of something or highlights content and adds brackets again show that reminder popup about slurp command. After 14 days, ask if they want to keep the hotkey helpers enabled or disable them. (+14 days, on permanently or off) Would something like that solve the issue? Context sensitive education using popups? edit: with these popups i really emphasise that they should be short, and as unobtrusive as we can make them. one-liners hopefully.

pez 2025-05-21T07:23:00.792949Z

Thanks for engaging, @tommi.martin! 🙏 ❤️ I think you nail the problem statement perfectly. And I also agree that education should be our goto tool. I have taken some steps in this direction (that I think help) with the Getting Started command, which introduces the force delete option. We definitely should revisit how the subject is presented there and see what improvements we want to make. Calva friends: Please consider running the getting started command and read it with the eyes of someone new to lisp/structural editing. I have so far much hesitated to add popups of any kind, but maybe we can find a middle ground where we do not annoy too much, but still manage to help newcomers. The reasons I have hesitated: • I do not personally like when my tools interrupt my work • It is hard to meet the user with these offer at a time when she has time for it • It is hard to nail the heuristics for when to offer help/tips ◦ Get this wrong, and we have the most annoying feature ever But if we image that we can solve this: > edit: with these popups i really emphasise that they should be short, and as unobtrusive as we can make them. one-liners hopefully Then we do not annoy and interrupt, and we don’t need to be fancy about the heuristics for detecting when to help. I now started to think that code lens buttons could be used for it. They can be placed in the code near where the cursor is and they are not super intrusive. The user can have code lenses disabled (I have), but maybe that’s not the most common. Such a button could read “learn about deleting brackets” and when clicked open http://calva.io at some page introducing the subject to a beginner. It still would leave the heuristics to be solved, but it would be simpler than for a more intrusive popup.

Tommi Martin 2025-05-21T07:37:16.911509Z

Possibly, I think some sort of proof of concept for visuals might help to make that decision, but before we think about adding features to calva itself for this. Do we have any kind of engagement data or information about how users engage with content outside of Calva for example? Something to help us determine if want to spend the effort to first make the feature and then maintain it? It is nice to have, yes but it'll affect platform compatibility in the future so anything to convince us about the right path would be useful.

Tommi Martin 2025-05-21T07:39:33.869549Z

Information I would look for is something about how far reaching the issue is how many users (especially new ones) experience it as a problem. It boils down to a sample size. But I have absolutely no idea where to get that kind of data edit: What i'm trying to say is this: "Are all the answers to the problem of education that don't involve new code or features explored already?" And "How big of an impact would this code and feature set have?"

pez 2025-05-21T07:51:44.604849Z

The issue pops up now and then. And most people do not ask for help when they experience issues, so we can know that the issue is much more common than it seems from the reports.

🤔 1
✅ 1
Tommi Martin 2025-05-21T07:53:08.664729Z

If you think it is something you'd like to make and find it a worthwhile trade-off, I do support you. Let me know if I can help

🙏 1
pez 2025-05-21T07:53:57.888639Z

An alternative is to have a getting started UI that takes you through some important steps. VS Code has API for this. GitLens is an example extension that uses it.

pez 2025-05-21T07:55:26.734479Z

Looks a bit like so. The user checks off the the things she has covered.

pez 2025-05-21T07:56:53.183519Z

I don’t recall when GitLens surfaces this, but we could consider popping something up for anyone we consider to be a new user. Again, important to get the heuristics right.

Tommi Martin 2025-05-21T08:02:33.395909Z

It could be the first step in proving easily accessible education for users. The format of that screen needs some thinking though. If it's only checkboxes and "open file" or "execute command" links, it might be a challenge to retain the info

Tommi Martin 2025-05-21T08:03:03.780309Z

But definately shouldn't ignore the opportunity

pez 2025-05-21T08:03:11.811369Z

The first three items for Calva could be: • Deleting brackets • Enclosing expressions in brackets • Connecting the Clojure REPL

👍 1
jurjanpaul 2025-05-21T08:03:42.792069Z

Does Parinfer count as structural editing? (I believe it does, obviously). After all these years of Clojure I still hate it when an editor refuses to simply backspace on a paren. It’s about being able to immediately grab back the steering wheel. I am finding that turning strict mode off and having the Parinfer extension enabled is now more workable than ever (despite unfortunate VS Code API limitations), especially after some improvements to Calva this last year or so. 🙏 I would love for Calva documentation, including tutorials, to suggest this as a ‘blessed’ use of Calva, fully acknowledging that this may be a matter of personal preference. The more a new user experiences ’being allowed to take full control in a way that matches previous editing experiences’, the more that user may be persuaded to try something new. So, personally I still care less about the (small) risk of parens going unbalanced - programmers understand syntax and know how to fix it - than about editing without roadblocks (no strict mode for me). Even so, I always encourage new Clojure programmers to learn Paredit, because the community tells me that makes them more productive. As to learning Paredit: I have tried and may try again some time. But to succeed I would probably have to build ‘PAREDIT, THE GAME’ first… (or discover that Calva has that already built in… 😉). Without a lot of speed excercises outside of actually wanting to build something, my finger memory simply keeps giving up on remembering those key combinations.

👍 1
pez 2025-05-21T08:03:52.438139Z

The info can be hosted on http://calva.io

pez 2025-05-21T08:06:25.084089Z

Parinfer is too quirky in VS Code to be something I would recommend. And it is an expert’s tool, rather than a beginner’s. The problem with unbalanced code in Calva is that things stop working. All bets are off.

Tommi Martin 2025-05-21T08:07:27.587189Z

Jurjan nailed the challenge with the paredit, the process takes a bit of time to remember and build into muscle memory.

pez 2025-05-21T08:07:47.134429Z

I provided an answer in that reddit thread. It is a sample of how I think this should be communicated and taught.

pez 2025-05-21T08:09:04.609439Z

Specifically, it advices to start with learning just one paredit command. A command that VS Code has a version of already, so some people are already familiar even if they don’t come from lisp land.

seancorfield 2025-05-21T12:31:49.491309Z

That person is posting a lot of bad faith click-bait "questions" about Clojure but it's good to see some reasonable discussion about possible improvements to the beginners' experience in Calva come out of it...

2025-05-21T17:11:18.687129Z

When I use paredit in Emacs, I normally don't have jr where it skips over brackets and such if you try to delete things or move things around. I too find it a bit annoying. But it's definitely a preference. That said, I agree with the optic that it defeats user expectations for a UI as they've come to learn it. The paredit commands are useful without it limiting the normal editing commands. But I also do not use paredit much anymore, as adjust-parens + aggressive-indent mode in Emacs has taken over my structural editing. I wish there was a name for it, it's like the reverse of pareinfer, I wonder if VS Code could support it? Basically code is automatically indented based on parenthesis. And then tab and shift+tab can be used to indent or dedent (in a way that also appropriately adjusts the parenthesis) It ends up feeling a bit like typing out bullet point lists that you can indent or dedent as you want.

pez 2025-05-21T18:39:18.682029Z

Sounds a lot like the Parinfer I almost got into Calva some years ago.

2025-05-21T19:54:43.564379Z

It's a bit different than Pareinfer. Pareinfer you type the indent yourself, and it adjusts the parenthesis. (This can be spaces, tabs, or what not) Here you type the parenthesis, and it adjusts the indentation. But you also have the option to have it dedent or indent where it adjusts both the indent and parenthesis together by pressing tab (indent) or shift+tab (dedent).

seancorfield 2025-05-21T19:58:38.814069Z

I thought Parinfer had two modes, one where you type parens and it adjusts indents, and one where you indent and it adjusts parens?

2025-05-21T20:04:51.274709Z

Oh, maybe. I only ever used the mode where you indent and it adjusts the parens, where people say it makes Clojure "like Python". Though I guess here it's like I have both modes at once. It adjusts indents based on parenthesis I type, but a command can have it adjust parens and indents together to selectively indent or dedent.

pez 2025-05-21T21:12:16.082179Z

The one I built sounds very much like what you describe, @didibus. It was a mix of Calva’s formatter and paren inference. If I would try again, I would do these parts the same way. Especially since it seems there is good examples of it around. Anyway, it is not like I will pick that task up again anytime soon. I still have bleeding wounds. 😃

Joe R. Smith 2025-05-21T21:12:54.510909Z

Make parinfer work correctly. I think it's always a losing proposition to force paredit down people's throats while teaching them a new language (and a new plugin, to boot).

pez 2025-05-21T21:19:37.399909Z

Noone is forcing Paredit on anyone here. It’s there. Noone has to use it.

Joe R. Smith 2025-05-21T21:20:22.507199Z

ok, "force" is too strong

Joe R. Smith 2025-05-21T21:20:40.677039Z

but I understand the frustration when people have it enabled and don't know what's going on.

Joe R. Smith 2025-05-21T21:21:06.870289Z

it's not the "DWIM" mode that parinfer can be (at least v3)

pez 2025-05-21T21:22:39.413209Z

Well, too much time spent on Parinfer from my side anyway.

Joe R. Smith 2025-05-21T21:23:00.751249Z

that's fair, I know this is open source.

Joe R. Smith 2025-05-21T21:23:15.292079Z

tbh, if I thought I could pay for it to be added, I would. 😉

pez 2025-05-21T21:23:32.091549Z

I’ll focus on trying to make it easier to understand what’s going on.

👍 1
🙌 1
2025-05-21T22:42:04.512939Z

Where is the "standard" pareinfer impl? Is it in Emacs ?

2025-05-21T22:54:17.441439Z

Oh cursive? @solussd what does V3 do differently?

Joe R. Smith 2025-05-21T22:59:44.791569Z

V3 iirc, is: • smart mode (unify indent and paren mode) • if a file has "incorrect" (according to parinfer) indentation, it leaves it alone, while continuing to maintain the parinfer invariants on code you edit

Joe R. Smith 2025-05-21T23:00:42.447919Z

I think the cursive impl is correct, there is a workaround where you have to, unintuitively, turn off paren matching in the plugin in order for it to wrap forms to the end of the parent form when you open a new paren, but otherwise it works well.

Joe R. Smith 2025-05-21T23:01:32.644519Z

https://shaunlebron.github.io/parinfer/demo

Joe R. Smith 2025-05-21T23:01:39.424409Z

^ smart mode there works as expected.

2025-05-21T23:04:19.101579Z

That doesn't let you delete the parenthesis though?

2025-05-21T23:24:22.905519Z

@pez I think adjust-parens and aggressive-indent may be a lot simpler to implement. Aggressive indent will basically reformat the top level form you are modifying on newline, or when adding/removing a bracket, but only if the form is balanced, otherwise it leaves it untouched. That means your code is always indented properly. And as you add/remove parenthesis it re-indents everything to always reflect the nesting. And adjust-parens I think is basically just slurp and barf, but as if you always moved the cursor to the start of the line before barfing or slurping. Thus it nests or unest the line. Now in combination, if you change the parenthesis with adjust parens, because you barfed/slurped the line, it will trigger re-indenting from aggressive-indent. Thus together it appears to be "indenting" which both nests inside the previous form and reindents accordingly.

Joe R. Smith 2025-05-21T23:25:24.082389Z

It does let you delete parens

Joe R. Smith 2025-05-21T23:25:39.701759Z

deleting a closing paren slurps forms after it from the parent form

Joe R. Smith 2025-05-21T23:25:55.526369Z

deleting an opening paren splices the paren's form into the parent

2025-05-22T00:06:48.673979Z

Hum... In the web link at least if I backspace it just skips over the parens

seancorfield 2025-05-22T00:23:44.991829Z

There's a user here who is a professor teaching Clojure to students, and he considers parinfer to be much worse for those students - they get even more confused by it than by paredit. So it's clearly very subjective. I quite liked parinfer but found that every editor implementation tended to mess up pasting code when parinfer was enabled. In the end, I went back to paredit as the more predictable experience. But I can definitely see why some folks love parinfer.

2025-05-22T02:38:59.202289Z

Ya, some things about pareinfer like pasting is why I stopped using it. Aggressive-indent + adjust-parens hasn't had any annoyances for me yet.

Joe R. Smith 2025-05-22T16:59:36.155549Z

@didibus there needs to be at least one form after the closing paren in the parent form to slurp, otherwise deleting the closing paren would leave you with an unbalanced form. Or, another way to think about it is, it does delete it, and immediately puts it back in the same place (rather than after trailing forms on the same line. e.g., (+ 0 (* 1 2 3) 4) if I delete the closing paren after the 3, parinfer would leave me with (+ 0 (* 1 2 3 4)) but if I had (+ 0 (* 1 2 3)) and deleted the closing paren after the 3, I'd end up w/ the same thing.

2025-05-22T18:47:04.114249Z

Right, but I think this is unintuitive to new users. Like @jurjanpaul502 was saying: > So, personally I still care less about the (small) risk of parens going unbalanced - programmers understand syntax and know how to fix it - than about editing without roadblocks (no strict mode for me). Because expectations of editors is that you delete it deletes. So if we're talking friendly editing for new-commers to not get frustrated, but also get a taste for how awesome editing in Clojure can be. I think delete should delete as a default. What you can do to give them a taste is to give them aggressive-indent and tab/shift-tab indent/dedent. Which is what I use, so maybne I'm biased haha, but I also think it's the most user-friendly.

Joe R. Smith 2025-05-22T18:48:36.460929Z

oh maybe, I can't speak to that beyond the small handful of people I've taught clojure to using paredit and parinfer over the years. Paredit was confusing, parinfer has a learning curve, too, but in my experience a smaller one. Turning it all off is probably the way to start.

2025-05-22T18:49:40.890789Z

Ya, I think if you have someone teaching you, things are very different. I'd agree that pareinfer looks weirder at first, but if someone shows you, you get it quickly. Where as paredit takes longer to learn all the shortcuts and wrap your head around the various transformations, etc.

Joe R. Smith 2025-05-21T21:11:28.531849Z

I know this has been brought up before (probably by me), but what does the future of Parinfer look like for Calva? I read through https://calva.io/parinfer and I see it appears to have been removed from the latest Calva. I also think that that page misrepresents what parinfer is. Sure it adjusts parens based on multiline indentation, but it also makes barf and slurp (e.g., from paredit) functions of adding and deleting in-line parens. IMHO it is an improvement over paredit in a lot of ways (I'll refrain from upsetting any paredit die-hards and keep that an opinion 😉 ). So, tldr, what needs to be done to make this work properly (where properly means Parinfer v3 "smart mode" -- also doesn't clobber mal-indented files)?

Joe R. Smith 2025-05-21T21:13:34.245659Z

fwiw, this is a "how can I help?"

🙏 1
pez 2025-05-21T21:18:08.327839Z

Funny. This was just mentioned in the thread above this one. My last comment there was that I don’t have enough of an inclination to pick this task up. I have spent all too much time on it. Which is extra crazy, because I do not even find Parinfer to be an improvement over ParEdit. Anyway, what stopped me last time I spent two months on it was quality issues with Calva’s structural editor. Something @phill is addressing with his many contributions. So if Calva should ever be the vehicle/host for Parinfer, then that’s where you can help.

👍 1
jurjanpaul 2025-05-21T21:33:54.202239Z

As I mentioned in the previous thread the recent Calva improvements have already made things much more workable in combination with the existing VSCode Parinfer extension, which supports smart mode just fine. (Yes, race conditions still occur because the VSCode API apparently forces asynchronous post processing; I have learned to deal with that, but I understand @pez’s reluctance to suggest this as a viable option for beginners for this reason). Note: to try this, remember to turn off Calva’s strict mode!

👀 1
Joe R. Smith 2025-05-21T21:36:09.857449Z

@jurjanpaul502 the vscode parinfer extension last updated in 2018?

jurjanpaul 2025-05-21T21:39:12.613359Z

Yes, that one.

jurjanpaul 2025-05-21T21:41:12.159359Z

There is also a forked one (by kress95), but it’s almost exactly the same, apart from toggling between smart mode and disabled only.

👍 1