chiark / gitweb /
el/dot-emacs.el: Fix indentation of `loop'.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 1 Jul 2020 18:52:49 +0000 (19:52 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 9 Aug 2020 03:34:42 +0000 (04:34 +0100)
This one has been annoying me for years.

el/dot-emacs.el

index 09da2d690f062274a4ec1f1a29d472eb0d37c1c0..fc3c13fcc87414104f579981af28d066137ef7e0 100644 (file)
@@ -4306,9 +4306,12 @@ (defun mdw-fontify-lispy ()
 
 ;; Special indentation.
 
-(setq lisp-simple-loop-indentation 2
-      lisp-loop-keyword-indentation 6
-      lisp-loop-forms-indentation 6)
+(defvar mdw-lisp-loop-default-indent 2)
+
+(setq lisp-simple-loop-indentation 0
+      lisp-loop-keyword-indentation 0
+      lisp-loop-forms-indentation 2
+      lisp-lambda-list-keyword-parameter-alignment t)
 
 (defun mdw-indent-funcall (path state indent-point sexp-column normal-indent)
   "Indent `funcall' more usefully.
@@ -4327,6 +4330,58 @@ (defun mdw-indent-funcall (path state indent-point sexp-column normal-indent)
                       (current-column))))))))
 (put 'funcall 'common-lisp-indent-function 'mdw-indent-funcall)
 
+(defadvice common-lisp-loop-part-indentation
+    (around mdw-fix-loop-indentation (indent-point state) activate compile)
+  "Improve `loop' indentation.
+If the first subform is on the same line as the `loop' keyword, then
+align the other subforms beneath it.  Otherwise, indent them
+`mdw-lisp-loop-default-indent' columns in from the opening parenthesis."
+
+  (let* ((loop-indentation (save-excursion
+                            (goto-char (elt state 1))
+                            (current-column))))
+
+    ;; Don't really care about this.
+    (when (and (eq lisp-indent-backquote-substitution-mode 'corrected))
+      (save-excursion
+       (goto-char (elt state 1))
+       (cl-incf loop-indentation
+                (cond ((eq (char-before) ?,) -1)
+                      ((and (eq (char-before) ?@)
+                            (progn (backward-char)
+                                   (eq (char-before) ?,)))
+                       -2)
+                      (t 0)))))
+
+    ;; If the first loop item is on the same line as the `loop' itself then
+    ;; use that as the baseline.  Otherwise advance by the default indent.
+    (goto-char (cadr state))
+    (forward-char 1)
+    (let ((baseline-indent
+          (if (= (line-number-at-pos)
+                 (if (condition-case nil (progn (forward-sexp 2) t)
+                       (scan-error nil))
+                     (progn (forward-sexp -1) (line-number-at-pos))
+                   -1))
+              (current-column)
+            (+ loop-indentation mdw-lisp-loop-default-indent))))
+
+      (goto-char indent-point)
+      (beginning-of-line)
+
+      (setq ad-return-value
+           (list
+            (cond ((not (lisp-extended-loop-p (elt state 1)))
+                   (+ baseline-indent lisp-simple-loop-indentation))
+                  ((looking-at "^\\s-*\\(:?\\sw+\\|;\\)")
+                   (+ baseline-indent lisp-loop-keyword-indentation))
+                  (t
+                   (+ baseline-indent lisp-loop-forms-indentation)))
+
+            ;; Tell the caller that the next line needs recomputation, even
+            ;; though it doesn't start a sexp.
+            loop-indentation)))))
+
 ;; SLIME setup.
 
 (defvar mdw-friendly-name "[mdw]"