Add support for range objects in Eshell "for" loops
* lisp/eshell/esh-cmd.el (eshell-for-iterate): Add support for 'eshell-range' objects. * test/lisp/eshell/esh-cmd-tests.el (esh-cmd-test/for-loop-range): New test. * doc/misc/eshell.texi (Control Flow): Update documentation. * etc/NEWS: Announce this change.
This commit is contained in:
parent
ed9ea57e57
commit
ee87af4f16
4 changed files with 42 additions and 5 deletions
|
@ -1761,11 +1761,15 @@ satisfied.
|
|||
Repeatedly evaluate @var{subcommand} until @var{conditional} is
|
||||
satisfied.
|
||||
|
||||
@item for @var{var} in @var{list}@dots{} @var{subcommand}
|
||||
Iterate over each element of @var{list}, storing the element in
|
||||
@var{var} and evaluating @var{subcommand}. If @var{list} is not a list,
|
||||
treat it as a list of one element. If you specify multiple @var{lists},
|
||||
this will iterate over each of them in turn.
|
||||
@item for @var{var} in @var{sequence}@dots{} @var{subcommand}
|
||||
Iterate over each element of @var{sequence}, storing the element in
|
||||
@var{var} and evaluating @var{subcommand}. If @var{sequence} is a
|
||||
range of the form @code{@var{begin}..@var{end}}, iterate over each
|
||||
integer between @var{begin} and @var{end}, not including @var{end}. If
|
||||
@var{sequence} is not a sequence, treat it as a list of one element.
|
||||
|
||||
If you specify multiple @var{sequences}, this will iterate over each of
|
||||
them in turn.
|
||||
|
||||
@end table
|
||||
|
||||
|
|
6
etc/NEWS
6
etc/NEWS
|
@ -280,6 +280,12 @@ These functions now take an optional ERROR-TARGET argument to control
|
|||
where to send the standard error output. See the "(eshell) Entry
|
||||
Points" node in the Eshell manual for more details.
|
||||
|
||||
+++
|
||||
*** You can now loop over ranges of integers with the Eshell 'for' command.
|
||||
When passing a range like 'BEGIN..END' to the Eshell 'for' command,
|
||||
Eshell will now iterate over each integer between BEGIN and END, not
|
||||
including END.
|
||||
|
||||
+++
|
||||
*** Conditional statements in Eshell now use an 'else' keyword.
|
||||
Eshell now prefers the following form when writing conditionals:
|
||||
|
|
|
@ -530,7 +530,19 @@ the second is ignored."
|
|||
"Iterate over the elements of each sequence in ARGS.
|
||||
If ARGS is not a sequence, treat it as a list of one element."
|
||||
(dolist (arg args)
|
||||
(when (eshell--range-string-p arg)
|
||||
(setq arg (eshell--string-to-range arg)))
|
||||
(cond
|
||||
((eshell-range-p arg)
|
||||
(let ((i (eshell-range-begin arg))
|
||||
(end (eshell-range-end arg)))
|
||||
;; NOTE: We could support unbounded ranges here, but those
|
||||
;; aren't very easy to use in Eshell yet. (We'd need something
|
||||
;; like the "break" statement for "for" loops.)
|
||||
(cl-assert (and i end))
|
||||
(while (< i end)
|
||||
(iter-yield i)
|
||||
(cl-incf i))))
|
||||
((stringp arg)
|
||||
(iter-yield arg))
|
||||
((listp arg)
|
||||
|
|
|
@ -341,6 +341,21 @@ processes correctly."
|
|||
(eshell-match-command-output "for i in `[1 2 3] { echo $i }"
|
||||
"1\n2\n3\n")))
|
||||
|
||||
(ert-deftest esh-cmd-test/for-loop-range ()
|
||||
"Test invocation of a for loop iterating over a range."
|
||||
(with-temp-eshell
|
||||
(eshell-match-command-output "for i in 1..5 { echo $i }"
|
||||
"1\n2\n3\n4\n")
|
||||
(let ((eshell-test-value 2))
|
||||
(eshell-match-command-output "for i in $eshell-test-value..5 { echo $i }"
|
||||
"2\n3\n4\n"))
|
||||
;; Make sure range syntax only work when it's part of the literal
|
||||
;; syntax; a variable expanding to something that looks like a range
|
||||
;; doesn't count.
|
||||
(let ((eshell-test-value "1..5"))
|
||||
(eshell-match-command-output "for i in $eshell-test-value { echo $i }"
|
||||
"1..5\n")))))
|
||||
|
||||
(ert-deftest esh-cmd-test/for-loop-mixed-args ()
|
||||
"Test invocation of a for loop iterating over multiple arguments."
|
||||
(with-temp-eshell
|
||||
|
|
Loading…
Add table
Reference in a new issue