diff options
| author | Jim Porter | 2022-11-08 22:49:23 -0800 |
|---|---|---|
| committer | Jim Porter | 2022-12-15 21:41:03 -0800 |
| commit | e63ef66c57ee74b24998a16b34949f67bbb73d8d (patch) | |
| tree | d41fe6c0405a02f78f025284a245e1c4735a6a1b /test/lisp/eshell | |
| parent | 66ac920b0c233e472c7f54d108503dfe9236d3c0 (diff) | |
| download | emacs-e63ef66c57ee74b24998a16b34949f67bbb73d8d.tar.gz emacs-e63ef66c57ee74b24998a16b34949f67bbb73d8d.zip | |
Add support for the "splice operator" in Eshell
This allows splicing lists in-place in argument lists, which is
particularly important when defining aliases using the '$*' special
variable (bug#59960).
* lisp/eshell/esh-var.el (eshell-parse-variable): Add support for the
splice operator.
(eshell-interpolate-variable): Let 'eshell-parse-variable' handle
adding 'eshell-escape-arg'.
(eshell-complete-variable-reference): Handle the splice operator.
* lisp/eshell/esh-arg.el (eshell-concat-groups)
(eshell-prepare-splice): New functions...
(eshell-resolve-current-argument): ... use them.
(eshell-splice-args): New function.
* lisp/eshell/esh-cmd.el (eshell-rewrite-named-command): Handle
'eshell-splice-args'.
* lisp/eshell/esh-util.el (eshell-list-to-string): New function...
(eshell-flatten-and-stringify): ... use it.
* lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments): Remove
'eshell-splice-args' sigils in Eshell command forms so that we can
perform completion on splice-expansions.
* lisp/eshell/em-unix.el (eshell-complete-host-reference): Don't try
to complete arguments containing "$@".
* test/lisp/eshell/esh-var-tets.el (esh-var-test/interp-list-var)
(esh-var-test/interp-list-var-concat, esh-var-test/interp-var-splice)
(esh-var-test/interp-var-splice-concat)
(esh-var-test/quoted-interp-list-var)
(esh-var-test/quoted-interp-list-var-concat)
(esh-var-test/quoted-interp-var-splice)
(esh-var-test/quoted-interp-var-splice-concat): New tests.
* test/lisp/eshell/em-alias-tests.el
(em-alias-test/alias-all-args-var-splice): New test.
* doc/misc/eshell.texi (Dollars Expansion): Explain the splice
operator.
(Aliases): Expand documentation and use '$@*'.
(Built-ins, Bugs and Ideas): Use '$@*' where appropriate.
* etc/NEWS: Announce this change.
Diffstat (limited to 'test/lisp/eshell')
| -rw-r--r-- | test/lisp/eshell/em-alias-tests.el | 9 | ||||
| -rw-r--r-- | test/lisp/eshell/esh-var-tests.el | 74 |
2 files changed, 83 insertions, 0 deletions
diff --git a/test/lisp/eshell/em-alias-tests.el b/test/lisp/eshell/em-alias-tests.el index aca622220e3..0a26e8d2011 100644 --- a/test/lisp/eshell/em-alias-tests.el +++ b/test/lisp/eshell/em-alias-tests.el | |||
| @@ -72,6 +72,15 @@ | |||
| 72 | (eshell-match-command-output "show-all-args a" "a\n") | 72 | (eshell-match-command-output "show-all-args a" "a\n") |
| 73 | (eshell-match-command-output "show-all-args a b c" "a\nb\nc\n"))) | 73 | (eshell-match-command-output "show-all-args a b c" "a\nb\nc\n"))) |
| 74 | 74 | ||
| 75 | (ert-deftest em-alias-test/alias-all-args-var-splice () | ||
| 76 | "Test alias with splicing the $* variable" | ||
| 77 | (with-temp-eshell | ||
| 78 | (eshell-insert-command "alias show-all-args 'echo args: $@*'") | ||
| 79 | (eshell-match-command-output "show-all-args" "args:\n") | ||
| 80 | (eshell-match-command-output "show-all-args a" "(\"args:\" \"a\")\n") | ||
| 81 | (eshell-match-command-output "show-all-args a b c" | ||
| 82 | "(\"args:\" \"a\" \"b\" \"c\")\n"))) | ||
| 83 | |||
| 75 | (ert-deftest em-alias-test/alias-all-args-var-indices () | 84 | (ert-deftest em-alias-test/alias-all-args-var-indices () |
| 76 | "Test alias with the $* variable using indices" | 85 | "Test alias with the $* variable using indices" |
| 77 | (with-temp-eshell | 86 | (with-temp-eshell |
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index 96fde026a54..d95669fdaf8 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el | |||
| @@ -60,6 +60,18 @@ | |||
| 60 | (eshell-command-result-equal "echo $\"user-login-name\"-foo" | 60 | (eshell-command-result-equal "echo $\"user-login-name\"-foo" |
| 61 | (concat user-login-name "-foo"))) | 61 | (concat user-login-name "-foo"))) |
| 62 | 62 | ||
| 63 | (ert-deftest esh-var-test/interp-list-var () | ||
| 64 | "Interpolate list variable" | ||
| 65 | (let ((eshell-test-value '(1 2 3))) | ||
| 66 | (eshell-command-result-equal "echo $eshell-test-value" | ||
| 67 | '(1 2 3)))) | ||
| 68 | |||
| 69 | (ert-deftest esh-var-test/interp-list-var-concat () | ||
| 70 | "Interpolate and concat list variable" | ||
| 71 | (let ((eshell-test-value '(1 2 3))) | ||
| 72 | (eshell-command-result-equal "echo a$'eshell-test-value'z" | ||
| 73 | '("a1" 2 "3z")))) | ||
| 74 | |||
| 63 | (ert-deftest esh-var-test/interp-var-indices () | 75 | (ert-deftest esh-var-test/interp-var-indices () |
| 64 | "Interpolate list variable with indices" | 76 | "Interpolate list variable with indices" |
| 65 | (let ((eshell-test-value '("zero" "one" "two" "three" "four"))) | 77 | (let ((eshell-test-value '("zero" "one" "two" "three" "four"))) |
| @@ -131,6 +143,26 @@ | |||
| 131 | (eshell-command-result-equal "echo $#eshell-test-value" 1) | 143 | (eshell-command-result-equal "echo $#eshell-test-value" 1) |
| 132 | (eshell-command-result-equal "echo $#eshell-test-value[foo]" 3))) | 144 | (eshell-command-result-equal "echo $#eshell-test-value[foo]" 3))) |
| 133 | 145 | ||
| 146 | (ert-deftest esh-var-test/interp-var-splice () | ||
| 147 | "Splice-interpolate list variable" | ||
| 148 | (let ((eshell-test-value '(1 2 3))) | ||
| 149 | (eshell-command-result-equal "echo a $@eshell-test-value z" | ||
| 150 | '("a" 1 2 3 "z")))) | ||
| 151 | |||
| 152 | (ert-deftest esh-var-test/interp-var-splice-concat () | ||
| 153 | "Splice-interpolate and concat list variable" | ||
| 154 | (let ((eshell-test-value '(1 2 3))) | ||
| 155 | (eshell-command-result-equal "echo it is a$@'eshell-test-value'z" | ||
| 156 | '("it" "is" "a1" 2 "3z")) | ||
| 157 | ;; This is a tricky case. We're concatenating a spliced list and | ||
| 158 | ;; a non-spliced list. The general rule is that splicing should | ||
| 159 | ;; work as though the user typed "$X[0] $X[1] ... $X[N]". That | ||
| 160 | ;; means that the last value of our splice should get concatenated | ||
| 161 | ;; into the first value of the non-spliced list. | ||
| 162 | (eshell-command-result-equal | ||
| 163 | "echo it is $@'eshell-test-value'$eshell-test-value" | ||
| 164 | '("it" "is" 1 2 (31 2 3))))) | ||
| 165 | |||
| 134 | (ert-deftest esh-var-test/interp-lisp () | 166 | (ert-deftest esh-var-test/interp-lisp () |
| 135 | "Interpolate Lisp form evaluation" | 167 | "Interpolate Lisp form evaluation" |
| 136 | (eshell-command-result-equal "+ $(+ 1 2) 3" 6)) | 168 | (eshell-command-result-equal "+ $(+ 1 2) 3" 6)) |
| @@ -197,6 +229,9 @@ | |||
| 197 | (eshell-match-command-output "echo ${echo hi}-${*echo there}" | 229 | (eshell-match-command-output "echo ${echo hi}-${*echo there}" |
| 198 | "hi-there\n"))) | 230 | "hi-there\n"))) |
| 199 | 231 | ||
| 232 | |||
| 233 | ;; Quoted variable interpolation | ||
| 234 | |||
| 200 | (ert-deftest esh-var-test/quoted-interp-var () | 235 | (ert-deftest esh-var-test/quoted-interp-var () |
| 201 | "Interpolate variable inside double-quotes" | 236 | "Interpolate variable inside double-quotes" |
| 202 | (eshell-command-result-equal "echo \"$user-login-name\"" | 237 | (eshell-command-result-equal "echo \"$user-login-name\"" |
| @@ -209,6 +244,18 @@ | |||
| 209 | (eshell-command-result-equal "echo \"hi, $\\\"user-login-name\\\"\"" | 244 | (eshell-command-result-equal "echo \"hi, $\\\"user-login-name\\\"\"" |
| 210 | (concat "hi, " user-login-name))) | 245 | (concat "hi, " user-login-name))) |
| 211 | 246 | ||
| 247 | (ert-deftest esh-var-test/quoted-interp-list-var () | ||
| 248 | "Interpolate list variable inside double-quotes" | ||
| 249 | (let ((eshell-test-value '(1 2 3))) | ||
| 250 | (eshell-command-result-equal "echo \"$eshell-test-value\"" | ||
| 251 | "(1 2 3)"))) | ||
| 252 | |||
| 253 | (ert-deftest esh-var-test/quoted-interp-list-var-concat () | ||
| 254 | "Interpolate and concat list variable inside double-quotes" | ||
| 255 | (let ((eshell-test-value '(1 2 3))) | ||
| 256 | (eshell-command-result-equal "echo \"a$'eshell-test-value'z\"" | ||
| 257 | "a(1 2 3)z"))) | ||
| 258 | |||
| 212 | (ert-deftest esh-var-test/quoted-interp-var-indices () | 259 | (ert-deftest esh-var-test/quoted-interp-var-indices () |
| 213 | "Interpolate string variable with indices inside double-quotes" | 260 | "Interpolate string variable with indices inside double-quotes" |
| 214 | (let ((eshell-test-value '("zero" "one" "two" "three" "four"))) | 261 | (let ((eshell-test-value '("zero" "one" "two" "three" "four"))) |
| @@ -291,6 +338,18 @@ inside double-quotes" | |||
| 291 | (eshell-command-result-equal "echo \"$#eshell-test-value[foo]\"" | 338 | (eshell-command-result-equal "echo \"$#eshell-test-value[foo]\"" |
| 292 | "3"))) | 339 | "3"))) |
| 293 | 340 | ||
| 341 | (ert-deftest esh-var-test/quoted-interp-var-splice () | ||
| 342 | "Splice-interpolate list variable inside double-quotes" | ||
| 343 | (let ((eshell-test-value '(1 2 3))) | ||
| 344 | (eshell-command-result-equal "echo a \"$@eshell-test-value\" z" | ||
| 345 | '("a" "1 2 3" "z")))) | ||
| 346 | |||
| 347 | (ert-deftest esh-var-test/quoted-interp-var-splice-concat () | ||
| 348 | "Splice-interpolate and concat list variable inside double-quotes" | ||
| 349 | (let ((eshell-test-value '(1 2 3))) | ||
| 350 | (eshell-command-result-equal "echo \"a$@'eshell-test-value'z\"" | ||
| 351 | "a1 2 3z"))) | ||
| 352 | |||
| 294 | (ert-deftest esh-var-test/quoted-interp-lisp () | 353 | (ert-deftest esh-var-test/quoted-interp-lisp () |
| 295 | "Interpolate Lisp form evaluation inside double-quotes" | 354 | "Interpolate Lisp form evaluation inside double-quotes" |
| 296 | (eshell-command-result-equal "echo \"hi $(concat \\\"the\\\" \\\"re\\\")\"" | 355 | (eshell-command-result-equal "echo \"hi $(concat \\\"the\\\" \\\"re\\\")\"" |
| @@ -325,6 +384,21 @@ inside double-quotes" | |||
| 325 | "foo\nbar baz")) | 384 | "foo\nbar baz")) |
| 326 | 385 | ||
| 327 | 386 | ||
| 387 | ;; Interpolating commands | ||
| 388 | |||
| 389 | (ert-deftest esh-var-test/command-interp () | ||
| 390 | "Interpolate a variable as a command name" | ||
| 391 | (let ((eshell-test-value "printnl")) | ||
| 392 | (eshell-command-result-equal "$eshell-test-value hello there" | ||
| 393 | "hello\nthere\n"))) | ||
| 394 | |||
| 395 | (ert-deftest esh-var-test/command-interp-splice () | ||
| 396 | "Interpolate a splice variable as a command name with arguments" | ||
| 397 | (let ((eshell-test-value '("printnl" "hello" "there"))) | ||
| 398 | (eshell-command-result-equal "$@eshell-test-value" | ||
| 399 | "hello\nthere\n"))) | ||
| 400 | |||
| 401 | |||
| 328 | ;; Interpolated variable conversion | 402 | ;; Interpolated variable conversion |
| 329 | 403 | ||
| 330 | (ert-deftest esh-var-test/interp-convert-var-number () | 404 | (ert-deftest esh-var-test/interp-convert-var-number () |