From 59e296eaf48494c60f5dcea88b9afd3db42b5764 Mon Sep 17 00:00:00 2001 From: akater Date: Sun, 11 Apr 2021 10:53:25 +0000 Subject: [PATCH] cl-macs: default indentation for all arglists with top-level &body --- lisp/emacs-lisp/cl-macs.el | 45 ++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 68211ec410..f04b9e9b5f 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -43,6 +43,8 @@ ;;; Code: +(eval-when-compile (require 'subr-x)) + (require 'cl-lib) (require 'macroexp) ;; `gv' is required here because cl-macs can be loaded before loaddefs.el. @@ -243,6 +245,20 @@ defvar cl--bind-defs) ;(DEF . DEFS) giving the "default default" for optargs. (defvar cl--bind-enquote) ;Non-nil if &cl-quote was in the formal arglist! (defvar cl--bind-lets) (defvar cl--bind-forms) +;;;###autoload +(defmacro cl-dolist (spec &rest body) + "Loop over a list. +Evaluate BODY with VAR bound to each `car' from LIST, in turn. +Then evaluate RESULT to get return value, default nil. +An implicit nil block is established around the loop. + +\(fn (VAR LIST [RESULT]) BODY...)" + (declare (debug ((symbolp form &optional form) cl-declarations body)) + (indent 1)) + (let ((loop `(dolist ,spec ,@body))) + (if (advice-member-p 'cl--wrap-in-nil-block 'dolist) + loop `(cl-block nil ,loop)))) + (defun cl--transform-lambda (form bind-block) "Transform a function form FORM of name BIND-BLOCK. BIND-BLOCK is the name of the symbol to which the function will be bound, @@ -319,6 +335,21 @@ defun cl--transform-lambda (form bind-block) (format "%S" (cons 'fn (cl--make-usage-args orig-args)))))) header))) + (when-let ((according-to-&body + (let ((counter 0)) + (cl-dolist (x orig-args) + (cond + ((eq '&body x) (cl-return counter)) + ((not (memq x cl--lambda-list-keywords)) + (cl-incf counter))))))) + ;; Placing the declaration in the end + ;; allows overriding the indentation setting + ;; with an explicit (declare (indent ..)) statement + ;; manually written in the form being expanded. + (setq header + (nconc header + (list + `(declare (indent ,according-to-&body)))))) ;; FIXME: we'd want to choose an arg name for the &rest param ;; and pass that as `expr' to cl--do-arglist, but that ends up ;; generating code with a redundant let-binding, so we instead @@ -1821,20 +1852,6 @@ defun cl--expand-do-loop (steps endtest body star) (apply #'append sets)))))) ,@(or (cdr endtest) '(nil))))) -;;;###autoload -(defmacro cl-dolist (spec &rest body) - "Loop over a list. -Evaluate BODY with VAR bound to each `car' from LIST, in turn. -Then evaluate RESULT to get return value, default nil. -An implicit nil block is established around the loop. - -\(fn (VAR LIST [RESULT]) BODY...)" - (declare (debug ((symbolp form &optional form) cl-declarations body)) - (indent 1)) - (let ((loop `(dolist ,spec ,@body))) - (if (advice-member-p 'cl--wrap-in-nil-block 'dolist) - loop `(cl-block nil ,loop)))) - ;;;###autoload (defmacro cl-dotimes (spec &rest body) "Loop a certain number of times. -- 2.26.2