Disabling ws-butler-before-save hook for sent emails?

What happened?

Hi! I’ve been hunting down an unwanted behavior when sending email using mu4e with Doom: The usual trailing space at the end of the signature delimiter (-- ) gets removed in the sent email, after I press C-c C-c. I’ve tracked it down to a ws-butler-before-save hook being triggered when the file gets saved to disk

Debugger backtrace here:

Backtrace
* delete-horizontal-space()
* ws-butler-clean-region(192 215)
* #<subr F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_2>(chg 192 #<marker at 216 in *draft*>)
* ws-butler-map-changes(#<subr F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_2>)
* ws-butler-before-save()
* funcall(ws-butler-before-save)
* (condition-case e (funcall hook) ((debug error) (signal 'doom-hook-error (list hook e))))
* doom-run-hook(ws-butler-before-save)
* run-hook-wrapped(doom-run-hook ws-butler-before-save)
* (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if (symbolp (car (cdr e))) (symbol-name (car (cdr e))) (car (cdr e))) (car (cdr (cdr e))))) (signal 'doom-hook-error (cons hook (cdr e)))))
* (let ((hook (car --dolist-tail--))) (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if (symbolp (car ...)) (symbol-name (car ...)) (car (cdr e))) (car (cdr (cdr e))))) (signal 'doom-hook-error (cons hook (cdr e))))) (setq --dolist-tail-- (cdr --dolist-tail--)))
* (while --dolist-tail-- (let ((hook (car --dolist-tail--))) (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if (symbolp ...) (symbol-name ...) (car ...)) (car (cdr ...)))) (signal 'doom-hook-error (cons hook (cdr e))))) (setq --dolist-tail-- (cdr --dolist-tail--))))
* (let ((--dolist-tail-- hooks)) (while --dolist-tail-- (let ((hook (car --dolist-tail--))) (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if ... ... ...) (car ...))) (signal 'doom-hook-error (cons hook (cdr e))))) (setq --dolist-tail-- (cdr --dolist-tail--)))))
* doom-run-hooks(before-save-hook)
* apply(doom-run-hooks before-save-hook)
* run-hooks(before-save-hook)
* basic-save-buffer(nil)
* #<subr save-buffer>()
* apply(#<subr save-buffer> nil)
* save-buffer()
* mu4e~setup-fcc-message-sent-hook-fn()
* funcall(mu4e~setup-fcc-message-sent-hook-fn)
* (condition-case e (funcall hook) ((debug error) (signal 'doom-hook-error (list hook e))))
* doom-run-hook(mu4e~setup-fcc-message-sent-hook-fn)
* run-hook-wrapped(doom-run-hook mu4e~setup-fcc-message-sent-hook-fn)
* (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if (symbolp (car (cdr e))) (symbol-name (car (cdr e))) (car (cdr e))) (car (cdr (cdr e))))) (signal 'doom-hook-error (cons hook (cdr e)))))
* (let ((hook (car --dolist-tail--))) (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if (symbolp (car ...)) (symbol-name (car ...)) (car (cdr e))) (car (cdr (cdr e))))) (signal 'doom-hook-error (cons hook (cdr e))))) (setq --dolist-tail-- (cdr --dolist-tail--)))
* (while --dolist-tail-- (let ((hook (car --dolist-tail--))) (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if (symbolp ...) (symbol-name ...) (car ...)) (car (cdr ...)))) (signal 'doom-hook-error (cons hook (cdr e))))) (setq --dolist-tail-- (cdr --dolist-tail--))))
* (let ((--dolist-tail-- hooks)) (while --dolist-tail-- (let ((hook (car --dolist-tail--))) (condition-case e (run-hook-wrapped hook #'doom-run-hook) ((debug doom-hook-error) (if debug-on-error nil (lwarn hook :error "Error running hook %S because: %s" (if ... ... ...) (car ...))) (signal 'doom-hook-error (cons hook (cdr e))))) (setq --dolist-tail-- (cdr --dolist-tail--)))))
* doom-run-hooks(message-send-hook)
* apply(doom-run-hooks message-send-hook)
* run-hooks(message-send-hook)
* apply(run-hooks message-send-hook)
* #<subr message-send>(nil)
* apply(#<subr message-send> nil)
* message-send(nil)
  message-send-and-exit(nil)
  funcall-interactively(message-send-and-exit nil)
  command-execute(message-send-and-exit)

What did you expect to happen?

My emails should be sent as-is, without messing with some trailing whitespace that I want to stay there.

Steps to reproduce

  1. Enable the mu4e module, setup an account, and a signature with mu4e-compose-signature.
  2. Open mu4e and write an email, send it to yourself
  3. The received email (as well as the one placed in your Sent maildir) lack the trailing space of the usual -- signature delimiter.

System information


Loading data dump...

Alright, it turns out I didn’t think about just disabling ws-butler-mode, which does the trick.

(add-hook! mu4e-compose-mode
  (ws-butler-mode -1))

Still, maybe this is something that should be done in Doom directly?

3 Likes