(purecopy (concat "^\\s-*("
(eval-when-compile
(regexp-opt
- '("defgroup" "deftype" "defstruct" "defclass"
- "define-condition" "define-widget" "defface"
- "defpackage") t))
+ '("defgroup" "deftheme" "deftype" "defstruct"
+ "defclass" "define-condition" "define-widget"
+ "defface" "defpackage") t))
"\\s-+'?\\(\\sw\\(\\sw\\|\\s_\\)+\\)"))
2))
(put 'defun* 'doc-string-elt 3)
(put 'defvar 'doc-string-elt 3)
(put 'defcustom 'doc-string-elt 3)
+(put 'deftheme 'doc-string-elt 2)
(put 'defconst 'doc-string-elt 3)
(put 'defmacro 'doc-string-elt 3)
(put 'defmacro* 'doc-string-elt 3)
(put 'define-generic-mode 'doc-string-elt 7)
;; define-global-mode has no explicit docstring.
(put 'easy-mmode-define-global-mode 'doc-string-elt 0)
-(put 'define-ibuffer-filter 'doc-string-elt 3)
+(put 'define-ibuffer-filter 'doc-string-elt 2)
(put 'define-ibuffer-op 'doc-string-elt 3)
-(put 'define-ibuffer-sorter 'doc-string-elt 3)
+(put 'define-ibuffer-sorter 'doc-string-elt 2)
(defun lisp-font-lock-syntactic-face-function (state)
(if (nth 3 state)
(defun last-sexp-setup-props (beg end value alt1 alt2)
"Set up text properties for the output of `eval-last-sexp-1'.
BEG and END are the start and end of the output in current-buffer.
-VALUE is the Lisp value printed, ALT1 and ALT2 are strings for the
+VALUE is the Lisp value printed, ALT1 and ALT2 are strings for the
alternative printed representations that can be displayed."
(let ((map (make-sparse-keymap)))
(define-key map "\C-m" 'last-sexp-toggle-display)
(define-key map [down-mouse-2] 'mouse-set-point)
(define-key map [mouse-2] 'last-sexp-toggle-display)
(add-text-properties
- beg end
+ beg end
`(printed-value (,value ,alt1 ,alt2)
- mouse-face highlight
+ mouse-face highlight
keymap ,map
help-echo "RET, mouse-2: toggle abbreviated display"
rear-nonsticky (mouse-face keymap help-echo
(interactive)
(let ((value (get-text-property (point) 'printed-value)))
(when value
- (let ((beg (or (previous-single-property-change (point) 'printed-value) (point)))
+ (let ((beg (or (previous-single-property-change (min (point-max) (1+ (point)))
+ 'printed-value)
+ (point)))
(end (or (next-single-char-property-change (point) 'printed-value) (point)))
(standard-output (current-buffer))
(point (point)))
(delete-region beg end)
(insert (nth 1 value))
- (last-sexp-setup-props beg (point)
+ (last-sexp-setup-props beg (point)
(nth 0 value)
(nth 2 value)
(nth 1 value))
(goto-char (min (point-max) point))))))
-
(defun eval-last-sexp-1 (eval-last-sexp-arg-internal)
"Evaluate sexp before point; print value in minibuffer.
With argument, print output into current buffer."
(not (null print-level)))
(not (string= unabbreviated
(buffer-substring-no-properties beg end))))
- (last-sexp-setup-props beg end value
+ (last-sexp-setup-props beg end value
unabbreviated
(buffer-substring-no-properties beg end))
))))))
;;;; Lisp paragraph filling commands.
+(defcustom emacs-lisp-docstring-fill-column 65
+ "Value of `fill-column' to use when filling a docstring.
+Any non-integer value means do not use a different value of
+`fill-column' when filling docstrings."
+ :type '(choice (integer)
+ (const :tag "Use the current `fill-column'" t))
+ :group 'lisp)
+
(defun lisp-fill-paragraph (&optional justify)
- "Like \\[fill-paragraph], but handle Emacs Lisp comments.
+ "Like \\[fill-paragraph], but handle Emacs Lisp comments and docstrings.
If any of the current line is a comment, fill the comment or the
paragraph of it that point is in, preserving the comment's indentation
and initial semicolons."
(interactive "P")
- (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))
(defun indent-code-rigidly (start end arg &optional nochange-regexp)
"Indent all lines of code, starting in the region, sideways by ARG columns.