- (let (
- ;; Non-nil if the current line contains a comment.
- has-comment
-
- ;; Non-nil if the current line contains code and a comment.
- has-code-and-comment
-
- ;; If has-comment, the appropriate fill-prefix for the comment.
- comment-fill-prefix
- )
-
- ;; Figure out what kind of comment we are looking at.
- (save-excursion
- (beginning-of-line)
- (cond
-
- ;; A line with nothing but a comment on it?
- ((looking-at "[ \t]*;[; \t]*")
- (setq has-comment t
- comment-fill-prefix (buffer-substring (match-beginning 0)
- (match-end 0))))
-
- ;; A line with some code, followed by a comment? Remember that the
- ;; semi which starts the comment shouldn't be part of a string or
- ;; character.
- ((let ((state (syntax-ppss (line-end-position))))
- (when (nth 4 state)
- (goto-char (nth 8 state))
- (looking-at ";+[\t ]*")))
- (setq has-comment t has-code-and-comment t)
- (setq comment-fill-prefix
- (concat (make-string (/ (current-column) tab-width) ?\t)
- (make-string (% (current-column) tab-width) ?\ )
- (buffer-substring (match-beginning 0) (match-end 0)))))))
-
- (if (not has-comment)
- ;; `paragraph-start' is set here (not in the buffer-local
- ;; variable so that `forward-paragraph' et al work as
- ;; expected) so that filling (doc) strings works sensibly.
- ;; Adding the opening paren to avoid the following sexp being
- ;; filled means that sexps generally aren't filled as normal
- ;; text, which is probably sensible. The `;' and `:' stop the
- ;; filled para at following comment lines and keywords
- ;; (typically in `defcustom').
- (let ((paragraph-start (concat paragraph-start
- "\\|\\s-*[\(;:\"]"))
- ;; Avoid filling the first line of docstring.
- (paragraph-separate
- (concat paragraph-separate "\\|\\s-*\".*\\.$")))
- (fill-paragraph justify))
-
- ;; Narrow to include only the comment, and then fill the region.
- (save-excursion
- (save-restriction
- (beginning-of-line)
- (narrow-to-region
- ;; Find the first line we should include in the region to fill.
- (save-excursion
- (while (and (zerop (forward-line -1))
- (looking-at "[ \t]*;")))
- ;; We may have gone too far. Go forward again.
- (or (looking-at ".*;")
- (forward-line 1))
- (point))
- ;; Find the beginning of the first line past the region to fill.
- (save-excursion
- (while (progn (forward-line 1)
- (looking-at "[ \t]*;")))
- (point)))
-
- ;; Lines with only semicolons on them can be paragraph boundaries.
- (let* ((paragraph-start (concat paragraph-start "\\|[ \t;]*$"))
- (paragraph-separate (concat paragraph-start "\\|[ \t;]*$"))
- (paragraph-ignore-fill-prefix nil)
- (fill-prefix comment-fill-prefix)
- (after-line (if has-code-and-comment
- (save-excursion
- (forward-line 1) (point))))
- (end (progn
- (forward-paragraph)
- (or (bolp) (newline 1))
- (point)))
- ;; If this comment starts on a line with code,
- ;; include that like in the filling.
- (beg (progn (backward-paragraph)
- (if (eq (point) after-line)
- (forward-line -1))
- (point))))
- (fill-region-as-paragraph beg end
- justify nil
- (save-excursion
- (goto-char beg)
- (if (looking-at fill-prefix)
- nil
- (re-search-forward comment-start-skip)
- (point))))))))
- t))
+ (or (fill-comment-paragraph justify)
+ ;; Point is on a program line (a line no comment); we are interested
+ ;; particularly in docstring lines.
+ ;;
+ ;; We bind `paragraph-start' and `paragraph-separate' temporarily. They
+ ;; are buffer-local, but we avoid changing them so that they can be set
+ ;; to make `forward-paragraph' and friends do something the user wants.
+ ;;
+ ;; `paragraph-start': The `(' in the character alternative and the
+ ;; left-singlequote plus `(' sequence after the \\| alternative prevent
+ ;; sexps and backquoted sexps that follow a docstring from being filled
+ ;; with the docstring. This setting has the consequence of inhibiting
+ ;; filling many program lines that are not docstrings, which is sensible,
+ ;; because the user probably asked to fill program lines by accident, or
+ ;; expecting indentation (perhaps we should try to do indenting in that
+ ;; case). The `;' and `:' stop the paragraph being filled at following
+ ;; comment lines and at keywords (e.g., in `defcustom'). Left parens are
+ ;; escaped to keep font-locking, filling, & paren matching in the source
+ ;; file happy.
+ ;;
+ ;; `paragraph-separate': A clever regexp distinguishes the first line of
+ ;; a docstring and identifies it as a paragraph separator, so that it
+ ;; won't be filled. (Since the first line of documentation stands alone
+ ;; in some contexts, filling should not alter the contents the author has
+ ;; chosen.) Only the first line of a docstring begins with whitespace
+ ;; and a quotation mark and ends with a period or (rarely) a comma.
+ ;;
+ ;; The `fill-column' is temporarily bound to
+ ;; `emacs-lisp-docstring-fill-column' if that value is an integer.
+ (let ((paragraph-start (concat paragraph-start
+ "\\|\\s-*\\([\(;:\"]\\|`\(\\|#'\(\\)"))
+ (paragraph-separate
+ (concat paragraph-separate "\\|\\s-*\".*[,\\.]$"))
+ (fill-column (if (integerp emacs-lisp-docstring-fill-column)
+ emacs-lisp-docstring-fill-column
+ fill-column)))
+ (fill-paragraph justify))
+ ;; Never return nil.
+ t))