cider
cider copied to clipboard
cider-eval-list-at-point eval's outer sexp
Expected behavior
On this code (println (+ 1 (* 2 3)))
with the cursor anywhere in (* 2 3) we expect to eval 6, as I understand from: https://github.com/clojure-emacs/cider/pull/2881
This adds a new function cider-eval-list-at-point, that evaluates a list around point [as in: code delimited by the nearest pair of parens surrounding point]
Actual behavior
with the cursor anywhere from * 2 3)
we get 7, from evaling (+ 1 (* 2 3))
, and on the opening (
of (* 2 3)
it evals the outer println
CIDER version information
;; CIDER 1.5.0 (Strasbourg), nREPL 1.0.0
;; Clojure 1.11.1, Java 17.0.5
Emacs version
28.1
Operating system
Ubuntu 22.04.1 LTS
JDK distribution
OpenJDK 64-Bit Server VM Temurin-17.0.5+8
it seems this is something to do with evil mode, if I turn off evil mode cider-eval-list-at-point works as expected
I found this thread talking about similar behaviour with evil/cider: https://www.reddit.com/r/emacs/comments/10f3eff/comment/j4wrt6t/
they link this source which is where evil is modifying the last-sexp behaviour: https://github.com/emacs-evil/evil/blob/8a05eb99c6ee60eb502a2c586fa2e771a513c417/evil-integration.el#L241-L251
so if you enable evil-move-beyond-eol
then it disables that and cider-eval-list-at-point
works as expected, but then it has the weird (for vimmers) behaviour of cursor moving one past the end of the line, and you need to position cursor one past what you want to evaluate
I "fixed" it for me by adding 1-
in cider-eval-list-at-point
:
(goto-char (1- (cadr (cider-list-at-point 'bounds))))
obviously I'm not proposing making that change in cider as it'd break non-evil users. I'm new with emacs, maybe someone more experienced can suggest the right way to fix this or the right way for me to get the behaviour I want.
basically I just want three shortcuts, with cursor on foo
in (+ 1 (* 2 foo) 2)
one will eval foo: currently I have set to cider-eval-last-sexp
one will eval (* 2 foo)
: currently I have set to cider-eval-list-at-point
with this hacky 1-
patch
and one will eval base form, set to cider-eval-defun-at-point
also the one other behaviour I miss from vim was be able to eval mark, so if I'm editing some function, and have some code that calls into the function, I can mark the code that calls the function, and then eval mark while editing the function to test it, without having to move back and forth. I don't know if that's possible or easy to configure here.
Feel free to close this issue cause it's really with evil mode and not cider, but maybe there is other cider users with evil mode that can suggest how to fix this
that 1-
doesn't even fix it in evil mode, as then it doesn't work right in insert mode or inside strings. I have a new try for a fix, that I'm not sure if it's the right change to make but at least this I've tested and behaves as it should in evil whatever mode normal or insert, and also behaves correctly for normal users without evil mode:
in cider-eval-list-at-point
I remove:
(goto-char (cadr (cider-list-at-point 'bounds)))
(cider-eval-last-sexp output-to-current-buffer)))
and replace with:
(skip-chars-forward "^)")
(cider-eval-sexp-up-to-point output-to-current-buffer)
And I think this is actually a minor improvement, as previously cider-eval-list-at-point
would eval a string or [] or {} if you were inside them, rather than evaluating the surrounding parens. strings or vec/map are data literals you generally already see them in your source and what you actually want to eval in repl is the surrounding function, this is also the behaviour the docstring implies:
Evaluate the list (eg. a function call, surrounded by parens) around point.
Edit: oops, I can't just goto to next ), I have goto next matching ), I changed (skip-chars-forward "^)")
to (evil-next-close-paren)
, I can't find if emacs/cider has an easy function to go to next matching close paren (just sexp that also includes ] } etc) that works without evil
I think there are just sexp-based helper functions currently.