aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoam Postavsky2017-03-15 22:27:27 -0400
committerNoam Postavsky2017-04-22 14:09:58 -0400
commit4713dd425beac5cb459704e67dcb8f6faf714375 (patch)
tree5f3ba3603a4bc724180d9b872b50c183c39a664b
parent2f6769f9cdb799e880fdcc09057353a0a2349bfc (diff)
downloademacs-4713dd425beac5cb459704e67dcb8f6faf714375.tar.gz
emacs-4713dd425beac5cb459704e67dcb8f6faf714375.zip
Add new `lisp-indent-region' that doesn't reparse the code.
Both `lisp-indent-region' and `lisp-indent-line' now use `syntax-ppss' to get initial state, so they will no longer indent string literal contents. * lisp/emacs-lisp/lisp-mode.el (lisp-ppss): New function, like `syntax-ppss', but with a more dependable item 2. (lisp-indent-region): New function, like `indent-region-line-by-line' but additionally keep a running parse state to avoid reparsing the code repeatedly. Use `lisp-ppss' to get initial state. (lisp-indent-line): Take optional PARSE-STATE argument, pass it to `calculate-lisp-indent', use `lisp-ppss' if not given. (lisp-mode-variables): Set `indent-region-function' to `lisp-indent-region'.
-rw-r--r--lisp/emacs-lisp/lisp-mode.el48
1 files changed, 44 insertions, 4 deletions
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 89d5659f300..54d916887cd 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -594,6 +594,7 @@ font-lock keywords will not be case sensitive."
594 ;; I believe that newcomment's auto-fill code properly deals with it -stef 594 ;; I believe that newcomment's auto-fill code properly deals with it -stef
595 ;;(set (make-local-variable 'adaptive-fill-mode) nil) 595 ;;(set (make-local-variable 'adaptive-fill-mode) nil)
596 (setq-local indent-line-function 'lisp-indent-line) 596 (setq-local indent-line-function 'lisp-indent-line)
597 (setq-local indent-region-function 'lisp-indent-region)
597 (setq-local outline-regexp ";;;\\(;* [^ \t\n]\\|###autoload\\)\\|(") 598 (setq-local outline-regexp ";;;\\(;* [^ \t\n]\\|###autoload\\)\\|(")
598 (setq-local outline-level 'lisp-outline-level) 599 (setq-local outline-level 'lisp-outline-level)
599 (setq-local add-log-current-defun-function #'lisp-current-defun-name) 600 (setq-local add-log-current-defun-function #'lisp-current-defun-name)
@@ -748,12 +749,51 @@ function is `common-lisp-indent-function'."
748 :type 'function 749 :type 'function
749 :group 'lisp) 750 :group 'lisp)
750 751
751(defun lisp-indent-line () 752(defun lisp-ppss (&optional pos)
753 "Return Parse-Partial-Sexp State at POS, defaulting to point.
754Like to `syntax-ppss' but includes the character address of the
755last complete sexp in the innermost containing list at position
7562 (counting from 0). This is important for lisp indentation."
757 (unless pos (setq pos (point)))
758 (let ((pss (syntax-ppss pos)))
759 (if (nth 9 pss)
760 (parse-partial-sexp (car (last (nth 9 pss))) pos)
761 pss)))
762
763(defun lisp-indent-region (start end)
764 "Indent region as Lisp code, efficiently."
765 (save-excursion
766 (setq end (copy-marker end))
767 (goto-char start)
768 ;; The default `indent-region-line-by-line' doesn't hold a running
769 ;; parse state, which forces each indent call to reparse from the
770 ;; beginning. That has O(n^2) complexity.
771 (let* ((parse-state (lisp-ppss start))
772 (last-syntax-point start)
773 (pr (unless (minibufferp)
774 (make-progress-reporter "Indenting region..." (point) end))))
775 (while (< (point) end)
776 (unless (and (bolp) (eolp))
777 (lisp-indent-line parse-state))
778 (forward-line 1)
779 (let ((last-sexp (nth 2 parse-state)))
780 (setq parse-state (parse-partial-sexp last-syntax-point (point)
781 nil nil parse-state))
782 ;; It's important to preserve last sexp location for
783 ;; `calculate-lisp-indent'.
784 (unless (nth 2 parse-state)
785 (setf (nth 2 parse-state) last-sexp))
786 (setq last-syntax-point (point)))
787 (and pr (progress-reporter-update pr (point))))
788 (and pr (progress-reporter-done pr))
789 (move-marker end nil))))
790
791(defun lisp-indent-line (&optional parse-state)
752 "Indent current line as Lisp code." 792 "Indent current line as Lisp code."
753 (interactive) 793 (interactive)
754 (let ((indent (calculate-lisp-indent)) 794 (let ((pos (- (point-max) (point)))
755 (pos (- (point-max) (point)))) 795 (indent (progn (beginning-of-line)
756 (beginning-of-line) 796 (calculate-lisp-indent (or parse-state (lisp-ppss))))))
757 (skip-chars-forward " \t") 797 (skip-chars-forward " \t")
758 (if (or (null indent) (looking-at "\\s<\\s<\\s<")) 798 (if (or (null indent) (looking-at "\\s<\\s<\\s<"))
759 ;; Don't alter indentation of a ;;; comment line 799 ;; Don't alter indentation of a ;;; comment line