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

Clojure-mode evaling last sexpr not using current char #646

Closed
zmaril opened this issue Feb 20, 2015 · 43 comments
Closed

Clojure-mode evaling last sexpr not using current char #646

zmaril opened this issue Feb 20, 2015 · 43 comments

Comments

@zmaril
Copy link
Contributor

zmaril commented Feb 20, 2015

I'm messing around with spacemacs for clojure development. Way cool! I've been using emacs for a long time and am just now learning vim and modal editing. I'm working on some interactive development stuff and I'm wondering how I can avoid chopping off the last character of the expression I am evaluating. If I do ",es" it doesn't include the current character inside the sexpr it goes back to find. This isn't the case in elisp mode.

For example:

(defn test [a] (+ 1 1)|)

If the selected character is to the right of the | above, then using ",es" will not use the last ) and will return two instead of the new function.

@sbenhaim
Copy link

Bump. This makes it impossible to evaluate the SEXP behind the cursor in normal mode unless you've (setq evil-move-cursor-back nil) to allow the cursor to go past the last character in the line (which is the workaround I'm using for now).

@pesterhazy
Copy link
Contributor

I'm also experiencing this problem. If you set the cursor on the ")" in (+ 5 3) and press ^X^E, you get 8 in lisp-interaction-mode (correctly) and 3 in clojure-mode (incorrectly). (It works fine in insert mode). I'm guessing there some special work-around in place for elisp, but I couldn't find it. Any pointers so I get make an attempt at a fix?

@pesterhazy
Copy link
Contributor

For the benefit of people googling this, the problem is related to cider-eval-last-sexp in conjunction with evil-mode.

@syl20bnr
Copy link
Owner

Can you try with (setq evil-move-cursor-back nil) in your dotspacemacs/config ?
This has the effect that when leaving the insert state the point does not go backward (like the default in Vim). But it should make Vim style more pleasant to use. I wonder if I should set it as default in Spacemacs, on one side it provides a better experience in Emacs, on the other side this is not the Vim default :-(

@pesterhazy
Copy link
Contributor

@syl20bnr Setting (setq evil-move-cursor-back nil) changes the behavior of the cursor -- it moves forward after insert -- but unfortunately it does not change the behavior of ^X^E. I still get 3 in the example above.

@syl20bnr
Copy link
Owner

Ok thank you for the feedback.
With (setq evil-move-cursor-back nil) you'll be able to go beyond the last character of a line though, this is very handy.

@syl20bnr syl20bnr reopened this May 27, 2015
@tuhdo
Copy link
Contributor

tuhdo commented May 27, 2015

I hope that this does not affect holy-mode. The behavior described in this issue is the expected behavior from Emacs users.

@syl20bnr
Copy link
Owner

What behavior ? The difference in behavior between elisp and clojure is expected ?

@tuhdo
Copy link
Contributor

tuhdo commented May 27, 2015

The default behavior in Emacs in any Lisp is that an sexpression is considered last sexpression when point is after its closing parenthesis. For example, (+ 1 1)[] ([] is your cursor), the last sexp is (+ 1 1) but when you move the cursor on the closing parenthesis, the last sexp is 1. This is expected behavior.

@syl20bnr
Copy link
Owner

So we have a bug in elisp.

@geo7
Copy link
Contributor

geo7 commented May 27, 2015

edit

I've just tested this and it's working fine

(if (< 4 5)(message "yes"))

having the cursor on the last paren evaluated that line, whoops


I've been using eLisp a little, and when doing so this is something that I've noticed. That I have to go to the end of the line, add a space exit insert mode and run. Otherwise the cursor will land on the ) last paren and not run the function / line properly. I have heard @tuhdo say this is default behaviour though, so I guessed its just something to do with the Evil / VIm key integration or something.

@tuhdo
Copy link
Contributor

tuhdo commented May 27, 2015

So we have a bug in elisp.

Which bug? In Emacs, it is expected the way I described and it should stick with holy-mode. The fix should only apply for Vim.

@geo7
Copy link
Contributor

geo7 commented May 27, 2015

@tuhdo I've just tested this out and it worked fine actually!

(if (< 4 5)(message "yes"))

having the cursor on the last paren evaluated that line

@tuhdo
Copy link
Contributor

tuhdo commented May 27, 2015

The expected behavior in holy-mode and stock Emacs point must be after the last parentheses to evaluate the if. Currently, it works that way in Emacs state but if this is to be fix in Clojure, it should be fixed only for Vim editing style.

@syl20bnr
Copy link
Owner

.....

There is a different behavior in elisp and clojure, when one is true it
implies that the other is not.

@tuhdo you say that clojure behavior is expected then elisp has a bug, they
should both behaves similarly. The style does not matter, just the
behavior, if in holy-mode everything is perfect then only vim style has to
be fixed.

Le mercredi 27 mai 2015, Tu Do notifications@github.com a écrit :

The expected behavior in holy-mode and stock Emacs point must be after
the last parentheses to evaluate the if. Currently, it works that way in
Emacs state but if this is to be fix in Clojure, it should be fixed only
for Vim editing style.


Reply to this email directly or view it on GitHub
#646 (comment).

-syl20bnr-

@tuhdo
Copy link
Contributor

tuhdo commented May 27, 2015

Because Emacs users write these Lisp packages, it is expected to behave the way I described in any Lisp. If Vim users have problem with it, then it should only be fixed when Vim editing style is active, or let Vim users get used to it.

@syl20bnr
Copy link
Owner

I understand what you mean and I won't touch the way Emacs users eval their code.

I just realized that we cannot have consistent behavior between holy-mode and vim because in vim the point cannot go beyond the last character of a line (I never had this trouble because of evil-move-cursor-back set to nil which indeed allow to go beyond the last character).

So in Vim style we will evaluate the sexp with the point included everywhere. In holy-mode we don't touch anything and eval the sexp before the point.

@syl20bnr
Copy link
Owner

But............ we will have inconsistencies with insert state.

Argh....... tough tough decision.

I can set evil-move-cursor-back to nil by default and have consistent behavior possible but Vim users will complain because this is not the default setting in Vim.

@CestDiego
Copy link
Contributor

@syl20bnr is there a way to set the evil-cursor-back only before doing , e e or evaluating last s-exp? If a user wants to get out of the parens he does a or A.

The probelm it seems is that...even though the cursor is at the paren, Emacs interpretes the cursor as being on the left.

@syl20bnr
Copy link
Owner

@CestDiego You are onto something. I bet there is some code in Evil to specifically evaluate last-sexp while being on the parenthesis instead of after to fix the end of line issue.

@CestDiego
Copy link
Contributor

@syl20bnr but currently it works in emacs lisp! D:

@CestDiego
Copy link
Contributor

alt

@syl20bnr
Copy link
Owner

What's working ? :p

on the parenthesis ? after the parenthesis ?

@pesterhazy
Copy link
Contributor

I think the code where evil is monkey-patching the "last-sexp" functions is here: https://github.com/emacsmirror/evil/blob/3aef97498926100c4c7e5f335dd32d49ef0c56a1/evil-integration.el#L315-L330

@syl20bnr
Copy link
Owner

@pesterhazy 👍

So I would go with another solution than the Evil one for this issue, that is:

  • don't hack eval-last-sexp or related functions
  • allow to go beyond the last character of the line

Since it diverges a bit from Vim I doubt it can be OK to propose it to Evil maintainer, but in Spacemacs we can do it.

@pesterhazy
Copy link
Contributor

The following advice seems to fix it for me:

(defadvice cider-last-sexp (around evil activate)
  "In normal-state or motion-state, last sexp ends at point."
  (if (or (evil-normal-state-p) (evil-motion-state-p))
      (save-excursion
        (unless (or (eobp) (eolp)) (forward-char))
        ad-do-it)
    ad-do-it))

Note that I don't really know elisp and hadn't heard the term advice applied to lisp as of 15 min ago.

@syl20bnr
Copy link
Owner

if you known python advice are some kind of decorators.

@syl20bnr
Copy link
Owner

@pesterhazy so we have a solution for the second fix possibility 👍

I still like to investigate the other possibility though.

@pesterhazy
Copy link
Contributor

I just tried it in stock emacs and, true enough, it evaluates to 3 when you set the cursor on the closing parens (in my example). I didn't expect that, and it seems counter-intuitive to me (is there a reason for this?). However, as it's emacs's default behavior and as emacs is the king of lisp, spacemacs should probably behave in the same way (eval sexp before the cursor).

That also means that the cursor should be able to go behind the last character in the line, as it does when you press A (append).

@pesterhazy
Copy link
Contributor

I suppose it makes more sense if (setq cursor-type 'bar). Anyway I'm convinced that eval-stuff-before-cursor is the behavior to use. However, I have no idea to make the cursor go beyond the last char with evil.

@pesterhazy
Copy link
Contributor

Huh, now I understand what you were saying in the first place; (setq evil-move-cursor-back nil) allows you to move behind the last character of the line, so it does restore functionality for Clojure (i.e. make it possible to eval sexps that end on the last character of the line).

@CestDiego
Copy link
Contributor

@syl20bnr If I remember correctly it was this before or after the cursor thing that multiple-cursors didn't work :O

@syl20bnr
Copy link
Owner

PR submitted to allow to set the point beyond the last character of a line and to have regular eval-sexp everywhere in Emacs: https://bitbucket.org/lyro/evil/pull-request/13/add-new-configuration-variable-evil-move/diff

@CestDiego
Copy link
Contributor

has this gotten any attention from the evil mantainers upstream? D:

@syl20bnr
Copy link
Owner

syl20bnr commented Jul 4, 2015

I proposed a PR which got merged, it is a new variable to get the emacs
default behavior by allowing the cursor to go past the last character of
the line independently of settings move-cursor-back to nil. I don't
remember the name of the variable and I don't think I have set it up in
Spacemacs yet. I'll check when I can :-)

Le samedi 4 juillet 2015, Diego Berrocal notifications@github.com a
écrit :

has this gotten any attention from the evil mantainers? D:


Reply to this email directly or view it on GitHub
#646 (comment).

-syl20bnr-

@CestDiego
Copy link
Contributor

I just realised evil mantainers doesn't sound good hahaha :) great work :)

@Gonzih
Copy link
Contributor

Gonzih commented Jul 9, 2015

Hi guys, was poking with same problem. And spotted this issue.

How can I use this new vaiable? Is it avaiable at the current stable release? Where should I define it?
Thank you for answering my annoying questions :)

@Gonzih
Copy link
Contributor

Gonzih commented Jul 9, 2015

As far as I understand solution by @syl20bnr is to allow to move cursor behind end of the line.
Is it possible to introduce keybinding for the "current sexp" in cider? I still preffer this functionality over moving cursor one char beyong current sexp to evaluate it.

@syl20bnr
Copy link
Owner

It is now possible to move the cursor behind the end character of a line. In emacs-lisp the behavior is back to normal where the evaluated expression corresponds to the expression behind before the point.
This is achieved by setting evil-move-beyond-eol to t which is now the case starting from 0.104.0.

Note that some work remains to be done to fix the $ behavior.

@Gonzih
Copy link
Contributor

Gonzih commented Aug 13, 2015

yay, works great! Thanks a lot!

On 08/12/2015 04:51 AM, Sylvain Benner wrote:

It is now possible to move the cursor behind the end character of a
line. In emacs-lisp the behavior is back to normal where the evaluated
expression corresponds to the expression /behind/ point.
This is achieved by setting |evil-move-beyond-eol| to |t| which is now
the case starting from 0.104.0.

Note that some work remains to be done to fix the |$| behavior.


Reply to this email directly or view it on GitHub
#646 (comment).

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

No branches or pull requests

9 participants