From 688ec23060f89a75d7356bba576bc8d31f32174f Mon Sep 17 00:00:00 2001 From: akater Date: Wed, 29 Sep 2021 15:45:32 +0000 Subject: [PATCH] ; Fixup: cl-flet indentation Addresses several deficiencies in bugfix 38037e04cb05cb1f2b604f0b1602d36b0bcf6985 - Check whether we're in the relevant subexpression of flet and friends. - Add -p to the predicate's name. - Add cl-macrolet cl-flet* cl-symbol-macrolet to the list of local definers. cl-symbol-macrolet added because this is how SLIME indents symbol-macrolet. --- lisp/emacs-lisp/lisp-mode.el | 55 ++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 7ce857e990..d2d63606da 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -1106,26 +1106,55 @@ defun calculate-lisp-indent (&optional parse-start) (t normal-indent)))))) -(defun lisp--local-defform-body (state) - "Return non-nil if at local definition body according to STATE. +(defun lisp--local-defform-body-p (state) + "Return non-nil when at local definition body according to STATE. STATE is the `parse-partial-sexp' state for current position." (when-let ((start-of-innermost-containing-list (nth 1 state))) - (let* ((parents (nth 9 state)) - (second-cons-after (cddr parents)) - second-order-parent) + (let* ((parents (nth 9 state)) second-order-parent + (second-cons-after (cddr parents))) (while second-cons-after (when (= start-of-innermost-containing-list (car second-cons-after)) (setq second-order-parent (car parents) ;; Leave the loop. second-cons-after nil)) - (pop second-cons-after) - (pop parents)) + (pop second-cons-after) (pop parents)) (and second-order-parent (save-excursion (goto-char (1+ second-order-parent)) - (memq (read (current-buffer)) - '(cl-flet cl-labels))))))) + (and (memq (read (current-buffer)) + '( cl-flet cl-labels cl-macrolet cl-flet* + cl-symbol-macrolet)) + ;; Now we must check that we are + ;; in the second element of the flet-like form. + ;; It would be easier if `parse-partial-sexp' also recorded + ;; relative positions of subsexps in supersexps + ;; but it doesn't so we check manually. + ;; + ;; First, we must be looking at list now. + (ignore-errors (when (= (scan-lists (point) 1 0) + (scan-sexps (point) 1)) + ;; Looking at list; descend into it: + (down-list 1) + t)) + ;; In Wishful Lisp, the following form would be + ;; (cl-member start-of-innermost-containing-list + ;; (points-at-beginning-of-lists-at-this-level) + ;; :test #'=) + (cl-loop + with pos = (ignore-errors + ;; The first local definition may be indented + ;; with whitespace following open paren. + (goto-char (scan-lists (point) 1 0)) + (goto-char (scan-lists (point) -1 0)) + (point)) + while pos + do (if (= start-of-innermost-containing-list pos) + (cl-return t) + (setq pos (ignore-errors + (goto-char (scan-lists (point) 2 0)) + (goto-char (scan-lists (point) -1 0)) + (point))))))))))) (defun lisp-indent-function (indent-point state) "This function is the normal value of the variable `lisp-indent-function'. @@ -1160,7 +1189,9 @@ defun lisp-indent-function (indent-point state) (if (and (elt state 2) (not (looking-at "\\sw\\|\\s_"))) ;; car of form doesn't seem to be a symbol - (if (lisp--local-defform-body state) + (if (lisp--local-defform-body-p state) + ;; We nevertheless check whether we are in flet-like form + ;; as we presume local function names could be non-symbols. (lisp-indent-defform state indent-point) (if (not (> (save-excursion (forward-line 1) (point)) calculate-lisp-indent-last-sexp)) @@ -1184,8 +1215,8 @@ defun lisp-indent-function (indent-point state) (and (null method) (> (length function) 3) (string-match "\\`def" function)) - ;; Check whether we are in flet or labels. - (lisp--local-defform-body state)) + ;; Check whether we are in flet-like form. + (lisp--local-defform-body-p state)) (lisp-indent-defform state indent-point)) ((integerp method) (lisp-indent-specform method state -- 2.32.0