;;; lisp-mode.el --- Lisp mode, and its idiosyncratic commands.
-;; Copyright (C) 1985 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: lisp, languages
(setq i (1+ i)))
(modify-syntax-entry ? " " emacs-lisp-mode-syntax-table)
(modify-syntax-entry ?\t " " emacs-lisp-mode-syntax-table)
+ (modify-syntax-entry ?\f " " emacs-lisp-mode-syntax-table)
(modify-syntax-entry ?\n "> " emacs-lisp-mode-syntax-table)
;; Give CR the same syntax as newline, for selective-display.
(modify-syntax-entry ?\^m "> " emacs-lisp-mode-syntax-table)
(defvar lisp-imenu-generic-expression
'(
(nil
- "^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\\s-+\\([-A-Za-z0-9+]+\\)" 2)
+ "^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\\s-+\\([-A-Za-z0-9+*|:/]+\\)" 2)
("Variables"
- "^\\s-*(def\\(var\\|const\\)\\s-+\\([-A-Za-z0-9+]+\\)" 2)
+ "^\\s-*(def\\(var\\|const\\|custom\\)\\s-+\\([-A-Za-z0-9+*|:/]+\\)" 2)
("Types"
- "^\\s-*(def\\(type\\|struct\\|class\\|ine-condition\\)\\s-+\\([-A-Za-z0-9+]+\\)"
+ "^\\s-*(def\\(group\\|type\\|struct\\|class\\|ine-condition\\)\\s-+\\([-A-Za-z0-9+*|:/]+\\)"
2))
"Imenu generic expression for Lisp mode. See `imenu-generic-expression'.")
;; because lisp-fill-paragraph should do the job.
(make-local-variable 'adaptive-fill-mode)
(setq 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 indent-line-function 'lisp-indent-line)
(make-local-variable 'indent-region-function)
(make-local-variable 'comment-start)
(setq comment-start ";")
(make-local-variable 'comment-start-skip)
- (setq comment-start-skip ";+ *")
+ ;; Look within the line for a ; following an even number of backslashes
+ ;; after either a non-backslash or the line beginning.
+ (setq comment-start-skip "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *")
(make-local-variable 'comment-column)
(setq comment-column 40)
(make-local-variable 'comment-indent-function)
(setq major-mode 'emacs-lisp-mode)
(setq mode-name "Emacs-Lisp")
(lisp-mode-variables nil)
+ (setq imenu-case-fold-search nil)
(run-hooks 'emacs-lisp-mode-hook))
(defvar lisp-mode-map ()
(setq major-mode 'lisp-mode)
(setq mode-name "Lisp")
(lisp-mode-variables t)
+ (setq imenu-case-fold-search t)
(set-syntax-table lisp-mode-syntax-table)
(run-hooks 'lisp-mode-hook))
"Evaluate sexp before point; print value in minibuffer.
With argument, print output into current buffer."
(interactive "P")
- (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t))
- (opoint (point)))
- (prin1 (let ((stab (syntax-table)))
- (eval (unwind-protect
+ (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t)))
+ (prin1 (eval (let ((stab (syntax-table))
+ (opoint (point))
+ ignore-quotes
+ expr)
+ (unwind-protect
(save-excursion
(set-syntax-table emacs-lisp-mode-syntax-table)
+ ;; If this sexp appears to be enclosed in `...'
+ ;; then ignore the surrounding quotes.
+ (setq ignore-quotes
+ (or (eq (following-char) ?\')
+ (eq (preceding-char) ?\')))
(forward-sexp -1)
(save-restriction
+ ;; vladimir@cs.ualberta.ca 30-Jul-1997: skip ` in
+ ;; `variable' so that the value is returned, not the
+ ;; name
+ (if (and ignore-quotes
+ (eq (following-char) ?`))
+ (forward-char))
(narrow-to-region (point-min) opoint)
- (read (current-buffer))))
+ (setq expr (read (current-buffer)))
+ ;; If it's an (interactive ...) form, it's more
+ ;; useful to show how an interactive call would
+ ;; use it.
+ (and (consp expr)
+ (eq (car expr) 'interactive)
+ (setq expr
+ (list 'call-interactively
+ (list 'quote
+ (list 'lambda
+ '(&rest args)
+ expr
+ 'args)))))
+ expr))
(set-syntax-table stab)))))))
(defun eval-defun (eval-defun-arg-internal)
(end-of-defun)
(beginning-of-defun)
(read (current-buffer)))))
- (if (and (eq (car form) 'defvar)
- (cdr-safe (cdr-safe form)))
- (setq form (cons 'defconst (cdr form))))
+ (cond ((and (eq (car form) 'defvar)
+ (cdr-safe (cdr-safe form)))
+ ;; Force variable to be bound.
+ (setq form (cons 'defconst (cdr form))))
+ ((and (eq (car form) 'defcustom)
+ (default-boundp (nth 1 form)))
+ ;; Force variable to be bound.
+ (set-default (nth 1 form) (eval (nth 2 form)))))
(prin1 (eval form))))
\f
(defun lisp-comment-indent ()
(if (looking-at "\\s<\\s<\\s<")
(current-column)
(if (looking-at "\\s<\\s<")
- (let ((tem (calculate-lisp-indent)))
+ (let ((tem (or (calculate-lisp-indent) (current-column))))
(if (listp tem) (car tem) tem))
(skip-chars-backward " \t")
(max (if (bolp) 0 (1+ (current-column)))
comment-column))))
-(defconst lisp-indent-offset nil "")
-(defconst lisp-indent-function 'lisp-indent-function "")
+(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))))
+ (do-auto-fill)
+ (let ((comment-start nil) (comment-start-skip nil))
+ (do-auto-fill)))))
+
+(defvar lisp-indent-offset nil "")
+(defvar lisp-indent-function 'lisp-indent-function "")
(defun lisp-indent-line (&optional whole-exp)
"Indent current line as Lisp code.
(beginning-of-line)
(setq beg (point))
(skip-chars-forward " \t")
- (if (looking-at "\\s<\\s<\\s<")
- ;; Don't alter indentation of a ;;; comment line.
+ (if (or (null indent) (looking-at "\\s<\\s<\\s<"))
+ ;; Don't alter indentation of a ;;; comment line
+ ;; or a line that starts in a string.
(goto-char (- (point-max) pos))
(if (and (looking-at "\\s<") (not (looking-at "\\s<\\s<")))
;; Single-semicolon comment lines should be indented
(defun calculate-lisp-indent (&optional parse-start)
"Return appropriate indentation for current line as Lisp code.
In usual case returns an integer: the column to indent to.
-Can instead return a list, whose car is the column to indent to.
+If the value is nil, that means don't change the indentation
+because the line starts inside a string.
+
+The value can also be a list of the form (COLUMN CONTAINING-SEXP-START).
This means that following lines at the same level of indentation
-should not necessarily be indented the same way.
-The second element of the list is the buffer position
-of the start of the containing expression."
+should not necessarily be indented the same as this line.
+Then COLUMN is the column to indent to, and CONTAINING-SEXP-START
+is the buffer position of the start of the containing expression."
(save-excursion
(beginning-of-line)
(let ((indent-point (point))
(let ((normal-indent (current-column)))
(cond ((elt state 3)
;; Inside a string, don't change indentation.
- (goto-char indent-point)
- (skip-chars-forward " \t")
- (current-column))
+ nil)
((and (integerp lisp-indent-offset) containing-sexp)
;; Indent by constant offset
(goto-char containing-sexp)
(method
(funcall method state indent-point)))))))
-(defconst lisp-body-indent 2
+(defvar lisp-body-indent 2
"Number of columns to indent the second line of a `(def...)' form.")
(defun lisp-indent-specform (count state indent-point normal-indent)
(put 'save-selected-window 'lisp-indent-function 0)
(put 'save-restriction 'lisp-indent-function 0)
(put 'save-match-data 'lisp-indent-function 0)
+(put 'save-current-buffer 'lisp-indent-function 0)
+(put 'with-current-buffer 'lisp-indent-function 1)
+(put 'combine-after-change-calls 'lisp-indent-function 0)
+(put 'with-output-to-string 'lisp-indent-function 0)
+(put 'with-temp-file 'lisp-indent-function 1)
+(put 'with-temp-buffer 'lisp-indent-function 0)
(put 'let 'lisp-indent-function 1)
(put 'let* 'lisp-indent-function 1)
(put 'while 'lisp-indent-function 1)
(put 'condition-case 'lisp-indent-function 2)
(put 'unwind-protect 'lisp-indent-function 1)
(put 'with-output-to-temp-buffer 'lisp-indent-function 1)
+(put 'eval-after-load 'lisp-indent-function 1)
(defun indent-sexp (&optional endpos)
"Indent each line of the list starting just after point.
(let ((val (calculate-lisp-indent
(if (car indent-stack) (- (car indent-stack))
starting-point))))
- (if (integerp val)
- (setcar indent-stack
- (setq this-indent val))
- (setcar indent-stack (- (car (cdr val))))
- (setq this-indent (car val)))))
- (if (/= (current-column) this-indent)
+ (if (null val)
+ (setq this-indent val)
+ (if (integerp val)
+ (setcar indent-stack
+ (setq this-indent val))
+ (setcar indent-stack (- (car (cdr val))))
+ (setq this-indent (car val))))))
+ (if (and this-indent (/= (current-column) this-indent))
(progn (delete-region bol (point))
(indent-to this-indent)))))
(or outer-loop-done
;; 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
)
((memq (char-after (point)) '(?\" ??)) (forward-sexp 1))))
(looking-at ";+[\t ]*"))
(error nil))
- (setq has-comment t)
+ (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) ?\ )
(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)))
- (beg (progn (backward-paragraph) (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
(re-search-forward comment-start-skip)
(point))))))))
t))
-
\f
(defun indent-code-rigidly (start end arg &optional nochange-regexp)
"Indent all lines of code, starting in the region, sideways by ARG columns.