Teach string repeat to handle multiple arguments

Each argument in string repeat is handled independently, except that the
--no-newline option applies only to the last newline.

Fixes #5988
This commit is contained in:
ridiculousfish 2021-01-11 16:30:33 -08:00
parent 290d1f2cd6
commit 7a0bddfcfa
3 changed files with 30 additions and 1 deletions

View file

@ -103,6 +103,7 @@ Scripting improvements
- ``math`` learned bitwise functions ``bitand``, ``bitor`` and ``bitxor``, used like ``math "bitand(0xFE, 5)"`` (:issue:`7281`). - ``math`` learned bitwise functions ``bitand``, ``bitor`` and ``bitxor``, used like ``math "bitand(0xFE, 5)"`` (:issue:`7281`).
- ``math`` learned tau for those wishing to cut down on typing "2 * pi". - ``math`` learned tau for those wishing to cut down on typing "2 * pi".
- ``string`` subcommands now quit early when used with ``--quiet`` (:issue:`7495`). - ``string`` subcommands now quit early when used with ``--quiet`` (:issue:`7495`).
- ``string repeat`` now handles multiple arguments, repeating each one (:issue:`5988`).
- Failed redirections will now set ``$status`` (:issue:`7540`). - Failed redirections will now set ``$status`` (:issue:`7540`).
- More consistent $status after errors, including invalid expansions like ``$foo[``. - More consistent $status after errors, including invalid expansions like ``$foo[``.
- ``read`` can now read interactively from other files, so e.g. forcing it to read from the terminal via ``read </dev/tty`` works (:issue:`7358`). - ``read`` can now read interactively from other files, so e.g. forcing it to read from the terminal via ``read </dev/tty`` works (:issue:`7358`).

View file

@ -1559,9 +1559,14 @@ static int string_repeat(parser_t &parser, io_streams_t &streams, int argc, wcha
if (retval != STATUS_CMD_OK) return retval; if (retval != STATUS_CMD_OK) return retval;
bool all_empty = true; bool all_empty = true;
bool first = true;
arg_iterator_t aiter(argv, optind, streams); arg_iterator_t aiter(argv, optind, streams);
if (const wcstring *word = aiter.nextstr()) { while (const wcstring *word = aiter.nextstr()) {
if (!first && !opts.quiet) {
streams.out.append(L'\n');
}
first = false;
const bool limit_repeat = const bool limit_repeat =
(opts.max > 0 && word->length() * opts.count > static_cast<size_t>(opts.max)) || (opts.max > 0 && word->length() * opts.count > static_cast<size_t>(opts.max)) ||
!opts.count; !opts.count;
@ -1574,6 +1579,8 @@ static int string_repeat(parser_t &parser, io_streams_t &streams, int argc, wcha
return STATUS_CMD_OK; return STATUS_CMD_OK;
} }
} }
// Append if not quiet.
if (!opts.quiet) { if (!opts.quiet) {
streams.out.append(repeated); streams.out.append(repeated);
} }

View file

@ -411,6 +411,27 @@ string repeat -n3 -m20 foo
string repeat -m4 foo string repeat -m4 foo
# CHECK: foof # CHECK: foof
string repeat -n 5 a b c
# CHECK: aaaaa
# CHECK: bbbbb
# CHECK: ccccc
string repeat -n 5 --max 4 123 456 789
# CHECK: 1231
# CHECK: 4564
# CHECK: 7897
string repeat -n 5 --max 4 123 '' 789
# CHECK: 1231
# CHECK:
# CHECK: 7897
# Historical string repeat behavior is no newline if no output.
echo -n before
string repeat -n 5 ''
echo after
# CHECK: beforeafter
string repeat -n-1 foo; and echo "exit 0" string repeat -n-1 foo; and echo "exit 0"
# CHECKERR: string repeat: Invalid count value '-1' # CHECKERR: string repeat: Invalid count value '-1'