|
|
1.1 ! root 1: ;; Lisp mode, and its idiosyncratic commands. ! 2: ;; Copyright (C) 1985 Free Software Foundation, Inc. ! 3: ! 4: ;; This file is part of GNU Emacs. ! 5: ! 6: ;; GNU Emacs is distributed in the hope that it will be useful, ! 7: ;; but WITHOUT ANY WARRANTY. No author or distributor ! 8: ;; accepts responsibility to anyone for the consequences of using it ! 9: ;; or for whether it serves any particular purpose or works at all, ! 10: ;; unless he says so in writing. Refer to the GNU Emacs General Public ! 11: ;; License for full details. ! 12: ! 13: ;; Everyone is granted permission to copy, modify and redistribute ! 14: ;; GNU Emacs, but only under the conditions described in the ! 15: ;; GNU Emacs General Public License. A copy of this license is ! 16: ;; supposed to have been given to you along with GNU Emacs so you ! 17: ;; can know your rights and responsibilities. It should be in a ! 18: ;; file named COPYING. Among other things, the copyright notice ! 19: ;; and this notice must be preserved on all copies. ! 20: ! 21: ! 22: (defvar lisp-mode-syntax-table nil "") ! 23: (defvar emacs-lisp-mode-syntax-table nil "") ! 24: (defvar lisp-mode-abbrev-table nil "") ! 25: ! 26: (if (not emacs-lisp-mode-syntax-table) ! 27: (let ((i 0)) ! 28: (setq emacs-lisp-mode-syntax-table (make-syntax-table)) ! 29: (while (< i ?0) ! 30: (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table) ! 31: (setq i (1+ i))) ! 32: (setq i (1+ ?9)) ! 33: (while (< i ?A) ! 34: (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table) ! 35: (setq i (1+ i))) ! 36: (setq i (1+ ?Z)) ! 37: (while (< i ?a) ! 38: (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table) ! 39: (setq i (1+ i))) ! 40: (setq i (1+ ?z)) ! 41: (while (< i 128) ! 42: (modify-syntax-entry i "_ " emacs-lisp-mode-syntax-table) ! 43: (setq i (1+ i))) ! 44: (modify-syntax-entry ? " " emacs-lisp-mode-syntax-table) ! 45: (modify-syntax-entry ?\t " " emacs-lisp-mode-syntax-table) ! 46: (modify-syntax-entry ?\n "> " emacs-lisp-mode-syntax-table) ! 47: (modify-syntax-entry ?\f "> " emacs-lisp-mode-syntax-table) ! 48: (modify-syntax-entry ?\; "< " emacs-lisp-mode-syntax-table) ! 49: (modify-syntax-entry ?` "' " emacs-lisp-mode-syntax-table) ! 50: (modify-syntax-entry ?' "' " emacs-lisp-mode-syntax-table) ! 51: (modify-syntax-entry ?, "' " emacs-lisp-mode-syntax-table) ! 52: (modify-syntax-entry ?. "' " emacs-lisp-mode-syntax-table) ! 53: (modify-syntax-entry ?# "' " emacs-lisp-mode-syntax-table) ! 54: (modify-syntax-entry ?\" "\" " emacs-lisp-mode-syntax-table) ! 55: (modify-syntax-entry ?\\ "\\ " emacs-lisp-mode-syntax-table) ! 56: (modify-syntax-entry ?\( "() " emacs-lisp-mode-syntax-table) ! 57: (modify-syntax-entry ?\) ")( " emacs-lisp-mode-syntax-table) ! 58: (modify-syntax-entry ?\[ "(] " emacs-lisp-mode-syntax-table) ! 59: (modify-syntax-entry ?\] ")[ " emacs-lisp-mode-syntax-table))) ! 60: ! 61: (define-abbrev-table 'lisp-mode-abbrev-table ()) ! 62: ! 63: (defun lisp-mode-variables (lisp-syntax) ! 64: (cond (lisp-syntax ! 65: (if (not lisp-mode-syntax-table) ! 66: (progn (setq lisp-mode-syntax-table ! 67: (copy-syntax-table emacs-lisp-mode-syntax-table)) ! 68: (modify-syntax-entry ?\| "\" " ! 69: lisp-mode-syntax-table) ! 70: (modify-syntax-entry ?\[ "_ " ! 71: lisp-mode-syntax-table) ! 72: (modify-syntax-entry ?\] "_ " ! 73: lisp-mode-syntax-table))) ! 74: (set-syntax-table lisp-mode-syntax-table))) ! 75: (setq local-abbrev-table lisp-mode-abbrev-table) ! 76: (make-local-variable 'paragraph-start) ! 77: (setq paragraph-start (concat "^$\\|" page-delimiter)) ! 78: (make-local-variable 'paragraph-separate) ! 79: (setq paragraph-separate paragraph-start) ! 80: (make-local-variable 'paragraph-ignore-fill-prefix) ! 81: (setq paragraph-ignore-fill-prefix t) ! 82: (make-local-variable 'indent-line-function) ! 83: (setq indent-line-function 'lisp-indent-line) ! 84: (make-local-variable 'comment-start) ! 85: (setq comment-start ";") ! 86: (make-local-variable 'comment-start-skip) ! 87: (setq comment-start-skip ";+ *") ! 88: (make-local-variable 'comment-column) ! 89: (setq comment-column 40) ! 90: (make-local-variable 'comment-indent-hook) ! 91: (setq comment-indent-hook 'lisp-comment-indent)) ! 92: ! 93: (defun lisp-mode-commands (map) ! 94: (define-key map "\e\C-q" 'indent-sexp) ! 95: (define-key map "\177" 'backward-delete-char-untabify) ! 96: (define-key map "\t" 'lisp-indent-line)) ! 97: ! 98: (defvar emacs-lisp-mode-map () "") ! 99: (if emacs-lisp-mode-map ! 100: () ! 101: (setq emacs-lisp-mode-map (make-sparse-keymap)) ! 102: (define-key emacs-lisp-mode-map "\e\C-x" 'eval-defun) ! 103: (lisp-mode-commands emacs-lisp-mode-map)) ! 104: ! 105: (defun emacs-lisp-mode () ! 106: "Major mode for editing Lisp code to run in Emacs. ! 107: Commands: ! 108: Delete converts tabs to spaces as it moves back. ! 109: Blank lines separate paragraphs. Semicolons start comments. ! 110: \\{emacs-lisp-mode-map} ! 111: Entry to this mode calls the value of emacs-lisp-mode-hook ! 112: if that value is non-nil." ! 113: (interactive) ! 114: (kill-all-local-variables) ! 115: (use-local-map emacs-lisp-mode-map) ! 116: (set-syntax-table emacs-lisp-mode-syntax-table) ! 117: (setq major-mode 'emacs-lisp-mode) ! 118: (setq mode-name "Emacs-Lisp") ! 119: (lisp-mode-variables nil) ! 120: (run-hooks 'emacs-lisp-mode-hook)) ! 121: ! 122: (defvar lisp-mode-map ()) ! 123: (if lisp-mode-map ! 124: () ! 125: (setq lisp-mode-map (make-sparse-keymap)) ! 126: (define-key lisp-mode-map "\e\C-x" 'lisp-send-defun) ! 127: (define-key lisp-mode-map "\C-c\C-l" 'run-lisp) ! 128: (lisp-mode-commands lisp-mode-map)) ! 129: ! 130: (defun lisp-mode () ! 131: "Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp. ! 132: Commands: ! 133: Delete converts tabs to spaces as it moves back. ! 134: Blank lines separate paragraphs. Semicolons start comments. ! 135: \\{lisp-mode-map} ! 136: Note that `run-lisp' may be used either to start an inferior Lisp job ! 137: or to switch back to an existing one. ! 138: ! 139: Entry to this mode calls the value of lisp-mode-hook ! 140: if that value is non-nil." ! 141: (interactive) ! 142: (kill-all-local-variables) ! 143: (use-local-map lisp-mode-map) ! 144: (setq major-mode 'lisp-mode) ! 145: (setq mode-name "Lisp") ! 146: (lisp-mode-variables t) ! 147: (set-syntax-table lisp-mode-syntax-table) ! 148: (run-hooks 'lisp-mode-hook)) ! 149: ! 150: ;; This will do unless shell.el is loaded. ! 151: (defun lisp-send-defun nil ! 152: "Send the current defun to the Lisp process made by M-x run-lisp." ! 153: (interactive) ! 154: (error "Process lisp does not exist")) ! 155: ! 156: (defvar lisp-interaction-mode-map ()) ! 157: (if lisp-interaction-mode-map ! 158: () ! 159: (setq lisp-interaction-mode-map (make-sparse-keymap)) ! 160: (lisp-mode-commands lisp-interaction-mode-map) ! 161: (define-key lisp-interaction-mode-map "\e\C-x" 'eval-defun) ! 162: (define-key lisp-interaction-mode-map "\n" 'eval-print-last-sexp)) ! 163: ! 164: (defun lisp-interaction-mode () ! 165: "Major mode for typing and evaluating Lisp forms. ! 166: Like Lisp mode except that \\[eval-print-last-sexp] evals the Lisp expression ! 167: before point, and prints its value into the buffer, advancing point. ! 168: ! 169: Commands: ! 170: Delete converts tabs to spaces as it moves back. ! 171: Paragraphs are separated only by blank lines. Semicolons start comments. ! 172: \\{lisp-interaction-mode-map} ! 173: Entry to this mode calls the value of lisp-interaction-mode-hook ! 174: if that value is non-nil." ! 175: (interactive) ! 176: (kill-all-local-variables) ! 177: (use-local-map lisp-interaction-mode-map) ! 178: (setq major-mode 'lisp-interaction-mode) ! 179: (setq mode-name "Lisp Interaction") ! 180: (lisp-mode-variables t) ! 181: (run-hooks 'lisp-interaction-mode-hook)) ! 182: ! 183: (defun eval-print-last-sexp (arg) ! 184: "Evaluate sexp before point; print value into current buffer." ! 185: (interactive "P") ! 186: (eval-region ! 187: (let ((stab (syntax-table))) ! 188: (unwind-protect ! 189: (save-excursion ! 190: (set-syntax-table emacs-lisp-mode-syntax-table) ! 191: (forward-sexp -1) ! 192: (point)) ! 193: (set-syntax-table stab))) ! 194: (point) ! 195: (current-buffer))) ! 196: ! 197: (defun eval-last-sexp (arg) ! 198: "Evaluate sexp before point; print value in minibuffer. ! 199: With argument, print output into current buffer." ! 200: (interactive "P") ! 201: (eval-region ! 202: (let ((stab (syntax-table))) ! 203: (unwind-protect ! 204: (save-excursion ! 205: (set-syntax-table emacs-lisp-mode-syntax-table) ! 206: (forward-sexp -1) ! 207: (point)) ! 208: (set-syntax-table stab))) ! 209: (point) ! 210: (if arg (current-buffer) t))) ! 211: ! 212: (defun eval-defun (arg) ! 213: "Evaluate defun that point is in or before. ! 214: Print value in minibuffer. ! 215: With argument, insert value in current buffer after the defun." ! 216: (interactive "P") ! 217: (save-excursion ! 218: (end-of-defun) ! 219: (let ((end (point))) ! 220: (beginning-of-defun) ! 221: (eval-region (point) end ! 222: (if arg (current-buffer) t))))) ! 223: ! 224: (defun lisp-comment-indent () ! 225: (if (looking-at ";;;") ! 226: (current-column) ! 227: (if (looking-at ";;") ! 228: (let ((tem (calculate-lisp-indent))) ! 229: (if (listp tem) (car tem) tem)) ! 230: (skip-chars-backward " \t") ! 231: (max (if (bolp) 0 (1+ (current-column))) ! 232: comment-column)))) ! 233: ! 234: (defconst lisp-indent-offset nil "") ! 235: (defconst lisp-indent-hook 'lisp-indent-hook "") ! 236: ! 237: (defun lisp-indent-line (&optional whole-exp) ! 238: "Indent current line as Lisp code. ! 239: With argument, indent any additional lines of the same expression ! 240: rigidly along with this one." ! 241: (interactive "P") ! 242: (let ((indent (calculate-lisp-indent)) shift-amt beg end ! 243: (pos (- (point-max) (point)))) ! 244: (beginning-of-line) ! 245: (setq beg (point)) ! 246: (skip-chars-forward " \t") ! 247: (if (looking-at ";;;") ! 248: ;; Don't alter indentation of a ;;; comment line. ! 249: nil ! 250: (if (and (looking-at ";") (not (looking-at ";;"))) ! 251: ;; Single-semicolon comment lines should be indented ! 252: ;; as comment lines, not as code. ! 253: (progn (indent-for-comment) (forward-char -1)) ! 254: (if (listp indent) (setq indent (car indent))) ! 255: (setq shift-amt (- indent (current-column))) ! 256: (if (zerop shift-amt) ! 257: nil ! 258: (delete-region beg (point)) ! 259: (indent-to indent))) ! 260: ;; If initial point was within line's indentation, ! 261: ;; position after the indentation. Else stay at same point in text. ! 262: (if (> (- (point-max) pos) (point)) ! 263: (goto-char (- (point-max) pos))) ! 264: ;; If desired, shift remaining lines of expression the same amount. ! 265: (and whole-exp (not (zerop shift-amt)) ! 266: (save-excursion ! 267: (goto-char beg) ! 268: (forward-sexp 1) ! 269: (setq end (point)) ! 270: (goto-char beg) ! 271: (forward-line 1) ! 272: (setq beg (point)) ! 273: (> end beg)) ! 274: (indent-code-rigidly beg end shift-amt))))) ! 275: ! 276: (defun calculate-lisp-indent (&optional parse-start) ! 277: "Return appropriate indentation for current line as Lisp code. ! 278: In usual case returns an integer: the column to indent to. ! 279: Can instead return a list, whose car is the column to indent to. ! 280: This means that following lines at the same level of indentation ! 281: should not necessarily be indented the same way. ! 282: The second element of the list is the buffer position ! 283: of the start of the containing expression." ! 284: (save-excursion ! 285: (beginning-of-line) ! 286: (let ((indent-point (point)) ! 287: state paren-depth ! 288: ;; setting this to a number inhibits calling hook ! 289: (desired-indent nil) ! 290: (retry t) ! 291: last-sexp containing-sexp) ! 292: (if parse-start ! 293: (goto-char parse-start) ! 294: (beginning-of-defun)) ! 295: ;; Find outermost containing sexp ! 296: (while (< (point) indent-point) ! 297: (setq state (parse-partial-sexp (point) indent-point 0))) ! 298: ;; Find innermost containing sexp ! 299: (while (and retry ! 300: state ! 301: (> (setq paren-depth (elt state 0)) 0)) ! 302: (setq retry nil) ! 303: (setq last-sexp (elt state 2)) ! 304: (setq containing-sexp (elt state 1)) ! 305: ;; Position following last unclosed open. ! 306: (goto-char (1+ containing-sexp)) ! 307: ;; Is there a complete sexp since then? ! 308: (if (and last-sexp (> last-sexp (point))) ! 309: ;; Yes, but is there a containing sexp after that? ! 310: (let ((peek (parse-partial-sexp last-sexp indent-point 0))) ! 311: (if (setq retry (car (cdr peek))) (setq state peek))))) ! 312: (if retry ! 313: nil ! 314: ;; Innermost containing sexp found ! 315: (goto-char (1+ containing-sexp)) ! 316: (if (not last-sexp) ! 317: ;; indent-point immediately follows open paren. ! 318: ;; Don't call hook. ! 319: (setq desired-indent (current-column)) ! 320: ;; Find the start of first element of containing sexp. ! 321: (parse-partial-sexp (point) last-sexp 0 t) ! 322: (cond ((looking-at "\\s(") ! 323: ;; First element of containing sexp is a list. ! 324: ;; Indent under that list. ! 325: ) ! 326: ((> (save-excursion (forward-line 1) (point)) ! 327: last-sexp) ! 328: ;; This is the first line to start within the containing sexp. ! 329: ;; It's almost certainly a function call. ! 330: (if (= (point) last-sexp) ! 331: ;; Containing sexp has nothing before this line ! 332: ;; except the first element. Indent under that element. ! 333: nil ! 334: ;; Skip the first element, find start of second (the first ! 335: ;; argument of the function call) and indent under. ! 336: (progn (forward-sexp 1) ! 337: (parse-partial-sexp (point) last-sexp 0 t))) ! 338: (backward-prefix-chars)) ! 339: (t ! 340: ;; Indent beneath first sexp on same line as last-sexp. ! 341: ;; Again, it's almost certainly a function call. ! 342: (goto-char last-sexp) ! 343: (beginning-of-line) ! 344: (parse-partial-sexp (point) last-sexp 0 t) ! 345: (backward-prefix-chars))))) ! 346: ;; Point is at the point to indent under unless we are inside a string. ! 347: ;; Call indentation hook except when overriden by lisp-indent-offset ! 348: ;; or if the desired indentation has already been computed. ! 349: (let ((normal-indent (current-column))) ! 350: (cond ((elt state 3) ! 351: ;; Inside a string, don't change indentation. ! 352: (goto-char indent-point) ! 353: (skip-chars-forward " \t") ! 354: (current-column)) ! 355: ((and (integerp lisp-indent-offset) containing-sexp) ! 356: ;; Indent by constant offset ! 357: (goto-char containing-sexp) ! 358: (+ normal-indent lisp-indent-offset)) ! 359: (desired-indent) ! 360: ((and (boundp 'lisp-indent-hook) ! 361: lisp-indent-hook ! 362: (not retry)) ! 363: (or (funcall lisp-indent-hook indent-point state) ! 364: normal-indent)) ! 365: (t ! 366: normal-indent)))))) ! 367: ! 368: (defun lisp-indent-hook (indent-point state) ! 369: (let ((normal-indent (current-column))) ! 370: (goto-char (1+ (elt state 1))) ! 371: (parse-partial-sexp (point) last-sexp 0 t) ! 372: (if (and (elt state 2) ! 373: (not (looking-at "\\sw\\|\\s_"))) ! 374: ;; car of form doesn't seem to be a a symbol ! 375: (progn ! 376: (if (not (> (save-excursion (forward-line 1) (point)) ! 377: last-sexp)) ! 378: (progn (goto-char last-sexp) ! 379: (beginning-of-line) ! 380: (parse-partial-sexp (point) last-sexp 0 t))) ! 381: ;; Indent under the list or under the first sexp on the ! 382: ;; same line as last-sexp. Note that first thing on that ! 383: ;; line has to be complete sexp since we are inside the ! 384: ;; innermost containing sexp. ! 385: (backward-prefix-chars) ! 386: (current-column)) ! 387: (let ((function (buffer-substring (point) ! 388: (progn (forward-sexp 1) (point)))) ! 389: method) ! 390: (setq method (get (intern-soft function) 'lisp-indent-hook)) ! 391: (cond ((or (eq method 'defun) ! 392: (and (null method) ! 393: (> (length function) 3) ! 394: (string-match "\\`def" function))) ! 395: (lisp-indent-defform state indent-point)) ! 396: ((integerp method) ! 397: (lisp-indent-specform method state ! 398: indent-point normal-indent)) ! 399: (method ! 400: (funcall method state indent-point))))))) ! 401: ! 402: (defconst lisp-body-indent 2 "") ! 403: ! 404: (defun lisp-indent-specform (count state indent-point normal-indent) ! 405: (let ((containing-form-start (elt state 1)) ! 406: (i count) ! 407: body-indent containing-form-column) ! 408: ;; Move to the start of containing form, calculate indentation ! 409: ;; to use for non-distinguished forms (> count), and move past the ! 410: ;; function symbol. lisp-indent-hook guarantees that there is at ! 411: ;; least one word or symbol character following open paren of containing ! 412: ;; form. ! 413: (goto-char containing-form-start) ! 414: (setq containing-form-column (current-column)) ! 415: (setq body-indent (+ lisp-body-indent containing-form-column)) ! 416: (forward-char 1) ! 417: (forward-sexp 1) ! 418: ;; Now find the start of the last form. ! 419: (parse-partial-sexp (point) indent-point 1 t) ! 420: (while (and (< (point) indent-point) ! 421: (condition-case () ! 422: (progn ! 423: (setq count (1- count)) ! 424: (forward-sexp 1) ! 425: (parse-partial-sexp (point) indent-point 1 t)) ! 426: (error nil)))) ! 427: ;; Point is sitting on first character of last (or count) sexp. ! 428: (if (> count 0) ! 429: ;; A distinguished form. If it is the first or second form use double ! 430: ;; lisp-body-indent, else normal indent. With lisp-body-indent bound ! 431: ;; to 2 (the default), this just happens to work the same with if as ! 432: ;; the older code, but it makes unwind-protect, condition-case, ! 433: ;; with-output-to-temp-buffer, et. al. much more tasteful. The older, ! 434: ;; less hacked, behavior can be obtained by replacing below with ! 435: ;; (list normal-indent containing-form-start). ! 436: (if (<= (- i count) 1) ! 437: (list (+ containing-form-column (* 2 lisp-body-indent)) ! 438: containing-form-start) ! 439: (list normal-indent containing-form-start)) ! 440: ;; A non-distinguished form. Use body-indent if there are no ! 441: ;; distinguished forms and this is the first undistinguished form, ! 442: ;; or if this is the first undistinguished form and the preceding ! 443: ;; distinguished form has indentation at least as great as body-indent. ! 444: (if (or (and (= i 0) (= count 0)) ! 445: (and (= count 0) (<= body-indent normal-indent))) ! 446: body-indent ! 447: normal-indent)))) ! 448: ! 449: (defun lisp-indent-defform (state indent-point) ! 450: (goto-char (car (cdr state))) ! 451: (forward-line 1) ! 452: (if (> (point) (car (cdr (cdr state)))) ! 453: (progn ! 454: (goto-char (car (cdr state))) ! 455: (+ lisp-body-indent (current-column))))) ! 456: ! 457: ! 458: ;; (put 'progn 'lisp-indent-hook 0), say, causes progn to be indented ! 459: ;; like defun if the first form is placed on the next line, otherwise ! 460: ;; it is indented like any other form (i.e. forms line up under first). ! 461: ! 462: (put 'lambda 'lisp-indent-hook 'defun) ! 463: (put 'progn 'lisp-indent-hook 0) ! 464: (put 'prog1 'lisp-indent-hook 1) ! 465: (put 'save-excursion 'lisp-indent-hook 0) ! 466: (put 'save-window-excursion 'lisp-indent-hook 0) ! 467: (put 'save-restriction 'lisp-indent-hook 0) ! 468: (put 'let 'lisp-indent-hook 1) ! 469: (put 'let* 'lisp-indent-hook 1) ! 470: (put 'while 'lisp-indent-hook 1) ! 471: (put 'if 'lisp-indent-hook 2) ! 472: (put 'catch 'lisp-indent-hook 1) ! 473: (put 'condition-case 'lisp-indent-hook 2) ! 474: (put 'unwind-protect 'lisp-indent-hook 1) ! 475: (put 'with-output-to-temp-buffer 'lisp-indent-hook 1) ! 476: ! 477: (defun indent-sexp () ! 478: "Indent each line of the list starting just after point." ! 479: (interactive) ! 480: (let ((indent-stack (list nil)) (next-depth 0) bol ! 481: outer-loop-done inner-loop-done state this-indent) ! 482: ;; Get error now if we don't have a complete sexp after point. ! 483: (save-excursion (forward-sexp 1)) ! 484: (save-excursion ! 485: (setq outer-loop-done nil) ! 486: (while (not outer-loop-done) ! 487: (setq last-depth next-depth ! 488: innerloop-done nil) ! 489: ;; Parse this line so we can learn the state ! 490: ;; to indent the next line. ! 491: ;; This inner loop goes through only once ! 492: ;; unless a line ends inside a string. ! 493: (while (and (not innerloop-done) ! 494: (not (setq outer-loop-done (eobp)))) ! 495: (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) ! 496: nil nil state)) ! 497: (setq next-depth (car state)) ! 498: ;; If the line contains a comment other than the sort ! 499: ;; that is indented like code, ! 500: ;; indent it now with indent-for-comment. ! 501: ;; Comments indented like code are right already. ! 502: ;; In any case clear the in-comment flag in the state ! 503: ;; because parse-partial-sexp never sees the newlines. ! 504: (if (car (nthcdr 4 state)) ! 505: (progn (indent-for-comment) ! 506: (end-of-line) ! 507: (setcar (nthcdr 4 state) nil))) ! 508: ;; If this line ends inside a string, ! 509: ;; go straight to next line, remaining within the inner loop, ! 510: ;; and turn off the \-flag. ! 511: (if (car (nthcdr 3 state)) ! 512: (progn ! 513: (forward-line 1) ! 514: (setcar (nthcdr 5 state) nil)) ! 515: (setq innerloop-done t))) ! 516: (if (setq outer-loop-done (<= next-depth 0)) ! 517: nil ! 518: (while (> last-depth next-depth) ! 519: (setq indent-stack (cdr indent-stack) ! 520: last-depth (1- last-depth))) ! 521: (while (< last-depth next-depth) ! 522: (setq indent-stack (cons nil indent-stack) ! 523: last-depth (1+ last-depth))) ! 524: ;; Now go to the next line and indent it according ! 525: ;; to what we learned from parsing the previous one. ! 526: (forward-line 1) ! 527: (setq bol (point)) ! 528: (skip-chars-forward " \t") ! 529: ;; But not if the line is blank, or just a comment ! 530: ;; (except for double-semi comments; indent them as usual). ! 531: (if (or (eobp) (looking-at "[;\n]")) ! 532: nil ! 533: (if (and (car indent-stack) ! 534: (>= (car indent-stack) 0)) ! 535: (setq this-indent (car indent-stack)) ! 536: (let ((val (calculate-lisp-indent ! 537: (if (car indent-stack) (- (car indent-stack)))))) ! 538: (if (integerp val) ! 539: (setcar indent-stack ! 540: (setq this-indent val)) ! 541: (setcar indent-stack (- (car (cdr val)))) ! 542: (setq this-indent (car val))))) ! 543: (if (/= (current-column) this-indent) ! 544: (progn (delete-region bol (point)) ! 545: (indent-to this-indent))))))))) ! 546: ! 547: (defun indent-code-rigidly (start end arg &optional nochange-regexp) ! 548: "Indent all lines of code, starting in the region, sideways by ARG columns. ! 549: Does not affect lines starting inside comments or strings, ! 550: assuming that the start of the region is not inside them. ! 551: Called from a program, takes args START, END, COLUMNS and NOCHANGE-REGEXP. ! 552: The last is a regexp which, if matched at the beginning of a line, ! 553: means don't indent that line." ! 554: (interactive "r\np") ! 555: (let (state) ! 556: (save-excursion ! 557: (goto-char end) ! 558: (setq end (point-marker)) ! 559: (goto-char start) ! 560: (or (bolp) ! 561: (setq state (parse-partial-sexp (point) ! 562: (progn ! 563: (forward-line 1) (point)) ! 564: nil nil state))) ! 565: (while (< (point) end) ! 566: (or (car (nthcdr 3 state)) ! 567: (and nochange-regexp ! 568: (looking-at nochange-regexp)) ! 569: ;; If line does not start in string, indent it ! 570: (let ((indent (current-indentation))) ! 571: (delete-region (point) (progn (skip-chars-forward " \t") (point))) ! 572: (or (eolp) ! 573: (indent-to (max 0 (+ indent arg)) 0)))) ! 574: (setq state (parse-partial-sexp (point) ! 575: (progn ! 576: (forward-line 1) (point)) ! 577: nil nil state)))))) ! 578:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.