Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sp-{forward,backward}-sexp should not jump up if there's nothing to jump over #1038

Closed
mathrick opened this issue Jun 8, 2020 · 5 comments · May be fixed by #1159
Closed

sp-{forward,backward}-sexp should not jump up if there's nothing to jump over #1038

mathrick opened this issue Jun 8, 2020 · 5 comments · May be fixed by #1159

Comments

@mathrick
Copy link
Contributor

mathrick commented Jun 8, 2020

Expected behavior

If sp-{forward,backward}-sexp (and all their related sister functions) is invoked in a position where there are no more balanced expressions to skip over, it should fail and not move the point. This is what built-in {forward,backward}-sexp does. Ie.

(foo (bar baz|))(foo (bar baz|))
=> forward-sexp: Scan error: "Containing expression ends prematurely", 387735, 387736

Admittedly, that's not a particularly helpful message, but the resulting behaviour is exactly as expected.

Actual behavior

It jumps up a level and starts operating on sexps there. This is documented as being so with no way to disable that fallback:

"Move forward across one balanced expression.
[...] If there is no forward expression, jump out of the current one (effectively doing sp-up-sexp).

This seems like it was meant as a convenience, but it effectively means the command will never stop doing things until it hits the end of file. That is a big problem because it means I now have to watch it closely and can't rely on it to tell me when I hit the end of the enclosing sexp, which defeats the purpose of having a structured navigation command do the paren matching for me. It's even more of a problem when writing code that uses it, as the result will silently change to something vastly different than what the promise was. In fact, I discovered the "fallback" when creating a keyboard macro to do some ad-hoc reformatting of a long list, as normally I can just hold F4 till it runs out of things to edit, since macros abort whenever a command fails, but with smartparens commands it just started applying the same commands in unrelated parts of the buffer.

As far as I can tell, the behaviour seems to be baked into sp-get-thing, so unless I'm mistaken, there's no way for any client code to reliably tell when it's at the end of an enclosed sexp?

Environment & version information

  • smartparens version: 20200324.2147
  • Active major-mode: emacs-lisp-mode
  • Smartparens strict mode: t
  • Emacs version (M-x emacs-version): GNU Emacs 26.3 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.14) of 2020-03-26, modified by Debian
  • Starterkit/Distribution: Ubuntu
  • OS: gnu/linux
@Fuco1
Copy link
Owner

Fuco1 commented Oct 7, 2020

You are right, this is a "feature" and has been since the very beginning. For some reason I didn't really like the default behaviour.

I think it should be possible to tweak the code somewhere to allow what you are proposing though.

The function sp-forward-parallel-sexp does what you want except it loops back to the beginning of the containing list when at the end. We could add a setting which would throw a user-error instead of looping.

We can't change sp-forward-sexp behaviour as it is relied in other code. We could maybe change it for interactive calls where it could fall back to sp-forward-parellel-sexp.

@joswik
Copy link

joswik commented Apr 29, 2021

I was going to ask that same question - and found this!
I've come across both functions - standard forward-sexp and sp-forward-parallel-sexp, but don't like either.
My wish is that cursor to simply stop at last sexp without any errors,
and then I am to decide whether to exit level (sp-up-sexp) or start all over again at the same level (sp-down-sexp).
Standard forward-sexp throws error (as OP's example shows) and I don't want to see any errors.

Wrt. sp-forward-parallel-sexp - I want to stop and see the last sexp at this level,
but this function wraps around and suddenly jumps behind first sexp which can be very far from the start of that level.
Also, after that it's not possible to quickly jump back to the end (sp-backward-down-sexp),
because it would descend one level down in that first sexp.

Could you just define a completely new function like sp-forward-parallel-sexp,
so 'If calling `sp-forward-sexp' at point would result in raising a level up' just do nothing?

Thanks!

@Fuco1
Copy link
Owner

Fuco1 commented May 29, 2021

To jump back to the end, you can call sp-backward-down-sexp at the beginning of the sexp:

If the point is inside sexp and there is no down expression to
descend to, jump to the end of current one. If moving forward,
jump to beginning of current one.

Similarly sp-down-sexp will jump to beginning if at the end.

There's also sp-end-of-sexp which does this from any position.

Could you just define a completely new function like sp-forward-parallel-sexp,
so 'If calling `sp-forward-sexp' at point would result in raising a level up' just do nothing?

Sure, we just need to keep the current one working as it is in case there are some scripts relying on this behaviour.

@joswik
Copy link

joswik commented Jun 20, 2021 via email

@Fuco1 Fuco1 closed this as completed Jun 28, 2021
@defaultxr
Copy link

Was this ever implemented? Neither sp-forward-sexp nor sp-forward-parallel-sexp seem to stop when reaching the end of the sexp, and I don't see any option for making them do so.

defaultxr added a commit to defaultxr/smartparens that referenced this issue May 3, 2023
This option will cause `sp-forward-parallel-sexp` and
`sp-backward-parallel-sexp` to raise a `user-error` when hitting the
end of the enclosing sexp, rather than looping back to the other
end.

Fixes Fuco1#1038.
defaultxr added a commit to defaultxr/smartparens that referenced this issue May 3, 2023
This option will cause `sp-forward-parallel-sexp` and
`sp-backward-parallel-sexp` to raise a `user-error` when hitting the
end of the enclosing sexp, rather than looping back to the other
end.

Fixes Fuco1#1038.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants