"define-compiler-macro" "define-modify-macro"
"defsetf" "define-setf-expander"
"define-method-combination"
- "defgeneric" "defmethod") t)
- "\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)")))
+ "defgeneric" "defmethod") t))
+ "\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)"))
2)
(list (purecopy "Variables")
(purecopy (concat "^\\s-*("
(eval-when-compile
(regexp-opt
'("defvar" "defconst" "defconstant" "defcustom"
- "defparameter" "define-symbol-macro") t)
- "\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)")))
+ "defparameter" "define-symbol-macro") t))
+ "\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)"))
2)
(list (purecopy "Types")
(purecopy (concat "^\\s-*("
(eval-when-compile
(regexp-opt
- '("defgroup" "deftype" "defstruct" "defclass"
- "define-condition" "define-widget" "defface"
- "defpackage") t)
- "\\s-+'?\\(\\sw\\(\\sw\\|\\s_\\)+\\)")))
+ '("defgroup" "deftheme" "deftype" "defstruct"
+ "defclass" "define-condition" "define-widget"
+ "defface" "defpackage") t))
+ "\\s-+'?\\(\\sw\\(\\sw\\|\\s_\\)+\\)"))
2))
"Imenu generic expression for Lisp mode. See `imenu-generic-expression'.")
(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 'defsubst 'doc-string-elt 3)
(put 'define-skeleton 'doc-string-elt 2)
(put 'define-derived-mode 'doc-string-elt 4)
(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 2)
+(put 'define-ibuffer-op 'doc-string-elt 3)
+(put 'define-ibuffer-sorter 'doc-string-elt 2)
(defun lisp-font-lock-syntactic-face-function (state)
(if (nth 3 state)
;; The LISP-SYNTAX argument is used by code in inf-lisp.el and is
;; (uselessly) passed from pp.el, chistory.el, gnus-kill.el and score-mode.el
(defun lisp-mode-variables (&optional lisp-syntax)
- (cond (lisp-syntax
- (set-syntax-table lisp-mode-syntax-table)))
+ (when lisp-syntax
+ (set-syntax-table lisp-mode-syntax-table))
(setq local-abbrev-table lisp-mode-abbrev-table)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat page-delimiter "\\|$" ))
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate paragraph-start)
(make-local-variable 'paragraph-ignore-fill-prefix)
(setq paragraph-ignore-fill-prefix t)
(make-local-variable 'fill-paragraph-function)
;; Adaptive fill mode gets in the way of auto-fill,
;; and should make no difference for explicit fill
;; because lisp-fill-paragraph should do the job.
- (make-local-variable 'adaptive-fill-mode)
- (setq adaptive-fill-mode nil)
+ ;; I believe that newcomment's auto-fill code properly deals with it -stef
+ ;;(set (make-local-variable 'adaptive-fill-mode) nil)
(make-local-variable 'normal-auto-fill-function)
(setq normal-auto-fill-function 'lisp-mode-auto-fill)
(make-local-variable 'indent-line-function)
(setq imenu-generic-expression lisp-imenu-generic-expression)
(make-local-variable 'multibyte-syntax-as-symbol)
(setq multibyte-syntax-as-symbol t)
+ (set (make-local-variable 'syntax-begin-function) 'beginning-of-defun)
(setq font-lock-defaults
'((lisp-font-lock-keywords
lisp-font-lock-keywords-1 lisp-font-lock-keywords-2)
:type 'hook
:group 'lisp)
-(define-derived-mode emacs-lisp-mode nil "Emacs-Lisp"
+(defun emacs-lisp-mode ()
"Major mode for editing Lisp code to run in Emacs.
Commands:
Delete converts tabs to spaces as it moves back.
\\{emacs-lisp-mode-map}
Entry to this mode calls the value of `emacs-lisp-mode-hook'
if that value is non-nil."
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map emacs-lisp-mode-map)
+ (set-syntax-table emacs-lisp-mode-syntax-table)
+ (setq major-mode 'emacs-lisp-mode)
+ (setq mode-name "Emacs-Lisp")
(lisp-mode-variables)
- (setq imenu-case-fold-search nil))
+ (setq imenu-case-fold-search nil)
+ (run-hooks 'emacs-lisp-mode-hook))
(defvar lisp-mode-map
(let ((map (make-sparse-keymap)))
"Keymap for ordinary Lisp mode.
All commands in `lisp-mode-shared-map' are inherited by this map.")
-(define-derived-mode lisp-mode nil "Lisp"
+(defun lisp-mode ()
"Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
Commands:
Delete converts tabs to spaces as it moves back.
Entry to this mode calls the value of `lisp-mode-hook'
if that value is non-nil."
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map lisp-mode-map)
+ (setq major-mode 'lisp-mode)
+ (setq mode-name "Lisp")
(lisp-mode-variables)
- (set (make-local-variable 'comment-start-skip)
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip
"\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(;+\\|#|\\) *")
- (set (make-local-variable 'font-lock-keywords-case-fold-search) t)
- (setq imenu-case-fold-search t))
+ (make-local-variable 'font-lock-keywords-case-fold-search)
+ (setq font-lock-keywords-case-fold-search t)
+ (setq imenu-case-fold-search t)
+ (set-syntax-table lisp-mode-syntax-table)
+ (run-hooks 'lisp-mode-hook))
;; This will do unless inf-lisp.el is loaded.
(defun lisp-eval-defun (&optional and-go)
"Keymap for Lisp Interaction mode.
All commands in `lisp-mode-shared-map' are inherited by this map.")
+(defvar lisp-interaction-mode-abbrev-table lisp-mode-abbrev-table)
(define-derived-mode lisp-interaction-mode emacs-lisp-mode "Lisp Interaction"
"Major mode for typing and evaluating Lisp forms.
Like Lisp mode except that \\[eval-print-last-sexp] evals the Lisp expression
before point, and prints its value into the buffer, advancing point.
-Note that printing is controled by `eval-expression-print-length'
+Note that printing is controlled by `eval-expression-print-length'
and `eval-expression-print-level'.
Commands:
(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."
(print-level eval-expression-print-level)
(beg (point))
end)
- (prin1 value)
- (setq end (point))
- (when (and (bufferp standard-output)
- (or (not (null print-length))
- (not (null print-level)))
- (not (string= unabbreviated
- (buffer-substring-no-properties beg end))))
- (last-sexp-setup-props beg end value
- unabbreviated
- (buffer-substring-no-properties beg end))
- )))))
+ (prog1
+ (prin1 value)
+ (setq end (point))
+ (when (and (bufferp standard-output)
+ (or (not (null print-length))
+ (not (null print-level)))
+ (not (string= unabbreviated
+ (buffer-substring-no-properties beg end))))
+ (last-sexp-setup-props beg end value
+ unabbreviated
+ (buffer-substring-no-properties beg end))
+ ))))))
(defun eval-last-sexp (eval-last-sexp-arg-internal)
Likewise for other constructs as necessary."
;; The code in edebug-defun should be consistent with this, but not
;; the same, since this gets a macroexpended form.
- (cond ((and (eq (car form) 'defvar)
+ (cond ((not (listp form))
+ form)
+ ((and (eq (car form) 'defvar)
(cdr-safe (cdr-safe form)))
;; Force variable to be bound.
(cons 'defconst (cdr form)))
(max (if (bolp) 0 (1+ (current-column)))
comment-column))))
+;; This function just forces a more costly detection of comments (using
+;; parse-partial-sexp from beginning-of-defun). I.e. It avoids the problem of
+;; taking a `;' inside a string started on another line for a comment starter.
+;; Note: `newcomment' gets it right in 99% of the cases if you're using
+;; font-lock, anyway, so we could get rid of it. -stef
(defun lisp-mode-auto-fill ()
(if (> (current-column) (current-fill-column))
(if (save-excursion
- (nth 4 (parse-partial-sexp (save-excursion
- (beginning-of-defun)
- (point))
- (point))))
+ (nth 4 (syntax-ppss (point))))
(do-auto-fill)
- (let ((comment-start nil) (comment-start-skip nil))
- (do-auto-fill)))))
+ (unless (and (boundp 'comment-auto-fill-only-comments)
+ comment-auto-fill-only-comments)
+ (let ((comment-start nil) (comment-start-skip nil))
+ (do-auto-fill))))))
(defvar lisp-indent-offset nil
"If non-nil, indent second line of expressions that many more columns.")
normal-indent))))))
(defun lisp-indent-function (indent-point state)
+ "This function is the normal value of the variable `lisp-indent-function'.
+It is used when indenting a line within a function call, to see if the
+called function says anything special about how to indent the line.
+
+INDENT-POINT is the position where the user typed TAB, or equivalent.
+Point is located at the point to indent under (for default indentation);
+STATE is the `parse-partial-sexp' state for that position.
+
+If the current line is in a call to a Lisp function
+which has a non-nil property `lisp-indent-function',
+that specifies how to do the indentation. The property value can be
+* `defun', meaning indent `defun'-style;
+* an integer N, meaning indent the first N arguments specially
+like ordinary function arguments and then indent any further
+aruments like a body;
+* a function to call just as this function was called.
+If that function returns nil, that means it doesn't specify
+the indentation.
+
+This function also returns nil meaning don't specify the indentation."
(let ((normal-indent (current-column)))
(goto-char (1+ (elt state 1)))
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
(if (and (elt state 2)
(not (looking-at "\\sw\\|\\s_")))
- ;; car of form doesn't seem to be a a symbol
+ ;; car of form doesn't seem to be a symbol
(progn
(if (not (> (save-excursion (forward-line 1) (point))
calculate-lisp-indent-last-sexp))
(put 'let* 'lisp-indent-function 1)
(put 'while 'lisp-indent-function 1)
(put 'if 'lisp-indent-function 2)
+(put 'read-if 'lisp-indent-function 2)
(put 'catch 'lisp-indent-function 1)
(put 'condition-case 'lisp-indent-function 2)
(put 'unwind-protect 'lisp-indent-function 1)
;;;; 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.
- ((condition-case nil
- (save-restriction
- (narrow-to-region (point-min)
- (save-excursion (end-of-line) (point)))
- (while (not (looking-at ";\\|$"))
- (skip-chars-forward "^;\n\"\\\\?")
- (cond
- ((eq (char-after (point)) ?\\) (forward-char 2))
- ((memq (char-after (point)) '(?\" ??)) (forward-sexp 1))))
- (looking-at ";+[\t ]*"))
- (error nil))
- (setq has-comment t has-code-and-comment t)
- (setq comment-fill-prefix
- (concat (make-string (/ (current-column) 8) ?\t)
- (make-string (% (current-column) 8) ?\ )
- (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-*[\(;:\"]")))
- (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.