Of course a my-defun
macro is the easy way out.
But a simpler solution would be
(advice-add 'eval-when-compile :filter-return
(lambda (exp)
(if (and (eq 'quote (car-safe exp))
(stringp (cadr exp)))
(cadr exp)
exp)))
Which should make your trick work, at least in all the cases where the function is macroexpanded before it's actually defined, which should include the main use cases (e.g. if it'sloaded from a file, if it's byte-compiled, or if it's defined via M-C-x
).
Still, this won't fix all the existing code, so maybe a better answer is something like:
;; -*- lexical-binding:t -*-
(defun my-shift-docstrings (orig ppss)
(let ((face (funcall orig ppss)))
(when (eq face 'font-lock-doc-face)
(save-excursion
(let ((start (point)))
(parse-partial-sexp (point) (point-max) nil nil ppss 'syntax-table)
(while (search-backward "\n" start t)
(put-text-property (point) (1+ (point)) 'display
(propertize "\n " 'cursor 0))))))
face))
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(font-lock-mode 1)
(push 'display font-lock-extra-managed-props)
(add-function :around (local 'font-lock-syntactic-face-function)
#'my-shift-docstrings)))
which should just shift the docstrings by 2 spaces, but only on the display side, without affecting the buffer's actual content.