When I looked into the issue that I filed: https://github.com/BetterThanTomorrow/calva/issues/2901#top I noticed that discard/ignore tokens weren't quite treated well. I use #_ quite a bit, so I figured I'd look into what it would feel like to have them work. All I did was hack up the code, but I kinda like it. But I'm wondering if I'm on the right track. Do others have feelings about if it's worth treating them as part of an sexp?
Video in the thread, but the idea is that :b and :a
[:a #_ :b] --paredit drag sexp forward--> [#_ :b a]
for all/most of paredit keybindings (slurp forward sexp, etc...)
I looked into clojure paredit in emacs. It handles # similarly to Calva. Maybe worse in some ways. And ##_ it handles pretty much the same.
Any comments on this ignore tokens experiment?
When there are stacked ignore tokens (`##`) that cause an affected s-expression to be ignored, then during an operation, one of those ignore tokens is grabbed and teleported in front of the moved s-expression.
In the video :c dragged backward and :b becomes #_:b while #_#_:a becomes just #_:a.
@phill Hopefully this is clearer... this one is me with the code that associates # with a sexp. For example, when dragged, slurped or deleted the whole thing (eg #4) comes as a unit.
And here's the production (well, actually dev) code. The #_ part is treated separately from the sexp that it modifies.
I did do this in screencast mode, but apparently the popup window doesn't get recorded. The comments indicate that I'm trying to do though.
I cannot tell what is going on in the videos. The written notation used by Calva's paredit unit tests (using | for cursor location, etc.) could make it clearer.
@phill Yeah, this is hard to communicate
[#_#_:a :b |:c :d] => [#_:a |:c #_:b :d]
• There are stacked ignore tokens causing :a and :b to be ignored
• User is on :c, drags it backward
• Due to this :b must be moved forward, but it is currently ignored by a #_ in the stack
• during the move, a #_ is moved from the stack to before :b
A minor issue is that once pulled apart, the ignore token stack isn't rebuilt automatically. This feels OK to me, at least for now, but I'm not an expert Clojure developer.
Another option would be to use keep the ignore stack.
Hmm... maybe I should check what emacs or cursive does?
When I stack #_ (such as for a map key and its value), I do not want them pulled apart. And if I had not stacked ignores, I would not want them to get auto-stacked.
Yeah, I get that, especially for a map
Or a let binding pair
Could a stacked ignore be treated as a single form, so
[#_#_:a :b |:c :d] => [|:c #_#_:a :b :d]
But I am less certain I would want move-cursor-sexp-forward/backward to treat stacked ignores as a single form. It would become difficult to get into them.
Calva's status quo might be the happy medium. But I do not know what other editors do!
My annoyance with how #_ is treated was less about dragging forward/backward and more about barf and slurp. It's just that dragging is easier to experiment with
Maybe for cursor motion, forward could advance over the whole stack (since the stack is sitting right there) and backward could ignore ignores and back up only one literal sexp.
Well you raised a very good question about splitting up the stacked ignores.
Yeah, and maybe for now, I could look into the little bugs that are happening (like the cursor going to strange places) and spaces appearing. I just poked at my issues with #_ and it was bigger than I thought. (It also involves a decent amount of code changes)
Are there Jira issues for those?
There's https://github.com/BetterThanTomorrow/calva/issues/2901. I'll file more when I re-encounter those small issues
Some examples:
I did verify that alt+enter evaluation on #_ (+ 1 1) can work with this too
One downside is that, at least for now, multiple ignore tokens aren't handled (due to complexity). So [#_ #_ :a :b :c] still doesn't work correctly.
Consistent operation with 2 stacked ignores (as for a typical map entry) would be nice. And if it can do 2, it can do hundreds.
I don't know what's happening in the movie. Calva's unit tests have a very nice notation for this sort of thing - micro-document, cursor or selection is here, do the command, and here's the resulting micro-document with cursor, which might work well in Slack too, with the added benefit, of course, that if you contribute your suggestion then you've already got the tests ready
Yup, I've been writing some unit tests. The movie is mostly moving dragging sexp around (alt+right and alt+left). I should redo it with presentation mode on so it's more obvious, and maybe add a comparison with the production code.
I agree that two stacked ignores would be nice. But ugh, I didn't want to get into walking backward up the parse tree. And that backward walk would need to happen each time the code manipulates an s-expression. (ETA: would have to go all the way to the root of the parse tree.) It's already messy looking for one! :) I'm actually starting to wonder if it might be better to change the parser to somehow mark s-expressions as ignored, and perhaps include the associated ignore token (maybe along with associated metadata?).