branch: elpa/loopy
commit 3c6beb610fded397088d616c1cc3cf6c90c8e568
Author: okamsn <28612288+oka...@users.noreply.github.com>
Commit: GitHub <nore...@github.com>

    Combine `loopy-iter-bare-commands` and 
`loopy-iter-bare-special-macro-arguments`. (#242)
    
    Closes #238.
    
    - Create `loopy-iter-bare-names`, a list which contains both.  Use this 
variable
      in `loopy-iter`.
    
    - Filter out supposed commands whose parsing function is a symbol matching 
one
      of the known pseudo-functions for special macro arguments when creating
      the bare-name sub-macros.
      - Add a NOTE saying to update the list of known pseudo-functions when
        changing the default value of `loopy-parsers`.
    
    - Make the `loopy-iter-bare-commands` and
      `loopy-iter-bare-special-macro-arguments` deprecated aliases of the new
      `loopy-iter-bare-names`.
    
    - Rename `loopy-iter-overwritten-command-parsers` to
      `loopy-iter-overwritten-parsers` to be consistent with the new 
`loopy-parsers`
      variable.  Make the old name an alias, but not deprecated.
    
    - Update the Org doc.
    
    - Update the README.
    
    - Update the CHANGELOG.
    
    - Add tests:
    
      - Add test `bare-names` to `tests/iter-tests.el` to test use of
        `loopy-iter-bare-names`.
    
      - Change occurences of `loopy-iter-bare-commands` to 
`loopy-iter-bare-names` in
        these tests in `tests/tests.el`:
        - accumulation-conflicting-final-updates
        - accumulation-conflicting-final-updates-ht
        - custom-command-sum
        - custom-command-sum-ht
        - custom-command-always-pass
    
      - Change occurences of `loopy-iter-bare-special-macro-arguments` to
        `loopy-iter-bare-names` in these tests in `tests/tests.el`:
        - custom-alias-flag
        - custom-alias-with
        - custom-alias-without
        - custom-alias-before-do
        - custom-alias-after-do
---
 CHANGELOG.md        |  22 +++++++---
 README.org          |   2 +
 doc/loopy-doc.org   |  29 ++++++------
 lisp/loopy-iter.el  | 124 +++++++++++++++++++++++++++++++++-------------------
 lisp/loopy-vars.el  |   4 ++
 tests/iter-tests.el |   5 +++
 tests/tests.el      |  40 ++++++++---------
 7 files changed, 139 insertions(+), 87 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 927a1671e8c..5c1aaade4e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,14 +17,20 @@ For Loopy Dash, see <https://github.com/okamsn/loopy-dash>.
   binds `VAR` to `nil`, but since this form is indistinguishable from a 
mistake,
   and since `nil` is a short word to write, this behavior is deprecated.
 
-- `loopy-command-parsers` and `loopy-aliases` are both deprecated in favor of
-  the newly added `loopy-parsers` ([#237]).  The new user option simplifies the
-  code internally, making it easier to add local overrides in the future, which
-  will make code which custom commands more portable.
+- Some variables were combined to simplify the code internally and make it
+  easier to add local overrides in the future, which will make code which 
custom
+  commands more portable.
 
-  The new user option is a hash table which maps symbols to parsing functions.
-  There is no longer a separate mapping of aliases to original names.  However,
-  `loopy-defalias` will continue to work.
+  - `loopy-command-parsers` and `loopy-aliases` are both deprecated in favor of
+    the newly added `loopy-parsers` ([#237]).  The new user option is a hash
+    table which maps symbols to parsing functions.  There is no longer a
+    separate mapping of aliases to original names.  However, `loopy-defalias`
+    will continue to work.
+
+  - `loopy-iter-bare-special-marco-arguments` and `loopy-iter-bare-commands` 
are
+    both deprecated in favor of the newly added `loopy-iter-bare-names` 
([#242],
+    [#238]). The new user option is a list which by default contains all 
symbols
+    previously listed in the old variables.
 
 - Separate `when` and `unless` commands to have different parsing functions
   ([#234], [#240]).  The old implementation used the name of the command in the
@@ -44,8 +50,10 @@ For Loopy Dash, see <https://github.com/okamsn/loopy-dash>.
 [#229]: https://github.com/okamsn/loopy/PR/229
 [#234]: https://github.com/okamsn/loopy/issues/234
 [#237]: https://github.com/okamsn/loopy/PR/237
+[#238]: https://github.com/okamsn/loopy/issues/238
 [#240]: https://github.com/okamsn/loopy/PR/240
 [#241]: https://github.com/okamsn/loopy/PR/241
+[#242]: https://github.com/okamsn/loopy/PR/242
 
 ## 0.14.0
 
diff --git a/README.org b/README.org
index fc095ca0a19..827186c511b 100644
--- a/README.org
+++ b/README.org
@@ -41,6 +41,8 @@ please let me know.
    - ~loopy-command-parsers~ and ~loopy-aliases~ are deprecated in favor of
      a single hash table in the new user option ~loopy-parsers~.  This
      simplified the code and will make adding local overrides easier.
+   - ~loopy-iter-bare-special-macro-arguments~ and ~loopy-iter-bare-commands~
+     are deprecated in favor of the single variable ~loopy-iter-bare-names~.
    - =when= and =unless= are now implemented separately, fixing when the
      commands are aliased.
  - Version 0.14.0:
diff --git a/doc/loopy-doc.org b/doc/loopy-doc.org
index 75066ddaf9c..65dedf5d7bf 100644
--- a/doc/loopy-doc.org
+++ b/doc/loopy-doc.org
@@ -4511,8 +4511,8 @@ which loop commands are treated as macros to be expanded 
by ~macroexpand-all~.
 Hence, a loop command could overshadow the function value of a symbol.  There
 are two ways to avoid such conflicts.
 
-#+cindex: loopy-iter bare commands
-#+vindex: loopy-iter-bare-commands
+#+cindex: loopy-iter bare names
+#+vindex: loopy-iter-bare-names
 The first way is to use non-conflicting aliases.  Like in Iterate (and
 ~cl-loop~, to an extent), almost all commands in ~loopy~ have aliases in the
 present-participle form (the "-ing" form).  For example, Loopy provides the
@@ -4540,17 +4540,17 @@ arguments that are recognized by default are given in 
[[#iter-default-names]].
                           (at outer (collecting j))))
 #+end_src
 
-The non-conflicting command aliases recognized by ~loopy-iter~ can be 
customized
-with the user option ~loopy-iter-bare-commands~, which is a list of symbols
-naming commands and their aliases.  Again, these commands are found in the loop
-body by using Emacs Lisp's macro-expansion features, so adding an alias that
-overrides a symbol's function definition can cause errors.  ~loopy~, whose
-environment is more limited, does not have this restriction.
-
-#+vindex: loopy-iter-bare-special-macro-arguments
-The special macro arguments (and their aliases) recognized by ~loopy-iter~ can
-be set in the user option ~loopy-iter-bare-special-macro-arguments~.  Some of
-their built-in aliases, such as =let*= for =with=, are excluded by default.
+The non-conflicting names of loop commands and special macro arguments
+recognized by ~loopy-iter~ can be customized with the user option
+~loopy-iter-bare-names~, which is a list of symbols naming commands, special
+macro arguments, and their aliases.  Again, these symbols are found in the loop
+body by using Emacs Lisp's macro-expansion features, so adding a name that
+overrides a symbol's function definition can cause errors. Names that are
+obvious conflicts, such as the non-suffixed versions of most loop commands 
(such
+as =list=), loop commands that are unneeded in ~loopy-iter~ (such as =when=),
+and the names of Loopy features that are the same as the names of Emacs Lisp
+features (such as =let*= for =with=) are by default excluded from
+~loopy-iter-bare-names~.
 
 #+cindex: loopy-iter keywords
 #+vindex: loopy-iter-keywords
@@ -4673,8 +4673,7 @@ Finally, there are a few things to keep in mind when 
using ~loopy-iter~:
 
 This section lists the default aliases supported as bare names in the macro
 ~loopy-iter~.  The list of supported bare names can be customized in the user
-options ~loopy-iter-bare-commands~ and
-~loopy-iter-bare-special-macro-arguments~.
+options ~loopy-iter-bare-names~.
 
 By default, the following commands are not recognized:
 - =do= and =command-do=, which are not needed.
diff --git a/lisp/loopy-iter.el b/lisp/loopy-iter.el
index da806bcbe2f..86a63912e03 100644
--- a/lisp/loopy-iter.el
+++ b/lisp/loopy-iter.el
@@ -99,8 +99,40 @@ Without these keywords, one must use one of the names given 
in
 
 ;;;; For parsing commands
 
-(defcustom loopy-iter-bare-commands
-  '(accumulating
+(define-obsolete-variable-alias 'loopy-iter-bare-commands
+  'loopy-iter-bare-names
+  "2025-07")
+(define-obsolete-variable-alias 'loopy-iter-bare-special-macro-arguments
+  'loopy-iter-bare-names
+  "2025-07")
+(defcustom loopy-iter-bare-names
+  '(;; Bare special macro arguments
+    after-do
+    after
+    else-do
+    else
+    before-do
+    before
+    initially-do
+    initially
+    finally-do
+    finally
+    finally-return
+    finally-protect
+    finally-protected
+    flag
+    flags
+    named
+    accum-opt
+    opt-accum
+    with
+    init
+    without
+    no-with
+    no-init
+    wrap
+    ;; Bare commands
+    accumulating
     adjoining
     always
     appending
@@ -164,9 +196,11 @@ Without these keywords, one must use one of the names 
given in
     thereis
     unioning
     vconcating)
-  "Commands recognized in `loopy-iter' without a preceding keyword.
+  "`loopy' features recognized in `loopy-iter' without a preceeding keyword.
 
-For special marco arguments, see `loopy-iter-bare-special-macro-arguments'."
+This list includes special macro arguments as well as loop commands.
+See the Info node `(loopy)The loopy-iter Macro' and the Info node
+`(loopy)Default Bare Names in loopy-iter'."
   :type '(repeat symbol)
   :group 'loopy-iter)
 
@@ -215,7 +249,8 @@ during a second pass on the expanded code."
 
 ;;;;; Overwritten parser definitions
 
-(defcustom loopy-iter-overwritten-command-parsers
+(defvaralias 'loopy-iter-overwritten-command-parsers 
'loopy-iter-overwritten-parsers)
+(defcustom loopy-iter-overwritten-parsers
   '((at       . loopy-iter--parse-at-command))
   "Overwritten command parsers.
 
@@ -258,24 +293,6 @@ These commands affect other loops higher up in the call 
list."
 
 ;;;; For parsing special macro arguments
 
-(defcustom loopy-iter-bare-special-macro-arguments
-  '( after-do        after else-do else
-     before-do       before initially-do initially
-     finally-do      finally
-     finally-return
-     finally-protect finally-protected
-     flag            flags
-     named
-     accum-opt       opt-accum
-     with            init
-     without         no-with no-init
-     wrap)
-  "Symbols naming recognized special macro arguments and their aliases.
-
-These should not overwrite any other macros or functions in Emacs Lisp."
-  :type '(repeat symbol)
-  :group 'loopy-iter)
-
 ;; TODO: Combine this with `loopy--def-special-processor'.
 (defmacro loopy-iter--def-special-processor (name &rest body)
   "Create a processor for the special macro argument NAME and its aliases.
@@ -306,7 +323,7 @@ Returns BODY without the `%s' argument."
                  (let ((first (cl-first expr)))
                    (or (and (memq first loopy-iter-keywords)
                             (eq ,fn-sym (loopy--get-command-parser (cl-second 
expr))))
-                       (and (memq first 
loopy-iter-bare-special-macro-arguments)
+                       (and (memq first loopy-iter-bare-names)
                             (eq ,fn-sym (loopy--get-command-parser first))))))
             (collecting matching-args expr)
           (collecting new-body expr))
@@ -338,7 +355,7 @@ Returns BODY without the `%s' argument."
                ,(pred (lambda (x) (eq 
'loopy--parse-named-special-macro-argument
                                       (loopy--get-command-parser x))))
                ,name . ,rest)
-             `(,(and (pred (lambda (x) (memq x 
loopy-iter-bare-special-macro-arguments)))
+             `(,(and (pred (lambda (x) (memq x loopy-iter-bare-names)))
                      (pred (lambda (x) (eq 
'loopy--parse-named-special-macro-argument
                                            (loopy--get-command-parser x)))))
                ,name . ,rest))
@@ -468,7 +485,7 @@ to use `loopy' in general.
              loopy-command-parsers))
 
    ;; NOTE: This one isn't obsolete but needs to happen before aliases.
-   (when loopy-iter-overwritten-command-parsers
+   (when loopy-iter-overwritten-parsers
      (map-do (lambda (k v)
                (puthash k v loopy--parsers-internal))
              loopy-iter-overwritten-command-parsers))
@@ -513,25 +530,42 @@ to use `loopy' in general.
                                           (loopy--parse-loop-command args))
                                       (push other 
loopy-iter--non-main-body-instructions)
                                       (macroexp-progn main))))))
-                    (loopy (list command loopy-iter-bare-commands)
-                           (collect
-                            (cons command
-                                  ;; Expanding functions do not receive the 
head
-                                  ;; of the expression, only the arguments, so
-                                  ;; we use a lexical lambda to include that
-                                  ;; information.
-                                  (let ((cmd command))
-                                    (lambda (&rest args)
-                                      (loopy--bind-main-body (main other)
-                                          ;; Bind here in case a command 
required to
-                                          ;; be in the top level is found in an
-                                          ;; expression while parsing an actual
-                                          ;; top-level command.
-                                          (let* ((loopy-iter--level (1+ 
loopy-iter--level))
-                                                 (loopy--in-sub-level (> 
loopy-iter--level 1)))
-                                            (loopy--parse-loop-command (cons 
cmd args)))
-                                        (push other 
loopy-iter--non-main-body-instructions)
-                                        (macroexp-progn main)))))))))
+                    ;; NOTE: Processing the special macro arguments removes
+                    ;; their occurences from the body, so no remaining symbol
+                    ;; should lead to one of their pseudo-functions, but we
+                    ;; check here anyway, just in case the symbol might show up
+                    ;; at a lower level in a wrapped Lisp feature.
+                    (loopy (list symbol loopy-iter-bare-names)
+                           (unless (memq (loopy--get-command-parser symbol)
+                                         '( 
loopy--parse-accum-opt-special-macro-argument
+                                            
loopy--parse-after-do-special-macro-argument
+                                            
loopy--parse-before-do-special-macro-argument
+                                            
loopy--parse-finally-do-special-macro-argument
+                                            
loopy--parse-finally-protect-special-macro-argument
+                                            
loopy--parse-finally-return-special-macro-argument
+                                            
loopy--parse-flag-special-macro-argument
+                                            
loopy--parse-with-special-macro-argument
+                                            
loopy--parse-without-special-macro-argument
+                                            
loopy--parse-named-special-macro-argument
+                                            
loopy--parse-wrap-special-macro-argument))
+                             (collect
+                              (cons symbol
+                                    ;; Expanding functions do not receive the 
head
+                                    ;; of the expression, only the arguments, 
so
+                                    ;; we use a lexical lambda to include that
+                                    ;; information.
+                                    (let ((cmd symbol))
+                                      (lambda (&rest args)
+                                        (loopy--bind-main-body (main other)
+                                            ;; Bind here in case a command 
required to
+                                            ;; be in the top level is found in 
an
+                                            ;; expression while parsing an 
actual
+                                            ;; top-level command.
+                                            (let* ((loopy-iter--level (1+ 
loopy-iter--level))
+                                                   (loopy--in-sub-level (> 
loopy-iter--level 1)))
+                                              (loopy--parse-loop-command (cons 
cmd args)))
+                                          (push other 
loopy-iter--non-main-body-instructions)
+                                          (macroexp-progn main))))))))))
            (common-env `(,@suppressed-expanders
                          ,@command-env
                          ,@macroexpand-all-environment))
diff --git a/lisp/loopy-vars.el b/lisp/loopy-vars.el
index 891a192e56b..849eece7390 100644
--- a/lisp/loopy-vars.el
+++ b/lisp/loopy-vars.el
@@ -157,6 +157,10 @@ Definition must exist.  Neither argument need be quoted."
   #s(hash-table
      test eq
      data (;; Special macro arguments
+           ;;
+           ;; NOTE: When editing the hash table, also edit the list of
+           ;; pseudo-functions for special macro arguments used in the
+           ;; definition of `loopy-iter'.
            accum-opt          loopy--parse-accum-opt-special-macro-argument
            opt-accum          loopy--parse-accum-opt-special-macro-argument
            after              loopy--parse-after-do-special-macro-argument
diff --git a/tests/iter-tests.el b/tests/iter-tests.el
index 8694e6db289..a5b5cf516ab 100644
--- a/tests/iter-tests.el
+++ b/tests/iter-tests.el
@@ -31,6 +31,11 @@
                       (repeating 3)
                       (collecting (list a b c)))))
 
+(ert-deftest bare-names ()
+  (let ((loopy-iter-bare-names (cons 'array loopy-iter-bare-names)))
+    (should (equal '(0 1 2 3)
+                   (liq (array i [0 1 2 3])
+                        (collecting i))))))
 
 ;; A list of special-form code walkers in Iterate. In Emacs Lisp, many of these
 ;; are macros, and so we should not need to test them, as they expand to 
simpler
diff --git a/tests/tests.el b/tests/tests.el
index 1c0336a9e5d..69cfd277db9 100644
--- a/tests/tests.el
+++ b/tests/tests.el
@@ -3860,8 +3860,8 @@ expansion time."
                                                   #'my-loopy-sum-command1)
                                       (map-insert 'sum2
                                                   #'my-loopy-sum-command2)))
-                       (loopy-iter-bare-commands (append '(sum1 sum2)
-                                                         
loopy-iter-bare-commands)))
+                       (loopy-iter-bare-names (append '(sum1 sum2)
+                                                      loopy-iter-bare-names)))
                    (eval (quote ,x) t)))))
   :multi-body t
   :body [((list i '(1 2 3 4 5))
@@ -3929,8 +3929,8 @@ expansion time."
                  (let ((loopy-parsers (thread-first loopy-parsers
                                                     (my-ht-map-insert 'sum1 
#'my-loopy-sum-command1)
                                                     (my-ht-map-insert 'sum2 
#'my-loopy-sum-command2)))
-                       (loopy-iter-bare-commands (append '(sum1 sum2)
-                                                         
loopy-iter-bare-commands)))
+                       (loopy-iter-bare-names (append '(sum1 sum2)
+                                                      loopy-iter-bare-names)))
                    (eval (quote ,x) t)))))
   :multi-body t
   :body [((list i '(1 2 3 4 5))
@@ -6652,8 +6652,8 @@ Wrapping with another eval to make sure variables are set 
by expansion time."
                  (let ((loopy-command-parsers
                         (map-insert loopy-command-parsers 'target-sum
                                     #'my-loopy-sum-command))
-                       (loopy-iter-bare-commands (cons 'target-sum
-                                                       
loopy-iter-bare-commands)))
+                       (loopy-iter-bare-names (cons 'target-sum
+                                                    loopy-iter-bare-names)))
                    (eval (quote ,x) t)))))
   :result 6
   :body ((target-sum my-target 1 2 3)
@@ -6672,8 +6672,8 @@ Wrapping with another eval to make sure variables are set 
by expansion time."
                  (let ((loopy-parsers (my-ht-map-insert loopy-parsers
                                                         'target-sum
                                                         
#'my-loopy-sum-command))
-                       (loopy-iter-bare-commands (cons 'target-sum
-                                                       
loopy-iter-bare-commands)))
+                       (loopy-iter-bare-names (cons 'target-sum
+                                                    loopy-iter-bare-names)))
                    (eval (quote ,x) t)))))
   :result 6
   :body ((target-sum my-target 1 2 3)
@@ -6709,8 +6709,8 @@ Otherwise, `loopy' should return t."
                  (let ((loopy-command-parsers
                         (map-insert loopy-command-parsers 'my-always
                                     #'my--loopy-always-command-parser))
-                       (loopy-iter-bare-commands (cons 'my-always
-                                                       
loopy-iter-bare-commands)))
+                       (loopy-iter-bare-names (cons 'my-always
+                                                    loopy-iter-bare-names)))
                    (eval (quote ,x) t)))))
   :result t
   :body ((list i (number-sequence 1 9))
@@ -6896,8 +6896,8 @@ NOTE: This should eventually be removed."
   :result '(1)
   :wrap ((x . `(let ((loopy-parsers
                       (my-ht-map-insert loopy-parsers 'f (map-elt 
loopy-parsers 'flag)))
-                     (loopy-iter-bare-special-macro-arguments
-                      (cons 'f loopy-iter-bare-special-macro-arguments)))
+                     (loopy-iter-bare-names
+                      (cons 'f loopy-iter-bare-names)))
                  (eval (quote ,x) t))))
   :body ((f default)
          (list i '(1))
@@ -6911,8 +6911,8 @@ NOTE: This should eventually be removed."
 (loopy-deftest custom-alias-with
   :result 1
   :wrap ((x . `(let ((loopy-parsers (my-ht-map-insert loopy-parsers 'as 
(map-elt loopy-parsers 'with)))
-                     (loopy-iter-bare-special-macro-arguments
-                      (cons 'as loopy-iter-bare-special-macro-arguments)))
+                     (loopy-iter-bare-names
+                      (cons 'as loopy-iter-bare-names)))
                  (eval (quote ,x) t))))
   :body ((as (a 1))
          (return a))
@@ -6925,8 +6925,8 @@ NOTE: This should eventually be removed."
   :result 5
   :wrap ((x . `(let ((loopy-parsers
                       (my-ht-map-insert loopy-parsers 'ignore (map-elt 
loopy-parsers 'without)))
-                     (loopy-iter-bare-special-macro-arguments
-                      (cons 'ignore loopy-iter-bare-special-macro-arguments)))
+                     (loopy-iter-bare-names
+                      (cons 'ignore loopy-iter-bare-names)))
                  (eval  (quote (let ((a 1)
                                      (b 2))
                                  ,x
@@ -6945,8 +6945,8 @@ NOTE: This should eventually be removed."
 (loopy-deftest custom-alias-before-do
   :result 7
   :wrap ((x . `(let ((loopy-aliases (map-copy loopy-aliases))
-                     (loopy-iter-bare-special-macro-arguments
-                      (cons 'precode loopy-iter-bare-special-macro-arguments)))
+                     (loopy-iter-bare-names
+                      (cons 'precode loopy-iter-bare-names)))
                  (loopy-defalias precode before-do)
                  (eval (quote ,x) t))))
   :body ((with (i 2))
@@ -6960,8 +6960,8 @@ NOTE: This should eventually be removed."
 (loopy-deftest custom-alias-after-do
   :result t
   :wrap ((x . `(let ((loopy-aliases (map-copy loopy-aliases))
-                     (loopy-iter-bare-special-macro-arguments
-                      (cons 'postcode 
loopy-iter-bare-special-macro-arguments)))
+                     (loopy-iter-bare-names
+                      (cons 'postcode loopy-iter-bare-names)))
                  (loopy-defalias postcode after-do)
                  (eval (quote ,x) t))))
   :body ((with (my-ret nil))

Reply via email to