428
+ − 1 ;;; lisp-mode.el --- Lisp mode, and its idiosyncratic commands.
+ − 2
+ − 3 ;; Copyright (C) 1985, 1996, 1997 Free Software Foundation, Inc.
442
+ − 4 ;; Copyright (C) 1995 Tinker Systems.
771
+ − 5 ;; Copyright (C) 2002 Ben Wing.
428
+ − 6
+ − 7 ;; Maintainer: FSF
+ − 8 ;; Keywords: lisp, languages, dumped
+ − 9
+ − 10 ;; This file is part of XEmacs.
+ − 11
+ − 12 ;; XEmacs is free software; you can redistribute it and/or modify it
+ − 13 ;; under the terms of the GNU General Public License as published by
+ − 14 ;; the Free Software Foundation; either version 2, or (at your option)
+ − 15 ;; any later version.
+ − 16
+ − 17 ;; XEmacs is distributed in the hope that it will be useful, but
+ − 18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
+ − 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ − 20 ;; General Public License for more details.
+ − 21
+ − 22 ;; You should have received a copy of the GNU General Public License
+ − 23 ;; along with XEmacs; see the file COPYING. If not, write to the Free
+ − 24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ − 25 ;; 02111-1307, USA.
+ − 26
+ − 27 ;;; Synched up with: FSF 19.34 (but starting to diverge).
+ − 28
+ − 29 ;;; Commentary:
+ − 30
+ − 31 ;; This file is dumped with XEmacs.
+ − 32
+ − 33 ;; The base major mode for editing Lisp code (used also for Emacs Lisp).
+ − 34 ;; This mode is documented in the Emacs manual
+ − 35
+ − 36 ;;; Code:
+ − 37
+ − 38 (defgroup lisp nil
+ − 39 "Lisp support, including Emacs Lisp."
+ − 40 :group 'languages
+ − 41 :group 'development)
+ − 42
+ − 43 (defvar lisp-mode-syntax-table nil)
+ − 44 (defvar emacs-lisp-mode-syntax-table nil)
+ − 45 (defvar lisp-mode-abbrev-table nil)
+ − 46
442
+ − 47 (defun construct-lisp-mode-menu (popup-p emacs-lisp-p)
+ − 48 (flet ((popup-wrap (form)
+ − 49 (if popup-p `(menu-call-at-event ',form) form)))
+ − 50 `(,@(if emacs-lisp-p
+ − 51 `(["%_Byte-Compile This File" ,(popup-wrap
+ − 52 'emacs-lisp-byte-compile)]
+ − 53 ["B%_yte-Compile/Load This File"
+ − 54 ,(popup-wrap 'emacs-lisp-byte-compile-and-load)]
+ − 55 ["Byte-%_Recompile Directory..."
+ − 56 ,(popup-wrap 'byte-recompile-directory)]
+ − 57 "---"))
+ − 58 ["%_Evaluate Region or Defun"
+ − 59 ,(popup-wrap '(if (region-exists-p)
+ − 60 (call-interactively 'eval-region)
+ − 61 (call-interactively 'eval-defun)))]
+ − 62 ["Evaluate %_Whole Buffer" ,(popup-wrap 'eval-current-buffer)]
+ − 63 ["Evaluate Last %_S-expression" ,(popup-wrap 'eval-last-sexp)]
+ − 64 "---"
800
+ − 65 ["%_Indent Region or Balanced Expression"
+ − 66 ,(popup-wrap '(if (region-exists-p)
+ − 67 (call-interactively 'indent-region)
+ − 68 (call-interactively 'indent-sexp)))]
+ − 69 ["I%_ndent Defun"
+ − 70 ,(popup-wrap '(progn
+ − 71 (beginning-of-defun)
+ − 72 (indent-sexp)))]
+ − 73 "---"
+ − 74 ["%_Comment Out Region" comment-region :active (region-exists-p)]
1333
+ − 75 ["Unc%_omment Region" uncomment-region :active (region-exists-p)]
800
+ − 76 "---"
442
+ − 77 ,@(if popup-p
+ − 78 '(["%_Find Function"
+ − 79 (find-function (menu-call-at-event '(function-at-point)))
+ − 80 :suffix (let ((fun (menu-call-at-event '(function-at-point))))
+ − 81 (if fun (symbol-name fun) ""))
+ − 82 :active (and (fboundp 'find-function)
+ − 83 (menu-call-at-event '(function-at-point)))]
+ − 84 ["%_Find Variable"
+ − 85 (find-variable (menu-call-at-event '(variable-at-point)))
+ − 86 :suffix (let ((fun (menu-call-at-event '(variable-at-point))))
+ − 87 (if fun (symbol-name fun) ""))
+ − 88 :active (and (fboundp 'find-variable)
+ − 89 (menu-call-at-event '(variable-at-point)))]
+ − 90 ["%_Help on Function"
+ − 91 (describe-function (menu-call-at-event '(function-at-point)))
+ − 92 :suffix (let ((fun (menu-call-at-event '(function-at-point))))
+ − 93 (if fun (symbol-name fun) ""))
+ − 94 :active (and (fboundp 'describe-function)
+ − 95 (menu-call-at-event '(function-at-point)))]
+ − 96 ["%_Help on Variable"
+ − 97 (describe-variable (menu-call-at-event '(variable-at-point)))
+ − 98 :suffix (let ((fun (menu-call-at-event '(variable-at-point))))
+ − 99 (if fun (symbol-name fun) ""))
+ − 100 :active (and (fboundp 'describe-variable)
+ − 101 (menu-call-at-event '(variable-at-point)))])
+ − 102 '(["Find %_Function..." find-function
+ − 103 :active (fboundp 'find-function)]
+ − 104 ["Find %_Variable..." find-variable
+ − 105 :active (fboundp 'find-variable)]
+ − 106 ["%_Help on Function..." describe-function
+ − 107 :active (fboundp 'describe-function)]
+ − 108 ["Hel%_p on Variable..." describe-variable
+ − 109 :active (fboundp 'describe-variable)]))
+ − 110 "---"
+ − 111 ["Instrument This Defun for %_Debugging" ,(popup-wrap 'edebug-defun)]
+ − 112 ["%_Trace Function..." trace-function-background]
+ − 113 ["%_Untrace All Functions" untrace-all
+ − 114 :active (fboundp 'untrace-all)]
+ − 115 "---"
800
+ − 116 ["Display %_Macro Expansion of Balanced Expression"
+ − 117 ,(popup-wrap 'macroexpand-sexp)]
+ − 118 ["Display Recursive Macro E%_xpansion of Balanced Expression"
+ − 119 ,(popup-wrap 'macroexpand-all-sexp)]
442
+ − 120 "---"
+ − 121 "Look for debug-on-error under Options->Troubleshooting"
+ − 122 )))
428
+ − 123
442
+ − 124 (defvar lisp-interaction-mode-popup-menu
+ − 125 (cons "Lisp-Interaction" (construct-lisp-mode-menu t nil)))
+ − 126
+ − 127 (defvar emacs-lisp-mode-popup-menu
+ − 128 (cons "Emacs-Lisp" (construct-lisp-mode-menu t t)))
428
+ − 129
+ − 130 ;Don't have a menubar entry in Lisp Interaction mode. Otherwise, the
+ − 131 ;*scratch* buffer has a Lisp menubar item! Very confusing.
442
+ − 132 ;Jan Vroonhof really wants this, so it's back. --ben
+ − 133 (defvar lisp-interaction-mode-menubar-menu
+ − 134 (cons "%_Lisp" (construct-lisp-mode-menu nil nil)))
428
+ − 135
442
+ − 136 (defvar emacs-lisp-mode-menubar-menu
+ − 137 (cons "%_Lisp" (construct-lisp-mode-menu nil t)))
428
+ − 138
+ − 139 (if (not emacs-lisp-mode-syntax-table)
+ − 140 (let ((i 0))
+ − 141 (setq emacs-lisp-mode-syntax-table (make-syntax-table))
+ − 142 (while (< i ?0)
+ − 143 (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
+ − 144 (setq i (1+ i)))
+ − 145 (setq i (1+ ?9))
+ − 146 (while (< i ?A)
+ − 147 (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
+ − 148 (setq i (1+ i)))
+ − 149 (setq i (1+ ?Z))
+ − 150 (while (< i ?a)
+ − 151 (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
+ − 152 (setq i (1+ i)))
+ − 153 (setq i (1+ ?z))
+ − 154 (while (< i 128)
+ − 155 (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table)
+ − 156 (setq i (1+ i)))
+ − 157 (modify-syntax-entry ? " " emacs-lisp-mode-syntax-table)
+ − 158 (modify-syntax-entry ?\t " " emacs-lisp-mode-syntax-table)
+ − 159 (modify-syntax-entry ?\f " " emacs-lisp-mode-syntax-table)
+ − 160 (modify-syntax-entry ?\n "> " emacs-lisp-mode-syntax-table)
+ − 161 ;; Give CR the same syntax as newline, for selective-display.
+ − 162 (modify-syntax-entry ?\^m "> " emacs-lisp-mode-syntax-table)
+ − 163 (modify-syntax-entry ?\; "< " emacs-lisp-mode-syntax-table)
+ − 164 (modify-syntax-entry ?` "' " emacs-lisp-mode-syntax-table)
+ − 165 (modify-syntax-entry ?' "' " emacs-lisp-mode-syntax-table)
+ − 166 (modify-syntax-entry ?, "' " emacs-lisp-mode-syntax-table)
+ − 167 ;; Used to be singlequote; changed for flonums.
+ − 168 (modify-syntax-entry ?. "_ " emacs-lisp-mode-syntax-table)
+ − 169 (modify-syntax-entry ?# "' " emacs-lisp-mode-syntax-table)
+ − 170 (modify-syntax-entry ?\" "\" " emacs-lisp-mode-syntax-table)
+ − 171 (modify-syntax-entry ?\\ "\\ " emacs-lisp-mode-syntax-table)
+ − 172 (modify-syntax-entry ?\( "() " emacs-lisp-mode-syntax-table)
+ − 173 (modify-syntax-entry ?\) ")( " emacs-lisp-mode-syntax-table)
+ − 174 (modify-syntax-entry ?\[ "(] " emacs-lisp-mode-syntax-table)
+ − 175 (modify-syntax-entry ?\] ")[ " emacs-lisp-mode-syntax-table)))
+ − 176
+ − 177 (if (not lisp-mode-syntax-table)
+ − 178 (progn (setq lisp-mode-syntax-table
+ − 179 (copy-syntax-table emacs-lisp-mode-syntax-table))
+ − 180 (modify-syntax-entry ?\[ "_ " lisp-mode-syntax-table)
+ − 181 ;; XEmacs changes
+ − 182 (modify-syntax-entry ?\] "_ " lisp-mode-syntax-table)
460
+ − 183 (modify-syntax-entry ?# "' 58" lisp-mode-syntax-table)
+ − 184 (modify-syntax-entry ?| "\" 67" lisp-mode-syntax-table)))
428
+ − 185
+ − 186 (define-abbrev-table 'lisp-mode-abbrev-table ())
+ − 187
+ − 188 (defvar lisp-imenu-generic-expression
+ − 189 '(
+ − 190 (nil
+ − 191 "^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\\s-+\\([-A-Za-z0-9+*|:]+\\)" 2)
+ − 192 ("Variables"
+ − 193 "^\\s-*(def\\(var\\|const\\|custom\\)\\s-+\\([-A-Za-z0-9+*|:]+\\)" 2)
+ − 194 ("Types"
+ − 195 "^\\s-*(def\\(group\\|type\\|struct\\|class\\|ine-condition\\)\\s-+\\([-A-Za-z0-9+*|:]+\\)"
+ − 196 2))
+ − 197
+ − 198 "Imenu generic expression for Lisp mode. See `imenu-generic-expression'.")
+ − 199
+ − 200 (defun lisp-mode-variables (lisp-syntax)
+ − 201 (cond (lisp-syntax
+ − 202 (set-syntax-table lisp-mode-syntax-table)))
+ − 203 (setq local-abbrev-table lisp-mode-abbrev-table)
+ − 204 (make-local-variable 'paragraph-start)
+ − 205 (setq paragraph-start (concat page-delimiter "\\|$" ))
+ − 206 (make-local-variable 'paragraph-separate)
+ − 207 (setq paragraph-separate paragraph-start)
+ − 208 (make-local-variable 'paragraph-ignore-fill-prefix)
+ − 209 (setq paragraph-ignore-fill-prefix t)
+ − 210 (make-local-variable 'fill-paragraph-function)
+ − 211 (setq fill-paragraph-function 'lisp-fill-paragraph)
+ − 212 ;; Adaptive fill mode gets in the way of auto-fill,
+ − 213 ;; and should make no difference for explicit fill
+ − 214 ;; because lisp-fill-paragraph should do the job.
+ − 215 (make-local-variable 'adaptive-fill-mode)
+ − 216 (setq adaptive-fill-mode nil)
+ − 217 (make-local-variable 'indent-line-function)
+ − 218 (setq indent-line-function 'lisp-indent-line)
+ − 219 (make-local-variable 'indent-region-function)
+ − 220 (setq indent-region-function 'lisp-indent-region)
+ − 221 (make-local-variable 'parse-sexp-ignore-comments)
+ − 222 (setq parse-sexp-ignore-comments t)
+ − 223 (make-local-variable 'outline-regexp)
+ − 224 (setq outline-regexp ";;; \\|(....")
+ − 225 (make-local-variable 'comment-start)
+ − 226 (setq comment-start ";")
+ − 227 ;; XEmacs change
+ − 228 (set (make-local-variable 'block-comment-start) ";;")
+ − 229 (make-local-variable 'comment-start-skip)
+ − 230 ;; Look within the line for a ; following an even number of backslashes
+ − 231 ;; after either a non-backslash or the line beginning.
+ − 232 (setq comment-start-skip "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *")
+ − 233 (make-local-variable 'comment-column)
+ − 234 (setq comment-column 40)
+ − 235 (make-local-variable 'comment-indent-function)
+ − 236 (setq comment-indent-function 'lisp-comment-indent)
+ − 237 ;; XEmacs change
+ − 238 (set (make-local-variable 'dabbrev-case-fold-search) nil)
+ − 239 (set (make-local-variable 'dabbrev-case-replace) nil)
+ − 240 (make-local-variable 'imenu-generic-expression)
+ − 241 (setq imenu-generic-expression lisp-imenu-generic-expression))
+ − 242
+ − 243 (defvar shared-lisp-mode-map ()
+ − 244 "Keymap for commands shared by all sorts of Lisp modes.")
+ − 245
+ − 246 (if shared-lisp-mode-map
+ − 247 ()
+ − 248 (setq shared-lisp-mode-map (make-sparse-keymap))
+ − 249 ;; XEmacs changes
+ − 250 (set-keymap-name shared-lisp-mode-map 'shared-lisp-mode-map)
+ − 251 (define-key shared-lisp-mode-map "\M-;" 'lisp-indent-for-comment)
+ − 252 (define-key shared-lisp-mode-map "\e\C-q" 'indent-sexp))
+ − 253
+ − 254 (defvar emacs-lisp-mode-map ()
+ − 255 "Keymap for Emacs Lisp mode.
+ − 256 All commands in `shared-lisp-mode-map' are inherited by this map.")
+ − 257
+ − 258 (if emacs-lisp-mode-map
+ − 259 ()
+ − 260 ;; XEmacs: Ignore FSF nconc stuff
+ − 261 (setq emacs-lisp-mode-map (make-sparse-keymap))
+ − 262 (set-keymap-name emacs-lisp-mode-map 'emacs-lisp-mode-map)
+ − 263 (set-keymap-parents emacs-lisp-mode-map (list shared-lisp-mode-map))
+ − 264 (define-key emacs-lisp-mode-map "\e\t" 'lisp-complete-symbol)
+ − 265 (define-key emacs-lisp-mode-map "\e\C-x" 'eval-defun)
+ − 266 ;; XEmacs: Not sure what the FSF menu bindings are. I hope XEmacs
+ − 267 ;; doesn't need them.
+ − 268 )
+ − 269
1428
+ − 270 ;; XEmacs: add docstrings to the hooks
+ − 271 (defvar emacs-lisp-mode-hook nil
+ − 272 "Hook to run when entering emacs-lisp-mode.")
+ − 273
+ − 274 (defvar lisp-mode-hook nil
+ − 275 "Hook to run when entering lisp-mode.")
+ − 276
+ − 277 (defvar lisp-interaction-mode-hook nil
+ − 278 "Hook to run when entering lisp-interaction-mode.")
+ − 279
428
+ − 280 (defun emacs-lisp-byte-compile ()
+ − 281 "Byte compile the file containing the current buffer."
+ − 282 (interactive)
+ − 283 (if buffer-file-name
+ − 284 ;; XEmacs change. Force buffer save first
+ − 285 (progn
+ − 286 (save-buffer)
+ − 287 (byte-compile-file buffer-file-name))
+ − 288 (error "The buffer must be saved in a file first.")))
+ − 289
+ − 290 (defun emacs-lisp-byte-compile-and-load ()
+ − 291 "Byte-compile the current file (if it has changed), then load compiled code."
+ − 292 (interactive)
+ − 293 (or buffer-file-name
+ − 294 (error "The buffer must be saved in a file first"))
+ − 295 (require 'bytecomp)
+ − 296 ;; Recompile if file or buffer has changed since last compilation.
+ − 297 (if (and (buffer-modified-p)
+ − 298 (y-or-n-p (format "save buffer %s first? " (buffer-name))))
+ − 299 (save-buffer))
+ − 300 (let ((compiled-file-name (byte-compile-dest-file buffer-file-name)))
+ − 301 (if (file-newer-than-file-p compiled-file-name buffer-file-name)
+ − 302 (load-file compiled-file-name)
+ − 303 (byte-compile-file buffer-file-name t))))
+ − 304
+ − 305 (defun emacs-lisp-mode ()
+ − 306 "Major mode for editing Lisp code to run in Emacs.
+ − 307 Commands:
+ − 308 Delete converts tabs to spaces as it moves back.
+ − 309 Blank lines separate paragraphs. Semicolons start comments.
+ − 310 \\{emacs-lisp-mode-map}
+ − 311 Entry to this mode calls the value of `emacs-lisp-mode-hook'
+ − 312 if that value is non-nil."
+ − 313 (interactive)
+ − 314 (kill-all-local-variables)
+ − 315 (use-local-map emacs-lisp-mode-map)
+ − 316 (set-syntax-table emacs-lisp-mode-syntax-table)
+ − 317 ;; XEmacs changes
+ − 318 (setq major-mode 'emacs-lisp-mode
442
+ − 319 mode-popup-menu emacs-lisp-mode-popup-menu
428
+ − 320 mode-name "Emacs-Lisp")
442
+ − 321 (if (and (featurep 'menubar)
+ − 322 current-menubar)
+ − 323 (progn
428
+ − 324 ;; make a local copy of the menubar, so our modes don't
+ − 325 ;; change the global menubar
442
+ − 326 (set-buffer-menubar current-menubar)
+ − 327 (add-submenu nil emacs-lisp-mode-menubar-menu)))
428
+ − 328 (lisp-mode-variables nil)
+ − 329 (run-hooks 'emacs-lisp-mode-hook))
+ − 330
430
+ − 331 (put 'emacs-lisp-mode 'font-lock-lisp-like t)
+ − 332
428
+ − 333 (defvar lisp-mode-map ()
+ − 334 "Keymap for ordinary Lisp mode.
+ − 335 All commands in `shared-lisp-mode-map' are inherited by this map.")
+ − 336
+ − 337 (if lisp-mode-map
+ − 338 ()
+ − 339 ;; XEmacs changes
+ − 340 (setq lisp-mode-map (make-sparse-keymap))
+ − 341 (set-keymap-name lisp-mode-map 'lisp-mode-map)
+ − 342 (set-keymap-parents lisp-mode-map (list shared-lisp-mode-map))
+ − 343 ;; gag, no. use ilisp. -jwz
+ − 344 ;; (define-key lisp-mode-map "\C-c\C-z" 'run-lisp)
+ − 345 )
+ − 346
+ − 347 (defun lisp-mode ()
613
+ − 348 "Major mode for editing Lisp code for Lisps other than Emacs Lisp.
428
+ − 349 Commands:
+ − 350 Delete converts tabs to spaces as it moves back.
+ − 351 Blank lines separate paragraphs. Semicolons start comments.
+ − 352 \\{lisp-mode-map}
+ − 353 Note that `run-lisp' may be used either to start an inferior Lisp job
+ − 354 or to switch back to an existing one.
+ − 355
+ − 356 Entry to this mode calls the value of `lisp-mode-hook'
+ − 357 if that value is non-nil."
+ − 358 (interactive)
+ − 359 (kill-all-local-variables)
+ − 360 (use-local-map lisp-mode-map)
+ − 361 (setq major-mode 'lisp-mode)
+ − 362 (setq mode-name "Lisp")
+ − 363 (lisp-mode-variables t)
+ − 364 (set-syntax-table lisp-mode-syntax-table)
+ − 365 (run-hooks 'lisp-mode-hook))
+ − 366
+ − 367 ;; XEmacs change: emacs-lisp-mode-map is a more appropriate parent.
+ − 368 (defvar lisp-interaction-mode-map ()
+ − 369 "Keymap for Lisp Interaction mode.
+ − 370 All commands in `shared-lisp-mode-map' are inherited by this map.")
+ − 371
+ − 372 (if lisp-interaction-mode-map
+ − 373 ()
+ − 374 ;; XEmacs set keymap our way
+ − 375 (setq lisp-interaction-mode-map (make-sparse-keymap))
+ − 376 (set-keymap-name lisp-interaction-mode-map 'lisp-interaction-mode-map)
+ − 377 (set-keymap-parents lisp-interaction-mode-map (list emacs-lisp-mode-map))
+ − 378 (define-key lisp-interaction-mode-map "\e\C-x" 'eval-defun)
+ − 379 (define-key lisp-interaction-mode-map "\e\t" 'lisp-complete-symbol)
+ − 380 (define-key lisp-interaction-mode-map "\n" 'eval-print-last-sexp))
+ − 381
+ − 382 (defun lisp-interaction-mode ()
+ − 383 "Major mode for typing and evaluating Lisp forms.
+ − 384 Like Lisp mode except that \\[eval-print-last-sexp] evals the Lisp expression
+ − 385 before point, and prints its value into the buffer, advancing point.
+ − 386
+ − 387 Commands:
+ − 388 Delete converts tabs to spaces as it moves back.
+ − 389 Paragraphs are separated only by blank lines.
+ − 390 Semicolons start comments.
+ − 391 \\{lisp-interaction-mode-map}
+ − 392 Entry to this mode calls the value of `lisp-interaction-mode-hook'
+ − 393 if that value is non-nil."
+ − 394 (interactive)
+ − 395 (kill-all-local-variables)
+ − 396 (use-local-map lisp-interaction-mode-map)
+ − 397 (setq major-mode 'lisp-interaction-mode)
+ − 398 (setq mode-name "Lisp Interaction")
442
+ − 399 (setq mode-popup-menu lisp-interaction-mode-popup-menu)
+ − 400 (if (and (featurep 'menubar)
+ − 401 current-menubar)
+ − 402 (progn
+ − 403 ;; make a local copy of the menubar, so our modes don't
+ − 404 ;; change the global menubar
+ − 405 (set-buffer-menubar current-menubar)
+ − 406 (add-submenu nil lisp-interaction-mode-menubar-menu)))
428
+ − 407 (set-syntax-table emacs-lisp-mode-syntax-table)
+ − 408 (lisp-mode-variables nil)
+ − 409 (run-hooks 'lisp-interaction-mode-hook))
+ − 410
+ − 411 (defun eval-print-last-sexp ()
+ − 412 "Evaluate sexp before point; print value into current buffer."
+ − 413 (interactive)
+ − 414 (let ((standard-output (current-buffer)))
+ − 415 (terpri)
+ − 416 (eval-last-sexp t)
+ − 417 (terpri)))
+ − 418
+ − 419 ;; XEmacs change
+ − 420 (defcustom eval-interactive-verbose t
+ − 421 "*Non-nil means that interactive evaluation can print messages.
+ − 422 The messages are printed when the expression is treated differently
2116
+ − 423 using `\\[eval-last-sexp]' and `\\[eval-defun]' than it would have
+ − 424 been treated noninteractively.
428
+ − 425
+ − 426 The printed messages are \"defvar treated as defconst\" and \"defcustom
+ − 427 evaluation forced\". See `eval-interactive' for more details."
+ − 428 :type 'boolean
+ − 429 :group 'lisp)
+ − 430
+ − 431 (defun eval-interactive (expr)
+ − 432 "Like `eval' except that it transforms defvars to defconsts.
+ − 433 The evaluation of defcustom forms is forced."
+ − 434 (cond ((and (eq (car-safe expr) 'defvar)
+ − 435 (> (length expr) 2))
+ − 436 (eval (cons 'defconst (cdr expr)))
+ − 437 (when eval-interactive-verbose
+ − 438 (message "defvar treated as defconst")
+ − 439 (sit-for 1)
+ − 440 (message ""))
+ − 441 (nth 1 expr))
+ − 442 ((and (eq (car-safe expr) 'defcustom)
+ − 443 (> (length expr) 2)
+ − 444 (default-boundp (nth 1 expr)))
+ − 445 ;; Force variable to be bound
+ − 446 ;; #### defcustom might specify a different :set method.
+ − 447 (set-default (nth 1 expr) (eval (nth 2 expr)))
+ − 448 ;; And evaluate the defcustom
+ − 449 (eval expr)
+ − 450 (when eval-interactive-verbose
+ − 451 (message "defcustom evaluation forced")
+ − 452 (sit-for 1)
+ − 453 (message ""))
+ − 454 (nth 1 expr))
+ − 455 (t
+ − 456 (eval expr))))
+ − 457
+ − 458 ;; XEmacs change, based on Bob Weiner suggestion
+ − 459 (defun eval-last-sexp (eval-last-sexp-arg-internal) ;dynamic scoping wonderment
+ − 460 "Evaluate sexp before point; print value in minibuffer.
+ − 461 With argument, print output into current buffer."
+ − 462 (interactive "P")
+ − 463 (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t))
+ − 464 (opoint (point))
+ − 465 ignore-quotes)
+ − 466 (prin1 (eval-interactive
+ − 467 (letf (((syntax-table) emacs-lisp-mode-syntax-table))
+ − 468 (save-excursion
+ − 469 ;; If this sexp appears to be enclosed in `...' then
+ − 470 ;; ignore the surrounding quotes.
+ − 471 (setq ignore-quotes (or (eq (char-after) ?\')
+ − 472 (eq (char-before) ?\')))
+ − 473 (forward-sexp -1)
+ − 474 ;; vladimir@cs.ualberta.ca 30-Jul-1997: skip ` in
+ − 475 ;; `variable' so that the value is returned, not the
+ − 476 ;; name.
+ − 477 (if (and ignore-quotes
+ − 478 (eq (char-after) ?\`))
+ − 479 (forward-char))
+ − 480 (save-restriction
+ − 481 (narrow-to-region (point-min) opoint)
+ − 482 (let ((expr (read (current-buffer))))
+ − 483 (if (eq (car-safe expr) 'interactive)
+ − 484 ;; If it's an (interactive ...) form, it's
+ − 485 ;; more useful to show how an interactive call
+ − 486 ;; would use it.
+ − 487 `(call-interactively
+ − 488 (lambda (&rest args)
+ − 489 ,expr args))
+ − 490 expr)))))))))
+ − 491
+ − 492 (defun eval-defun (eval-defun-arg-internal)
+ − 493 "Evaluate defun that point is in or before.
+ − 494 Print value in minibuffer.
+ − 495 With argument, insert value in current buffer after the defun."
+ − 496 (interactive "P")
+ − 497 (let ((standard-output (if eval-defun-arg-internal (current-buffer) t)))
+ − 498 (prin1 (eval-interactive (save-excursion
+ − 499 (end-of-defun)
+ − 500 (beginning-of-defun)
+ − 501 (read (current-buffer)))))))
+ − 502
+ − 503
+ − 504 (defun lisp-comment-indent ()
+ − 505 (if (looking-at "\\s<\\s<\\s<")
+ − 506 (current-column)
+ − 507 (if (looking-at "\\s<\\s<")
+ − 508 ;; #### FSF has:
+ − 509 ;; (let ((tem (or (calculate-lisp-indent) (current-column)))) ...
+ − 510 (let ((tem (calculate-lisp-indent)))
+ − 511 (if (listp tem) (car tem) tem))
+ − 512 (skip-chars-backward " \t")
+ − 513 (max (if (bolp) 0 (1+ (current-column)))
+ − 514 comment-column))))
+ − 515
+ − 516 ;; XEmacs change
+ − 517 (defun lisp-indent-for-comment ()
+ − 518 "Indent this line's comment appropriately, or insert an empty comment.
+ − 519 If adding a new comment on a blank line, use `block-comment-start' instead
+ − 520 of `comment-start' to open the comment."
+ − 521 ;; by Stig@hackvan.com
+ − 522 ;; #### - This functionality, the recognition of block-comment-{start,end},
+ − 523 ;; will perhaps be standardized across modes and move to indent-for-comment.
+ − 524 (interactive)
+ − 525 (if (and block-comment-start
+ − 526 (save-excursion (beginning-of-line) (looking-at "^[ \t]*$")))
+ − 527 (insert block-comment-start))
+ − 528 (indent-for-comment))
+ − 529
+ − 530 (defvar lisp-indent-offset nil)
+ − 531 (defvar lisp-indent-function 'lisp-indent-function)
+ − 532
+ − 533 (defun lisp-indent-line (&optional whole-exp)
+ − 534 "Indent current line as Lisp code.
+ − 535 With argument, indent any additional lines of the same expression
+ − 536 rigidly along with this one."
+ − 537 (interactive "P")
+ − 538 (let ((indent (calculate-lisp-indent)) shift-amt beg end
+ − 539 (pos (- (point-max) (point))))
+ − 540 (beginning-of-line)
+ − 541 (setq beg (point))
+ − 542 (skip-chars-forward " \t")
+ − 543 (if (looking-at "\\s<\\s<\\s<")
+ − 544 ;; Don't alter indentation of a ;;; comment line.
+ − 545 (goto-char (- (point-max) pos))
+ − 546 (if (and (looking-at "\\s<") (not (looking-at "\\s<\\s<")))
+ − 547 ;; Single-semicolon comment lines should be indented
+ − 548 ;; as comment lines, not as code.
446
+ − 549 (progn (indent-for-comment) (backward-char 1))
428
+ − 550 (if (listp indent) (setq indent (car indent)))
+ − 551 (setq shift-amt (- indent (current-column)))
+ − 552 (if (zerop shift-amt)
+ − 553 nil
+ − 554 (delete-region beg (point))
+ − 555 (indent-to indent)))
+ − 556 ;; If initial point was within line's indentation,
+ − 557 ;; position after the indentation. Else stay at same point in text.
+ − 558 (if (> (- (point-max) pos) (point))
+ − 559 (goto-char (- (point-max) pos)))
+ − 560 ;; If desired, shift remaining lines of expression the same amount.
+ − 561 (and whole-exp (not (zerop shift-amt))
+ − 562 (save-excursion
+ − 563 (goto-char beg)
+ − 564 (forward-sexp 1)
+ − 565 (setq end (point))
+ − 566 (goto-char beg)
+ − 567 (forward-line 1)
+ − 568 (setq beg (point))
+ − 569 (> end beg))
+ − 570 (indent-code-rigidly beg end shift-amt)))))
+ − 571
+ − 572 (defvar calculate-lisp-indent-last-sexp)
+ − 573
+ − 574 (defun calculate-lisp-indent (&optional parse-start)
+ − 575 "Return appropriate indentation for current line as Lisp code.
+ − 576 In usual case returns an integer: the column to indent to.
+ − 577 Can instead return a list, whose car is the column to indent to.
+ − 578 This means that following lines at the same level of indentation
+ − 579 should not necessarily be indented the same way.
+ − 580 The second element of the list is the buffer position
+ − 581 of the start of the containing expression."
+ − 582 (save-excursion
+ − 583 (beginning-of-line)
+ − 584 (let ((indent-point (point))
+ − 585 ;; XEmacs change (remove paren-depth)
+ − 586 state ;;paren-depth
+ − 587 ;; setting this to a number inhibits calling hook
+ − 588 (desired-indent nil)
+ − 589 (retry t)
+ − 590 calculate-lisp-indent-last-sexp containing-sexp)
+ − 591 (if parse-start
+ − 592 (goto-char parse-start)
+ − 593 (beginning-of-defun))
+ − 594 ;; Find outermost containing sexp
+ − 595 (while (< (point) indent-point)
+ − 596 (setq state (parse-partial-sexp (point) indent-point 0)))
+ − 597 ;; Find innermost containing sexp
+ − 598 (while (and retry
+ − 599 state
+ − 600 ;; XEmacs change (remove paren-depth)
+ − 601 (> ;;(setq paren-depth (elt state 0))
+ − 602 (elt state 0)
+ − 603 0))
+ − 604 (setq retry nil)
+ − 605 (setq calculate-lisp-indent-last-sexp (elt state 2))
+ − 606 (setq containing-sexp (elt state 1))
+ − 607 ;; Position following last unclosed open.
+ − 608 (goto-char (1+ containing-sexp))
+ − 609 ;; Is there a complete sexp since then?
+ − 610 (if (and calculate-lisp-indent-last-sexp
+ − 611 (> calculate-lisp-indent-last-sexp (point)))
+ − 612 ;; Yes, but is there a containing sexp after that?
+ − 613 (let ((peek (parse-partial-sexp calculate-lisp-indent-last-sexp
+ − 614 indent-point 0)))
+ − 615 (if (setq retry (car (cdr peek))) (setq state peek)))))
+ − 616 (if retry
+ − 617 nil
+ − 618 ;; Innermost containing sexp found
+ − 619 (goto-char (1+ containing-sexp))
+ − 620 (if (not calculate-lisp-indent-last-sexp)
+ − 621 ;; indent-point immediately follows open paren.
+ − 622 ;; Don't call hook.
+ − 623 (setq desired-indent (current-column))
+ − 624 ;; Find the start of first element of containing sexp.
+ − 625 (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
+ − 626 (cond ((looking-at "\\s(")
+ − 627 ;; First element of containing sexp is a list.
+ − 628 ;; Indent under that list.
+ − 629 )
+ − 630 ((> (save-excursion (forward-line 1) (point))
+ − 631 calculate-lisp-indent-last-sexp)
+ − 632 ;; This is the first line to start within the containing sexp.
+ − 633 ;; It's almost certainly a function call.
+ − 634 (if (= (point) calculate-lisp-indent-last-sexp)
+ − 635 ;; Containing sexp has nothing before this line
+ − 636 ;; except the first element. Indent under that element.
+ − 637 nil
+ − 638 ;; Skip the first element, find start of second (the first
+ − 639 ;; argument of the function call) and indent under.
+ − 640 (progn (forward-sexp 1)
+ − 641 (parse-partial-sexp (point)
+ − 642 calculate-lisp-indent-last-sexp
+ − 643 0 t)))
+ − 644 (backward-prefix-chars))
+ − 645 (t
+ − 646 ;; Indent beneath first sexp on same line as
+ − 647 ;; calculate-lisp-indent-last-sexp. Again, it's
+ − 648 ;; almost certainly a function call.
+ − 649 (goto-char calculate-lisp-indent-last-sexp)
+ − 650 (beginning-of-line)
+ − 651 (parse-partial-sexp (point) calculate-lisp-indent-last-sexp
+ − 652 0 t)
+ − 653 (backward-prefix-chars)))))
+ − 654 ;; Point is at the point to indent under unless we are inside a string.
+ − 655 ;; Call indentation hook except when overridden by lisp-indent-offset
+ − 656 ;; or if the desired indentation has already been computed.
+ − 657 (let ((normal-indent (current-column)))
+ − 658 (cond ((elt state 3)
+ − 659 ;; Inside a string, don't change indentation.
+ − 660 (goto-char indent-point)
+ − 661 (skip-chars-forward " \t")
+ − 662 (current-column))
+ − 663 (desired-indent)
+ − 664 ((and (boundp 'lisp-indent-function)
+ − 665 lisp-indent-function
+ − 666 (not retry))
+ − 667 (or (funcall lisp-indent-function indent-point state)
+ − 668 normal-indent))
+ − 669 ;; XEmacs change:
+ − 670 ;; lisp-indent-offset shouldn't override lisp-indent-function !
+ − 671 ((and (integerp lisp-indent-offset) containing-sexp)
+ − 672 ;; Indent by constant offset
+ − 673 (goto-char containing-sexp)
+ − 674 (+ normal-indent lisp-indent-offset))
+ − 675 (t
+ − 676 normal-indent))))))
+ − 677
872
+ − 678 (defvar lisp-function-and-type-regexp
+ − 679 (concat "def\\("
+ − 680 ;; def but not define-.
+ − 681 "\\(un\\|advice\\|alias\\|macro\\*?\\|setf\\|subst\\*?\\|"
+ − 682 "-edebug-spec\\|"
+ − 683 ;; CLOS
+ − 684 "method\\|generic\\|"
+ − 685 ;; define-*
+ − 686 "ine-\\(?:"
+ − 687 ;; basic Lisp stuff
+ − 688 "compiler-macro\\|function\\|function-when-void\\|modify-macro\\|"
+ − 689 "setf-method\\|"
+ − 690 ;; obsolete/compatible support, XEmacs-specific
+ − 691 "compatible-function-alias\\|obsolete-function-alias\\|"
+ − 692 ;; XEmacs-specific, supporting stuff inside of XEmacs
+ − 693 "ccl-program\\|device-method\\*?\\|prefix-command\\|skeleton"
+ − 694 "\\)\\)\\|"
+ − 695 ;; Structure declarations.
+ − 696 "\\(class\\|struct\\|type\\)\\)\\>")
+ − 697 "Regular expression to match the function and type keywords used in Lisp.
+ − 698 This matches, for example, the string \"defun\", as well as defsetf,
+ − 699 defsubst*, define-prefix-command, etc. Match string 1 matches everything
+ − 700 but the three-letter \"def\" string at the beginning. Match string 2
+ − 701 matches everything after that, when it's *NOT* a \"type\" declaration --
+ − 702 which includes defclass, defstruct, and deftype. Match string 3 is similar
+ − 703 to match string 2 in that it matches everything after the \"def\", when
+ − 704 \(and only when) the keyword matched *IS* a type declaration. You can use
+ − 705 match strings 2 and 3 to easily determine whether a function or type was
+ − 706 matched. The regex is terminated with a \\\> so that there must be a
+ − 707 word-end; i.e. defunbbb won't match.")
+ − 708
+ − 709 (defvar lisp-flet-regexp
+ − 710 "(\\(flet\\|macrolet\\|labels\\)\\(\\s-\\|\n\\)")
+ − 711
428
+ − 712 (defun lisp-indent-function (indent-point state)
+ − 713 ;; free reference to `calculate-lisp-indent-last-sexp'
+ − 714 ;; in #'calculate-lisp-indent
+ − 715 (let ((normal-indent (current-column)))
+ − 716 (goto-char (1+ (elt state 1)))
+ − 717 (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
+ − 718 (if (and (elt state 2)
+ − 719 (not (looking-at "\\sw\\|\\s_")))
629
+ − 720 ;; car of form doesn't seem to be a symbol
428
+ − 721 (progn
+ − 722 (if (not (> (save-excursion (forward-line 1) (point))
+ − 723 calculate-lisp-indent-last-sexp))
+ − 724 (progn (goto-char calculate-lisp-indent-last-sexp)
+ − 725 (beginning-of-line)
+ − 726 (parse-partial-sexp (point)
+ − 727 calculate-lisp-indent-last-sexp 0 t)))
+ − 728 ;; Indent under the list or under the first sexp on the same
+ − 729 ;; line as calculate-lisp-indent-last-sexp. Note that first
+ − 730 ;; thing on that line has to be complete sexp since we are
+ − 731 ;; inside the innermost containing sexp.
+ − 732 (backward-prefix-chars)
+ − 733 (current-column))
872
+ − 734
+ − 735 ;; Now come a bunch of ad-hoc checks to see if we're in particular
+ − 736 ;; places (defining an flet function, in the argument list of a
+ − 737 ;; regular or flet function, in a quoted list, etc.) where the
+ − 738 ;; regular indenting doesn't work well.
+ − 739
+ − 740 ;; #### All this stuff here should be generalized so that
+ − 741 ;; you can specify, for various functions, how you want
+ − 742 ;; particular arguments handled -- in some way that works
+ − 743 ;; recursively, so it can handle flet and such.
+ − 744
+ − 745 (let* ((function (buffer-substring (point)
428
+ − 746 (progn (forward-sexp 1) (point))))
872
+ − 747 (quote (condition-case nil
+ − 748 (save-excursion
+ − 749 (backward-up-list 1)
+ − 750 (memq (char-before (point)) '(?' ?`)))))
+ − 751 method)
+ − 752 (cond
+ − 753 ;; if we're indenting a quoted list, and the first word is not
+ − 754 ;; lambda, line up second line below first with no indentation,
+ − 755 ;; so that property lists indent correctly.
+ − 756 ((and quote (not (equal function "lambda")))
+ − 757 (setq method 'lisp-indent-quoteform))
+ − 758 ;; do the same if we're indenting the arg list of a def* form.
+ − 759 ((let ((p (point)))
+ − 760 (condition-case nil
442
+ − 761 (save-excursion
872
+ − 762 (backward-up-list 2)
+ − 763 ;; make sure we're indeed the second argument of the
+ − 764 ;; def* form.
+ − 765 (and (eq (point) (save-excursion
+ − 766 (goto-char p)
+ − 767 (backward-up-list 1)
+ − 768 (backward-sexp 2)
+ − 769 (1- (point))))
+ − 770 ;; check to see that the function is a def* type
+ − 771 (eq (char-after) ?\()
+ − 772 (progn (forward-char 1) t)
+ − 773 (looking-at lisp-function-and-type-regexp)
+ − 774 ;; defstruct may have slot option specs, which
+ − 775 ;; should probably be reverse-indented like
+ − 776 ;; normal, because the slot name is the first
+ − 777 ;; in the list. #### Review this.
+ − 778 (not (equal (match-string 0) "defstruct"))))
+ − 779 (error nil)))
+ − 780 (setq method 'lisp-indent-quoteform))
+ − 781
+ − 782 ;; handle functions in flet forms
+ − 783 ((let ((p (point)))
+ − 784 (condition-case nil
+ − 785 (save-excursion
+ − 786 (backward-up-list 3)
+ − 787 ;; make sure we're indeed a function, i.e. inside the
+ − 788 ;; first form after the flet.
+ − 789 (and (eq (point) (save-excursion
+ − 790 (goto-char p)
+ − 791 (backward-up-list 2)
+ − 792 (backward-sexp 1)
+ − 793 (1- (point))))
+ − 794 (looking-at lisp-flet-regexp)))
+ − 795 (error nil)))
+ − 796 (setq method 'defun))
+ − 797
+ − 798 ;; handle the arg lists in functions in flet forms
+ − 799 ((let ((p (point)))
+ − 800 (condition-case nil
+ − 801 (save-excursion
+ − 802 (backward-up-list 2)
+ − 803 ;; make sure we're indeed the arg list -- i.e. the first
+ − 804 ;; element after the function name.
+ − 805 (and (eq (point) (save-excursion
+ − 806 (goto-char p)
+ − 807 (backward-up-list 1)
+ − 808 (backward-sexp 1)
+ − 809 (1- (point))))
+ − 810 (progn
+ − 811 (backward-up-list 2)
+ − 812 (looking-at lisp-flet-regexp))))
+ − 813 (error nil)))
+ − 814 (setq method 'lisp-indent-quoteform))
+ − 815 (t
+ − 816 (setq method
+ − 817 (or (get (intern-soft function) 'lisp-indent-function)
+ − 818 (get (intern-soft function) 'lisp-indent-hook)))))
428
+ − 819 (cond ((or (eq method 'defun)
+ − 820 (and (null method)
+ − 821 (> (length function) 3)
+ − 822 (string-match "\\`def" function)))
+ − 823 (lisp-indent-defform state indent-point))
+ − 824 ((integerp method)
+ − 825 (lisp-indent-specform method state
+ − 826 indent-point normal-indent))
+ − 827 (method
+ − 828 (funcall method state indent-point)))))))
+ − 829
872
+ − 830 (defun lisp-indent-quoteform (state indent-point)
+ − 831 (goto-char (car (cdr state)))
+ − 832 (forward-line 1)
+ − 833 (if (> (point) (car (cdr (cdr state))))
+ − 834 (progn
+ − 835 (goto-char (car (cdr state)))
+ − 836 (+ 1 (current-column)))))
+ − 837
428
+ − 838 (defvar lisp-body-indent 2
+ − 839 "Number of columns to indent the second line of a `(def...)' form.")
+ − 840
+ − 841 (defun lisp-indent-specform (count state indent-point normal-indent)
+ − 842 (let ((containing-form-start (elt state 1))
+ − 843 (i count)
+ − 844 body-indent containing-form-column)
+ − 845 ;; Move to the start of containing form, calculate indentation
+ − 846 ;; to use for non-distinguished forms (> count), and move past the
+ − 847 ;; function symbol. lisp-indent-function guarantees that there is at
+ − 848 ;; least one word or symbol character following open paren of containing
+ − 849 ;; form.
+ − 850 (goto-char containing-form-start)
+ − 851 (setq containing-form-column (current-column))
+ − 852 (setq body-indent (+ lisp-body-indent containing-form-column))
+ − 853 (forward-char 1)
+ − 854 (forward-sexp 1)
+ − 855 ;; Now find the start of the last form.
+ − 856 (parse-partial-sexp (point) indent-point 1 t)
+ − 857 (while (and (< (point) indent-point)
+ − 858 (condition-case ()
+ − 859 (progn
+ − 860 (setq count (1- count))
+ − 861 (forward-sexp 1)
+ − 862 (parse-partial-sexp (point) indent-point 1 t))
+ − 863 (error nil))))
+ − 864 ;; Point is sitting on first character of last (or count) sexp.
+ − 865 (if (> count 0)
+ − 866 ;; A distinguished form. If it is the first or second form use double
+ − 867 ;; lisp-body-indent, else normal indent. With lisp-body-indent bound
+ − 868 ;; to 2 (the default), this just happens to work the same with if as
+ − 869 ;; the older code, but it makes unwind-protect, condition-case,
+ − 870 ;; with-output-to-temp-buffer, et. al. much more tasteful. The older,
+ − 871 ;; less hacked, behavior can be obtained by replacing below with
+ − 872 ;; (list normal-indent containing-form-start).
+ − 873 (if (<= (- i count) 1)
+ − 874 (list (+ containing-form-column (* 2 lisp-body-indent))
+ − 875 containing-form-start)
+ − 876 (list normal-indent containing-form-start))
+ − 877 ;; A non-distinguished form. Use body-indent if there are no
+ − 878 ;; distinguished forms and this is the first undistinguished form,
+ − 879 ;; or if this is the first undistinguished form and the preceding
+ − 880 ;; distinguished form has indentation at least as great as body-indent.
+ − 881 (if (or (and (= i 0) (= count 0))
+ − 882 (and (= count 0) (<= body-indent normal-indent)))
+ − 883 body-indent
+ − 884 normal-indent))))
+ − 885
+ − 886 (defun lisp-indent-defform (state indent-point)
+ − 887 (goto-char (car (cdr state)))
+ − 888 (forward-line 1)
+ − 889 (if (> (point) (car (cdr (cdr state))))
+ − 890 (progn
+ − 891 (goto-char (car (cdr state)))
+ − 892 (+ lisp-body-indent (current-column)))))
+ − 893
+ − 894
+ − 895 ;; (put 'progn 'lisp-indent-function 0), say, causes progn to be indented
+ − 896 ;; like defun if the first form is placed on the next line, otherwise
+ − 897 ;; it is indented like any other form (i.e. forms line up under first).
+ − 898
776
+ − 899 ;; NOTE: All def* functions are handled specially, no need to put them here.
+ − 900 ;; NOTE: All cl-* constructs are handled in cl.el.
+ − 901
428
+ − 902 (put 'lambda 'lisp-indent-function 'defun)
+ − 903 (put 'autoload 'lisp-indent-function 'defun)
+ − 904 (put 'progn 'lisp-indent-function 0)
+ − 905 (put 'prog1 'lisp-indent-function 1)
+ − 906 (put 'prog2 'lisp-indent-function 2)
+ − 907 (put 'save-excursion 'lisp-indent-function 0)
+ − 908 (put 'save-window-excursion 'lisp-indent-function 0)
+ − 909 (put 'save-selected-window 'lisp-indent-function 0)
442
+ − 910 (put 'with-selected-window 'lisp-indent-function 1)
428
+ − 911 (put 'save-selected-frame 'lisp-indent-function 0)
+ − 912 (put 'with-selected-frame 'lisp-indent-function 1)
872
+ − 913 (put 'save-selected-device 'lisp-indent-function 0)
+ − 914 (put 'with-selected-device 'lisp-indent-function 1)
428
+ − 915 (put 'save-restriction 'lisp-indent-function 0)
+ − 916 (put 'save-match-data 'lisp-indent-function 0)
+ − 917 (put 'let 'lisp-indent-function 1)
+ − 918 (put 'let* 'lisp-indent-function 1)
+ − 919 (put 'let-specifier 'lisp-indent-function 1)
+ − 920 (put 'while 'lisp-indent-function 1)
+ − 921 (put 'if 'lisp-indent-function 2)
+ − 922 (put 'catch 'lisp-indent-function 1)
+ − 923 (put 'condition-case 'lisp-indent-function 2)
460
+ − 924 (put 'handler-case 'lisp-indent-function 1)
+ − 925 (put 'handler-bind 'lisp-indent-function 1)
428
+ − 926 (put 'call-with-condition-handler 'lisp-indent-function 2)
+ − 927 (put 'unwind-protect 'lisp-indent-function 1)
+ − 928 (put 'save-current-buffer 'lisp-indent-function 0)
+ − 929 (put 'with-current-buffer 'lisp-indent-function 1)
+ − 930 (put 'with-string-as-buffer-contents 'lisp-indent-function 1)
+ − 931 (put 'with-temp-file 'lisp-indent-function 1)
+ − 932 (put 'with-temp-buffer 'lisp-indent-function 0)
+ − 933 (put 'with-output-to-string 'lisp-indent-function 0)
+ − 934 (put 'with-output-to-temp-buffer 'lisp-indent-function 1)
460
+ − 935 (put 'with-slots 'lisp-indent-function 2)
+ − 936 (put 'with-open-file 'lisp-indent-function 1)
+ − 937 (put 'with-open-stream 'lisp-indent-function 1)
428
+ − 938 (put 'eval-after-load 'lisp-indent-function 1)
+ − 939 (put 'display-message 'lisp-indent-function 1)
+ − 940 (put 'display-warning 'lisp-indent-function 1)
+ − 941 (put 'lmessage 'lisp-indent-function 2)
+ − 942 (put 'lwarn 'lisp-indent-function 2)
+ − 943 (put 'global-set-key 'lisp-indent-function 1)
460
+ − 944 (put 'print-unreadable-object 'lisp-indent-function 1)
428
+ − 945
+ − 946 (defun indent-sexp (&optional endpos)
+ − 947 "Indent each line of the list starting just after point.
+ − 948 If optional arg ENDPOS is given, indent each line, stopping when
+ − 949 ENDPOS is encountered."
+ − 950 (interactive)
+ − 951 (let ((indent-stack (list nil))
+ − 952 (next-depth 0)
+ − 953 ;; If ENDPOS is non-nil, use nil as STARTING-POINT
+ − 954 ;; so that calculate-lisp-indent will find the beginning of
+ − 955 ;; the defun we are in.
+ − 956 ;; If ENDPOS is nil, it is safe not to scan before point
+ − 957 ;; since every line we indent is more deeply nested than point is.
+ − 958 (starting-point (if endpos nil (point)))
+ − 959 (last-point (point))
+ − 960 last-depth bol outer-loop-done inner-loop-done state this-indent)
+ − 961 (or endpos
+ − 962 ;; Get error now if we don't have a complete sexp after point.
+ − 963 (save-excursion (forward-sexp 1)))
+ − 964 (save-excursion
+ − 965 (setq outer-loop-done nil)
+ − 966 (while (if endpos (< (point) endpos)
+ − 967 (not outer-loop-done))
+ − 968 (setq last-depth next-depth
+ − 969 inner-loop-done nil)
+ − 970 ;; Parse this line so we can learn the state
+ − 971 ;; to indent the next line.
+ − 972 ;; This inner loop goes through only once
+ − 973 ;; unless a line ends inside a string.
+ − 974 (while (and (not inner-loop-done)
+ − 975 (not (setq outer-loop-done (eobp))))
+ − 976 (setq state (parse-partial-sexp (point) (progn (end-of-line) (point))
+ − 977 nil nil state))
+ − 978 (setq next-depth (car state))
+ − 979 ;; If the line contains a comment other than the sort
+ − 980 ;; that is indented like code,
+ − 981 ;; indent it now with indent-for-comment.
+ − 982 ;; Comments indented like code are right already.
+ − 983 ;; In any case clear the in-comment flag in the state
+ − 984 ;; because parse-partial-sexp never sees the newlines.
+ − 985 (if (car (nthcdr 4 state))
+ − 986 (progn (indent-for-comment)
+ − 987 (end-of-line)
+ − 988 (setcar (nthcdr 4 state) nil)))
+ − 989 ;; If this line ends inside a string,
+ − 990 ;; go straight to next line, remaining within the inner loop,
+ − 991 ;; and turn off the \-flag.
+ − 992 (if (car (nthcdr 3 state))
+ − 993 (progn
+ − 994 (forward-line 1)
+ − 995 (setcar (nthcdr 5 state) nil))
+ − 996 (setq inner-loop-done t)))
+ − 997 (and endpos
+ − 998 (<= next-depth 0)
+ − 999 (progn
+ − 1000 (setq indent-stack (append indent-stack
+ − 1001 (make-list (- next-depth) nil))
+ − 1002 last-depth (- last-depth next-depth)
+ − 1003 next-depth 0)))
+ − 1004 (or outer-loop-done endpos
+ − 1005 (setq outer-loop-done (<= next-depth 0)))
+ − 1006 (if outer-loop-done
+ − 1007 (forward-line 1)
+ − 1008 (while (> last-depth next-depth)
+ − 1009 (setq indent-stack (cdr indent-stack)
+ − 1010 last-depth (1- last-depth)))
+ − 1011 (while (< last-depth next-depth)
+ − 1012 (setq indent-stack (cons nil indent-stack)
+ − 1013 last-depth (1+ last-depth)))
+ − 1014 ;; Now go to the next line and indent it according
+ − 1015 ;; to what we learned from parsing the previous one.
+ − 1016 (forward-line 1)
+ − 1017 (setq bol (point))
+ − 1018 (skip-chars-forward " \t")
+ − 1019 ;; But not if the line is blank, or just a comment
+ − 1020 ;; (except for double-semi comments; indent them as usual).
+ − 1021 (if (or (eobp) (looking-at "\\s<\\|\n"))
+ − 1022 nil
+ − 1023 (if (and (car indent-stack)
+ − 1024 (>= (car indent-stack) 0))
+ − 1025 (setq this-indent (car indent-stack))
+ − 1026 (let ((val (calculate-lisp-indent
+ − 1027 (if (car indent-stack) (- (car indent-stack))
+ − 1028 starting-point))))
+ − 1029 (if (integerp val)
+ − 1030 (setcar indent-stack
+ − 1031 (setq this-indent val))
+ − 1032 (setcar indent-stack (- (car (cdr val))))
+ − 1033 (setq this-indent (car val)))))
+ − 1034 (if (/= (current-column) this-indent)
+ − 1035 (progn (delete-region bol (point))
+ − 1036 (indent-to this-indent)))))
+ − 1037 (or outer-loop-done
+ − 1038 (setq outer-loop-done (= (point) last-point))
+ − 1039 (setq last-point (point)))))))
+ − 1040
+ − 1041 ;; Indent every line whose first char is between START and END inclusive.
+ − 1042 (defun lisp-indent-region (start end)
+ − 1043 (save-excursion
+ − 1044 (let ((endmark (copy-marker end)))
+ − 1045 (goto-char start)
+ − 1046 (and (bolp) (not (eolp))
+ − 1047 (lisp-indent-line))
+ − 1048 (indent-sexp endmark)
+ − 1049 (set-marker endmark nil))))
+ − 1050
+ − 1051 ;;;; Lisp paragraph filling commands.
+ − 1052
+ − 1053 (defun lisp-fill-paragraph (&optional justify)
+ − 1054 "Like \\[fill-paragraph], but handle Emacs Lisp comments.
+ − 1055 If any of the current line is a comment, fill the comment or the
+ − 1056 paragraph of it that point is in, preserving the comment's indentation
+ − 1057 and initial semicolons."
+ − 1058 (interactive "P")
+ − 1059 (let (
+ − 1060 ;; Non-nil if the current line contains a comment.
+ − 1061 has-comment
+ − 1062
+ − 1063 ;; Non-nil if the current line contains code and a comment.
+ − 1064 has-code-and-comment
+ − 1065
+ − 1066 ;; If has-comment, the appropriate fill-prefix for the comment.
+ − 1067 comment-fill-prefix
+ − 1068 )
+ − 1069
+ − 1070 ;; Figure out what kind of comment we are looking at.
+ − 1071 (save-excursion
+ − 1072 (beginning-of-line)
+ − 1073 (cond
+ − 1074
+ − 1075 ;; A line with nothing but a comment on it?
+ − 1076 ((looking-at "[ \t]*;[; \t]*")
+ − 1077 (setq has-comment t
+ − 1078 comment-fill-prefix (buffer-substring (match-beginning 0)
+ − 1079 (match-end 0))))
+ − 1080
+ − 1081 ;; A line with some code, followed by a comment? Remember that the
+ − 1082 ;; semi which starts the comment shouldn't be part of a string or
+ − 1083 ;; character.
+ − 1084 ;; XEmacs Try this the FSF and see if it works.
+ − 1085 ; ((progn
+ − 1086 ; (while (not (looking-at ";\\|$"))
+ − 1087 ; (skip-chars-forward "^;\n\"\\\\?")
+ − 1088 ; (cond
+ − 1089 ; ((eq (char-after (point)) ?\\) (forward-char 2))
+ − 1090 ; ((memq (char-after (point)) '(?\" ??)) (forward-sexp 1))))
+ − 1091 ; (looking-at ";+[\t ]*"))
+ − 1092 ; (setq has-comment t)
+ − 1093 ((condition-case nil
+ − 1094 (save-restriction
+ − 1095 (narrow-to-region (point-min)
+ − 1096 (save-excursion (end-of-line) (point)))
+ − 1097 (while (not (looking-at ";\\|$"))
+ − 1098 (skip-chars-forward "^;\n\"\\\\?")
+ − 1099 (cond
+ − 1100 ((eq (char-after (point)) ?\\) (forward-char 2))
+ − 1101 ((memq (char-after (point)) '(?\" ??)) (forward-sexp 1))))
844
+ − 1102 ;; don't do comment filling in a string, or we will mess up
+ − 1103 ;; doc strings and other places where semicolons are used.
+ − 1104 (and (not (eq 'string (buffer-syntactic-context)))
+ − 1105 (looking-at ";+[\t ]*")))
428
+ − 1106 (error nil))
+ − 1107 (setq has-comment t has-code-and-comment t)
+ − 1108 (setq comment-fill-prefix
+ − 1109 (concat (make-string (/ (current-column) 8) ?\t)
+ − 1110 (make-string (% (current-column) 8) ?\ )
+ − 1111 (buffer-substring (match-beginning 0) (match-end 0)))))))
+ − 1112
+ − 1113 (if (not has-comment)
+ − 1114 (fill-paragraph justify)
+ − 1115
+ − 1116 ;; Narrow to include only the comment, and then fill the region.
+ − 1117 (save-excursion
+ − 1118 (save-restriction
+ − 1119 (beginning-of-line)
+ − 1120 (narrow-to-region
+ − 1121 ;; Find the first line we should include in the region to fill.
+ − 1122 (save-excursion
+ − 1123 (while (and (zerop (forward-line -1))
+ − 1124 (looking-at "^[ \t]*;")))
+ − 1125 ;; We may have gone too far. Go forward again.
+ − 1126 (or (looking-at ".*;")
+ − 1127 (forward-line 1))
+ − 1128 (point))
+ − 1129 ;; Find the beginning of the first line past the region to fill.
+ − 1130 (save-excursion
+ − 1131 (while (progn (forward-line 1)
+ − 1132 (looking-at "^[ \t]*;")))
+ − 1133 (point)))
+ − 1134
+ − 1135 ;; Lines with only semicolons on them can be paragraph boundaries.
+ − 1136 (let* ((paragraph-start (concat paragraph-start "\\|[ \t;]*$"))
+ − 1137 (paragraph-separate (concat paragraph-start "\\|[ \t;]*$"))
+ − 1138 (paragraph-ignore-fill-prefix nil)
+ − 1139 (fill-prefix comment-fill-prefix)
+ − 1140 (after-line (if has-code-and-comment
+ − 1141 (save-excursion
+ − 1142 (forward-line 1) (point))))
+ − 1143 (end (progn
+ − 1144 (forward-paragraph)
+ − 1145 (or (bolp) (newline 1))
+ − 1146 (point)))
+ − 1147 ;; If this comment starts on a line with code,
+ − 1148 ;; include that like in the filling.
+ − 1149 (beg (progn (backward-paragraph)
+ − 1150 (if (eq (point) after-line)
+ − 1151 (forward-line -1))
+ − 1152 (point))))
+ − 1153 (fill-region-as-paragraph beg end
+ − 1154 justify nil
+ − 1155 (save-excursion
+ − 1156 (goto-char beg)
+ − 1157 (if (looking-at fill-prefix)
+ − 1158 nil
+ − 1159 (re-search-forward comment-start-skip)
+ − 1160 (point))))))))
+ − 1161 t))
+ − 1162
+ − 1163 (defun indent-code-rigidly (start end arg &optional nochange-regexp)
+ − 1164 "Indent all lines of code, starting in the region, sideways by ARG columns.
+ − 1165 Does not affect lines starting inside comments or strings, assuming that
+ − 1166 the start of the region is not inside them.
+ − 1167
+ − 1168 Called from a program, takes args START, END, COLUMNS and NOCHANGE-REGEXP.
+ − 1169 The last is a regexp which, if matched at the beginning of a line,
+ − 1170 means don't indent that line."
+ − 1171 (interactive "r\np")
+ − 1172 (let (state)
+ − 1173 (save-excursion
+ − 1174 (goto-char end)
+ − 1175 (setq end (point-marker))
+ − 1176 (goto-char start)
+ − 1177 (or (bolp)
+ − 1178 (setq state (parse-partial-sexp (point)
+ − 1179 (progn
+ − 1180 (forward-line 1) (point))
+ − 1181 nil nil state)))
+ − 1182 (while (< (point) end)
+ − 1183 (or (car (nthcdr 3 state))
+ − 1184 (and nochange-regexp
+ − 1185 (looking-at nochange-regexp))
+ − 1186 ;; If line does not start in string, indent it
+ − 1187 (let ((indent (current-indentation)))
+ − 1188 (delete-region (point) (progn (skip-chars-forward " \t") (point)))
+ − 1189 (or (eolp)
+ − 1190 (indent-to (max 0 (+ indent arg)) 0))))
+ − 1191 (setq state (parse-partial-sexp (point)
+ − 1192 (progn
+ − 1193 (forward-line 1) (point))
+ − 1194 nil nil state))))))
+ − 1195
+ − 1196 (provide 'lisp-mode)
+ − 1197
+ − 1198 ;;; lisp-mode.el ends here