clojure-emacs / cider

The Clojure Interactive Development Environment that Rocks for Emacs
https://cider.mx
GNU General Public License v3.0
3.55k stars 645 forks source link

cider-defun-at-point doesn't work correctly with #_ prefixed forms #2682

Open alexander-yakushev opened 5 years ago

alexander-yakushev commented 5 years ago

Partially related to #2375.

cider-defun-at-point goes completely nuts when invoked from forms prefixed by #_ (or any other data reader for that matter). Here's an example (█ stands for cursor):

#_(foo█)

#_(bar)

(cider-defun-at-point) here returns "#_"! Basically, it returns any form that follows the #-prefixed form we are in; and that might be the desired behavior – but certainly not returning `#`.

bbatsov commented 5 years ago

Likely the underlying problem is somewhere in clojure-mode. We'll figure that out.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution and understanding!

alexander-yakushev commented 5 years ago

Keep it aliiiiiiive 😄!

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution and understanding!

dpsutton commented 4 years ago

Good bump! I had no idea about this and this is my fault.

dpsutton commented 4 years ago

@alexander-yakushev

After looking at this I don't think that I actually broke this but its a bit scary. I messed with this arcane machinery once to handle the top level stuff inside of (comment ...) forms. I think there are some assumptions around beginning-of-defun that are considered invariants and start breaking things if they aren't followed. From the docstring:

If search is successful, return t; point ends up at the beginning of the line where the search succeeded. Otherwise, return nil.

...

Regardless of the values of ‘defun-prompt-regexp’ and ‘beginning-of-defun-function’, point always moves to the beginning of the line whenever the search is successful.

Messing with this stuff can cause havoc from what i remember. One possible workaround is to use

#_
(top level form)

rather than #_ (top level form).

However, you can try this patch to clojure-mode and see if it solves your woes:

diff --git a/clojure-mode.el b/clojure-mode.el
index 91f1410..bf983c5 100644
--- a/clojure-mode.el
+++ b/clojure-mode.el
@@ -2069,7 +2069,8 @@ operators can be used.  Given a positive N it will do it that
 many times."
   (let ((beginning-of-defun-function nil))
     (if (and clojure-toplevel-inside-comment-form
-             (clojure-top-level-form-p "comment"))
+             (or (clojure-top-level-form-p "comment")
+                 (clojure-top-level-form-p "#_")))
         (condition-case nil
             (save-match-data
               (let ((original-position (point))

and then (setq clojure-toplevel-inside-comment-form t) (which you should already be using :) I tried this and it started correct picking up that i wanted the "top level" form after the reader macro rather than what ends up being the previous form. No idea what might happen in tricky situations though.