emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Indenting docstrings


From: Stefan Monnier
Subject: Indenting docstrings
Date: Thu, 10 Mar 2022 15:01:55 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux)

As you probably know, the convention in ELisp is to write the content of
docstrings "flush left", since any leading space will be considered part
of the actual docstring which then typically leads to ugly results when
the docstring is displayed *Help* by `C-h o`.

See for example:

https://emacs.stackexchange.com/questions/2887/is-there-a-better-way-to-handle-multiline-docstrings-in-elisp

For those who can't get used to it, here's a minor mode which will
indent the content of docstrings but only on the display, without
affecting the actual buffer.


        Stefan


(define-minor-mode elisp-indent-docstrings-mode
  "If non-nil, docstrings are displayed with extra indentation."
  :global t
  (funcall (if elisp-indent-docstrings-mode
               #'add-hook #'remove-hook)
           'emacs-lisp-mode-hook
           #'elisp--add-indent-docstring-font-lock-rule)
  (when elisp-indent-docstrings-mode
    (dolist (buf (buffer-list))
      (with-current-buffer buf
        (when (derived-mode-p 'emacs-lisp-mode)
          (elisp--add-indent-docstring-font-lock-rule))))))

(defun elisp--add-indent-docstring-font-lock-rule ()
  (font-lock-add-keywords nil '((elisp--indent-docstrings)) 'append)
  (font-lock-flush)
  (push 'line-prefix font-lock-extra-managed-props))

(defun elisp--indent-docstrings (limit)
  (when elisp-indent-docstrings-mode
    (let ((pos nil))
      (while (and (< (point) limit)
                  (setq pos (text-property-any (point) limit
                                               'face 'font-lock-doc-face)))
        (goto-char pos)
        (let* ((ppss (syntax-ppss))
               (start (or (nth 8 ppss) pos))
               (indent (save-excursion
                         (goto-char start)
                         (when (and (eq (char-after) ?\")
                                    (not (eq (char-after (1+ (point))) ?\\)))
                           (1+ (current-column)))))
               (display (when indent (concat ;; "\n"
                                             (make-string indent ?\s))))
               (end (or (text-property-not-all (point) limit
                                               'face 'font-lock-doc-face)
                        limit)))
          (if (not display)
              (goto-char end)
            (while (re-search-forward "^." end 'move)
              (put-text-property (match-beginning 0) (1+ (match-beginning 0))
                                 'line-prefix display)))))))
  nil)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]