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

Usage of (save-excursion) SF interferes with format-on-save configuration in Clojure/Cider setups #45

Open
nsadeh opened this issue Dec 12, 2023 · 3 comments
Labels

Comments

@nsadeh
Copy link

nsadeh commented Dec 12, 2023

This is technically not a bug in super-save but rather an oddity of (save-excursion), but in my Prelude setup it's coming from super-save so I am wondering if it's possible to tinker with super-save to work around it.

Expected behavior

When triggering super-save hooks with a format-on-save hook ((add-hook 'before-save-hook 'cider-format-buffer) in init.el), the file should format and the cursor should stay in its appropriate place, just like it stays there when you run cider-format-buffer or basic-buffer-save without super-save

Actual behavior

Triggering the super-save hook (e.g., navigating to a different application) saves and formats the document, but the cursor yeets to the beginning of the buffer

Steps to reproduce the problem

  1. Install and setup super-save as per the instructions (or by installing Prelude), and add focus-out to the trigger list
  2. Add (add-hook 'before-save-hook 'cider-format-buffer) to init.el to format on save
  3. Test by manually saving and see that the format hook runs
  4. Test the described behavior by navigating to a different application and returning
  5. The cursor should be at the beginning of the buffer

Environment & Version information

super-save version

Version: 20231209.1044

Emacs version

29.1

Operating system

macOS Sonoma 14.1.2

@nsadeh
Copy link
Author

nsadeh commented Dec 12, 2023

Adding this advice is a workaround:

(defun my-cider-format-before-save ()
  "Function to run `cider-format-buffer` before `super-save-command`."
  (when (and (bound-and-true-p cider-mode)
             (derived-mode-p 'clojure-mode 'clojurescript-mode 'clojurec-mode))
    (cider-format-buffer)))

(advice-add 'super-save-command :before #'my-cider-format-before-save)

I added this to init.el, not sure if that's the correct location but it worked there.

@bbatsov bbatsov added the bug label Dec 12, 2023
@bbatsov
Copy link
Owner

bbatsov commented Dec 12, 2023

Hmm, that's weird. The command that super-save runs to save a buffer is quite simple:

(defun super-save-buffer (buffer)
  "Save BUFFER if needed, super-save style."
  (with-current-buffer buffer
    (save-excursion
      (when (super-save-p)
        (super-save-delete-trailing-whitespace-maybe)
        (if super-save-silent
            (with-temp-message ""
              (let ((inhibit-message t)
                    (inhibit-redisplay t)
                    (message-log-max nil))
                (basic-save-buffer)))
          (basic-save-buffer))))))

That's why it's not immediately clear what causes this weird interaction that you've experienced.

@nsadeh
Copy link
Author

nsadeh commented Dec 12, 2023

Thank you for commenting so fast.

The strange interaction is actually between cider-format-buffer and check-excursion. You can test it by creating an improperly formatted clojure file and running the evaluate expression function on (check-excursion (cider-format-buffer)). Note that running format without check-excursion doesn't yeet the cursor.

I discovered this after setting up a simple pre-save hook to cider-format-buffer my clojure files, then noticed when I click away from Emacs my cursor jumps to the top of the buffer. I am quite new to Emacs having installed it for the first time two days ago, and after sleuthing around found that the interaction between (check-excursion) and (cider-format-buffer) has to do with super-save and my pre-save hook.

Adding an advice before super-save-command fixes that interaction, though, because now cider-format-buffer runs outside of the check-excursion form. You can even keep the pre-save hook in this case for manual saves which I like to do, because now since there's a pre-super-save hook, running format inside check-excursion doesn't do anything (you're running format twice), and since the buffer doesn't change, check-excursion doesn't get confused about where to place the cursor.

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

No branches or pull requests

2 participants