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/
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.
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.
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.
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?"
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.
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
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.
Looks a bit like so. The user checks off the the things she has covered.
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.
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
But definately shouldn't ignore the opportunity
The first three items for Calva could be: • Deleting brackets • Enclosing expressions in brackets • Connecting the Clojure REPL
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.
The info can be hosted on http://calva.io
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.
Jurjan nailed the challenge with the paredit, the process takes a bit of time to remember and build into muscle memory.
I provided an answer in that reddit thread. It is a sample of how I think this should be communicated and taught.
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.
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...
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.
Sounds a lot like the Parinfer I almost got into Calva some years ago.
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).
I thought Parinfer had two modes, one where you type parens and it adjusts indents, and one where you indent and it adjusts parens?
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.
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. 😃
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).
Noone is forcing Paredit on anyone here. It’s there. Noone has to use it.
ok, "force" is too strong
but I understand the frustration when people have it enabled and don't know what's going on.
it's not the "DWIM" mode that parinfer can be (at least v3)
Well, too much time spent on Parinfer from my side anyway.
that's fair, I know this is open source.
tbh, if I thought I could pay for it to be added, I would. 😉
I’ll focus on trying to make it easier to understand what’s going on.
Where is the "standard" pareinfer impl? Is it in Emacs ?
Oh cursive? @solussd what does V3 do differently?
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
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.
^ smart mode there works as expected.
That doesn't let you delete the parenthesis though?
@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.
https://elpa.gnu.org/packages/adjust-parens.html https://github.com/Malabarba/aggressive-indent-mode
It does let you delete parens
deleting a closing paren slurps forms after it from the parent form
deleting an opening paren splices the paren's form into the parent
Hum... In the web link at least if I backspace it just skips over the parens
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.
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.
@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.
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.
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.
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.
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)?
fwiw, this is a "how can I help?"
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.
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!
@jurjanpaul502 the vscode parinfer extension last updated in 2018?
Yes, that one.
There is also a forked one (by kress95), but it’s almost exactly the same, apart from toggling between smart mode and disabled only.