abo-abo / lispy

Short and sweet LISP editing
http://oremacs.com/lispy/
1.2k stars 132 forks source link

Slurp / barf multiple levels #398

Open Ambrevar opened 6 years ago

Ambrevar commented 6 years ago

Consider the following, with | the point:

(foo
 (bar arg1 arg2)|)
(baz)

It would be great if we could slurp from there in order to get

(foo
 (bar arg1 arg2 (baz))|)

Same for barf, obviously. What do you thing?

abo-abo commented 6 years ago

I don't think it fits into the established lispy-slurp behavior. Maybe another command could be added that does this.

How I would solve this edit:

Ambrevar commented 6 years ago

Why doesn't it fit slurp? The way I see it, currently implementation "slurps the next branch that shares the same parent node."

If we lift the restriction and only "slurp the next branch", we get the same behaviour except that it keeps "slurping" instead of doing nothing when there is no more branch under the same parent.

A strong selling point of lispy is the fast editing it enables. One > in the above example is much faster than ok., let alone moving the cursor.

ok. is a good approach if we are already on baz, in which case we want to move the s-exp. I think this highlights a duality between moving and slurping. If moving handles multiple levels, then so should slurping.

My two cents :)

Do you see any downside to me proposal?

abo-abo commented 6 years ago

Do you see any downside to me proposal?

Your example above is not a common use case in my opinion.

Here's a very common use case for me:

(progn
  (let ((foo (bar))))|
  (e1)
  (e2)
  (e3))

Here, the new let binding was just introduced. The same case holds for adding (save-excursion), (with-output-to-string) etc. And what you typically want to do here is to slurp in all sexps that belong to progn, and not go beyond that. 99> or just holding > solves that problem nicely.

With your proposed change > can go beyond the parent expression, making my use case awkward to deal with.

The difference here is similar to structured j vs unstructured f - both are useful in many contexts, but joining them into a single command would make it awkward. Hence my suggestion to add a new slurp command that does what you want. In fact, after writing this and some checking I see that we already have lispy-forward-slurp-sexp which mirrors paredit-forward-slurp-sexp. The only issue is that the emulation is buggy at the moment, i.e. paredit-forward-slurp-sexp does what you want, but lispy-forward-slurp-sexp doesn't. We can fix that in time.

Ambrevar commented 6 years ago

Makes a lot of sense. Thank you! :)

noctuid commented 6 years ago

And what you typically want to do here is to slurp in all sexps that belong to progn, and not go beyond that. 99> or just holding > solves that problem nicely.

Since a 0 argument already does this, might it make sense to allow an explicit numerical arg to do this (including 1)? One downside is that this would require refactoring other commands that use lispy-slurp and lispy-barf that shouldn't force slurping extra slurping/barfing.

abo-abo commented 6 years ago

Since a 0 argument already does this, might it make sense to allow an explicit numerical arg to do this (including 1)?

To do what exactly, I don't understand?

noctuid commented 6 years ago

The requested functionality. For example:

((foo)|) bar
;; > (fails; at max)
((foo)|) bar
;; 1> (explict count "forces past max")
((foo bar)|)

If you don't like this as a default, then maybe as an alternative command (which would also prevent the need to change other functions that use lispy-slurp)?

abo-abo commented 6 years ago

then maybe as an alternative command

Should we extend lispy-forward-slurp-sexp (bound to C-) in Paredit key theme)? It does work with multiple levels of nesting yet, but paredit-forward-slurp-sexp does. So I think it's a good idea to have lispy-forward-slurp-sexp mirror this functionality.

noctuid commented 6 years ago

Maybe, but I'd prefer if there was also a command that stayed in special. There could be another command that stays in special, and then lispy-forward-slurp-sexp could call it instead of lispy-slurp.

abo-abo commented 6 years ago

@noctuid Sounds good. Looking forward to PR:)