as part of an echo(1)/printf(1) analogue with a repeat option
How should we implement this style of tool?
Implementation ideas include:
- simplified version that takes no arguments
- complete GNU rewrite
- as part of an echo(1)/printf(1) analogue with a repeat option
echo -r, -r being "reverberate", would be delightful, but echo(1p) is implementation dependent enough as-is.
speak has historically been used for text-to-speech, so maybe not the best name under which to put an echo.
Plan 9 from User Space uses an echo (notably, with a -n option) and no yes(1) that I can see. I presume yes(1) would be accomplished easily in rc(1). I don't know it but here it is in sh(1):
while :;doprintf'%s\n' y;done
Argument echoing is a tough cookie because so many utilities do it. There are at least four designed for the task; echo(1) (POSIX, but they advise against its use for printf(1p) due to wildly varying implementations), printf(1p), prompt(1) (not POSIX and as far as I know rarely implemented, I'll explain further in the following paragraphs), and yes(1) (not in POSIX). To briefly describe all of them as background:
echo(1p), described in A Research UNIX Reader (pg. 7), prints its arguments to standard output, space-delimited and with a trailing newline.
prompt(1), described in the same paragraph, was replaced with echo(1)'s -n option, which is the heritage from which Plan 9's echo(1) derives. It prints without the newline:
printf(1p) is POSIX's answer to echo(1)'s unreliability in arguments. Standardized and based on a standardized language library feature (printf(3p) from the C standard library, particularly <stdio.h>), printf(1p) rarely differs in implementation, though its syntax isn't the prettiest:
It takes C format strings but with some fiddly bits attached to make it more convenient for shell scripting.
Finally, there's yes(1), which is echo(1) but forever:
$ yes
y
y
y
y
# infinity truncated
The only utility we really need to implement is printf(1p), after which we can write echo(1), prompt(1), and yes(1) in shell. I would prefer echo(1) and prompt(1) to be in C because they're small and easily debugged though any actual benefit from this would be little to none. yes(1) could be easily done in shell as well no matter what's implemented. Its usage in the GNU coreutils seems to be the same as echo(1) (as in, it spits out its arguments space-delimited newline-terminated) but with repetition.
If arguments weren't supported I imagine it would be awkward to bend yes(1) to one's uses:
$ yes hello world
Usage: yes
$ yes
y
y
y
^C
$ yes | sed 's:y:hello world:'
hello world
hello world
hello world
^C
So I would prefer to just support arguments. It wouldn't really take much more effort. It doesn't seem to have any specific options though GNU yes(1)'s man page is quite short and the GNU website documentation for yes(1) is shorter so I'm not sure.
`echo -r`, `-r` being "reverberate", would be delightful, but echo(1p) is implementation dependent enough as-is.
`speak` has historically been used for text-to-speech, so maybe not the best name under which to put an `echo`.
Plan 9 from User Space uses an [echo](https://github.com/9fans/plan9port/blob/master/src/cmd/echo.c) (notably, with a `-n` option) and no yes(1) that I can see. I presume yes(1) would be accomplished easily in rc(1). I don't know it but here it is in sh(1):
```sh
while :; do printf '%s\n' y; done
```
Argument echoing is a tough cookie because so many utilities do it. There are at least four designed for the task; echo(1) (POSIX, but they advise against its use for printf(1p) due to wildly varying implementations), printf(1p), prompt(1) (not POSIX and as far as I know rarely implemented, I'll explain further in the following paragraphs), and yes(1) (not in POSIX). To briefly describe all of them as background:
echo(1p), described in [A Research UNIX Reader](https://www.cs.dartmouth.edu/~doug/reader.pdf) (pg. 7), prints its arguments to standard output, space-delimited and with a trailing newline.
```sh
00000000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.|
0000000c
```
prompt(1), described in the same paragraph, was replaced with echo(1)'s `-n` option, which is the heritage from which Plan 9's echo(1) derives. It prints without the newline:
```sh
00000000 68 65 6c 6c 6f 20 77 6f 72 6c 64 |hello world|
0000000b
```
I really like prompt(1) and it being a separate utility to do this because echo(1) never reliably has any particular option. [I've implemented both in C and Rust already](https://git.sr.ht/~trinity/src/tree/main/item/echo) but [I had trouble with being able to output non-UTF-8 arguments in Rust](https://trinity.moe/blah/2023-10-31.html) so if we were to import one of these into the coreutils tree C would be the way to go for now.
[printf(1p)](https://www.man7.org/linux/man-pages/man1/printf.1p.html) is POSIX's answer to echo(1)'s unreliability in arguments. Standardized and based on a standardized language library feature (printf(3p) from the C standard library, particularly `<stdio.h>`), printf(1p) rarely differs in implementation, though its syntax isn't the prettiest:
```sh
$ printf %s 'hello world'
hello world$ printf '%s\n' 'hello world'
hello world
$
```
It takes C format strings but with some fiddly bits attached to make it more convenient for shell scripting.
Finally, there's yes(1), which is echo(1) but forever:
```sh
$ yes
y
y
y
y
# infinity truncated
```
The only utility we really need to implement is printf(1p), after which we can write echo(1), prompt(1), and yes(1) in shell. I would prefer echo(1) and prompt(1) to be in C because they're small and easily debugged though any actual benefit from this would be little to none. yes(1) could be easily done in shell as well no matter what's implemented. Its usage in the GNU coreutils seems to be the same as echo(1) (as in, it spits out its arguments space-delimited newline-terminated) but with repetition.
If arguments weren't supported I imagine it would be awkward to bend yes(1) to one's uses:
```sh
$ yes hello world
Usage: yes
$ yes
y
y
y
^C
$ yes | sed 's:y:hello world:'
hello world
hello world
hello world
^C
```
So I would prefer to just support arguments. It wouldn't really take much more effort. It doesn't seem to have any specific options though [GNU yes(1)'s man page](https://www.man7.org/linux/man-pages/man1/yes.1.html) is quite short and [the GNU website documentation for yes(1)](https://www.gnu.org/software/coreutils/manual/html_node/yes-invocation.html#yes-invocation) is shorter so I'm not sure.
On second thought I might be able to implement it in shell without terrible hacks. It seems to do the following:
Printing verbatim. This can be achieved with echo(1) or prompt(1).
Integer validation (printf '%d\n' "$var"). This could be an int(1) or something.
String formatting. We discussed a format(1) utility.
Perhaps printf(1) should be a shell script and echo(1), prompt(1), and some others should be binaries?
printf(1p) would be a nice addition.
On second thought I might be able to implement it in shell without terrible hacks. It seems to do the following:
- Printing verbatim. This can be achieved with echo(1) or prompt(1).
- Integer validation (`printf '%d\n' "$var"`). This could be an int(1) or something.
- String formatting. We discussed a format(1) utility.
Perhaps printf(1) should be a shell script and echo(1), prompt(1), and some others should be binaries?
i think we discussed an out(1) command in the past that does what echo does but without the uncertainty that comes with how it’s defined in POSIX. we definitely want a format(1) command but i want to veto most explicitly posixy tool names in the bonsai coreutils, we want as little semantic overlap with it as possible because we want to make clear that our shell is not POSIX and not POSIX-compliant.
A printf(1p) implementation as one of the test scripts in tests/posix/ would be ideal.
i think we discussed an out(1) command in the past that does what echo does but without the uncertainty that comes with how it’s defined in POSIX. we definitely want a format(1) command but i want to veto most explicitly posixy tool names in the bonsai coreutils, we want as little semantic overlap with it as possible because we want to make clear that our shell is *not* POSIX and *not* POSIX-compliant.
A printf(1p) implementation as one of the test scripts in `tests/posix/` would be ideal.
format(1) should be a string formatter akin to printf(1p) but without sucking. out(1) should be a wrapper around format(1) to be an echo(1) equivalent without the POSIX-specified -n option. And yes(1) should also be a wrapper around format(1).
Emma and I just discussed this:
format(1) should be a string formatter akin to printf(1p) but without sucking. out(1) should be a wrapper around format(1) to be an echo(1) equivalent without the POSIX-specified `-n` option. And yes(1) should also be a wrapper around format(1).
On second thought, I'm fully on board with dropping printf(1p) and using format(1). I wonder if the name could be better though - I still think "format" is vague.
I don't think out(1) is necessary. Even really fresh beginners to C are taught printf(3p) and that requires the newline to be specified.
I still believe yes(1) should be a shell script, wrapping format(1).
On second thought, I'm fully on board with dropping printf(1p) and using format(1). I wonder if the name could be better though - I still think "format" is vague.
I don't think out(1) is necessary. Even really fresh beginners to C are taught printf(3p) and that requires the newline to be specified.
I still believe yes(1) should be a shell script, wrapping format(1).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
How should we implement this style of tool?
Implementation ideas include:
echo -r,-rbeing "reverberate", would be delightful, but echo(1p) is implementation dependent enough as-is.speakhas historically been used for text-to-speech, so maybe not the best name under which to put anecho.Plan 9 from User Space uses an echo (notably, with a
-noption) and no yes(1) that I can see. I presume yes(1) would be accomplished easily in rc(1). I don't know it but here it is in sh(1):Argument echoing is a tough cookie because so many utilities do it. There are at least four designed for the task; echo(1) (POSIX, but they advise against its use for printf(1p) due to wildly varying implementations), printf(1p), prompt(1) (not POSIX and as far as I know rarely implemented, I'll explain further in the following paragraphs), and yes(1) (not in POSIX). To briefly describe all of them as background:
echo(1p), described in A Research UNIX Reader (pg. 7), prints its arguments to standard output, space-delimited and with a trailing newline.
prompt(1), described in the same paragraph, was replaced with echo(1)'s
-noption, which is the heritage from which Plan 9's echo(1) derives. It prints without the newline:I really like prompt(1) and it being a separate utility to do this because echo(1) never reliably has any particular option. I've implemented both in C and Rust already but I had trouble with being able to output non-UTF-8 arguments in Rust so if we were to import one of these into the coreutils tree C would be the way to go for now.
printf(1p) is POSIX's answer to echo(1)'s unreliability in arguments. Standardized and based on a standardized language library feature (printf(3p) from the C standard library, particularly
<stdio.h>), printf(1p) rarely differs in implementation, though its syntax isn't the prettiest:It takes C format strings but with some fiddly bits attached to make it more convenient for shell scripting.
Finally, there's yes(1), which is echo(1) but forever:
The only utility we really need to implement is printf(1p), after which we can write echo(1), prompt(1), and yes(1) in shell. I would prefer echo(1) and prompt(1) to be in C because they're small and easily debugged though any actual benefit from this would be little to none. yes(1) could be easily done in shell as well no matter what's implemented. Its usage in the GNU coreutils seems to be the same as echo(1) (as in, it spits out its arguments space-delimited newline-terminated) but with repetition.
If arguments weren't supported I imagine it would be awkward to bend yes(1) to one's uses:
So I would prefer to just support arguments. It wouldn't really take much more effort. It doesn't seem to have any specific options though GNU yes(1)'s man page is quite short and the GNU website documentation for yes(1) is shorter so I'm not sure.
Here's a fully featured yes(1) in C:
Untested.
printf(1p) will suck to implement so I'll wanna finish what I've already started before that.
i didn’t think we would be including printf? didn’t we discuss a different formatting tool?
printf(1p) would be a nice addition.
On second thought I might be able to implement it in shell without terrible hacks. It seems to do the following:
printf '%d\n' "$var"). This could be an int(1) or something.Perhaps printf(1) should be a shell script and echo(1), prompt(1), and some others should be binaries?
i think we discussed an out(1) command in the past that does what echo does but without the uncertainty that comes with how it’s defined in POSIX. we definitely want a format(1) command but i want to veto most explicitly posixy tool names in the bonsai coreutils, we want as little semantic overlap with it as possible because we want to make clear that our shell is not POSIX and not POSIX-compliant.
A printf(1p) implementation as one of the test scripts in
tests/posix/would be ideal.Emma and I just discussed this:
format(1) should be a string formatter akin to printf(1p) but without sucking. out(1) should be a wrapper around format(1) to be an echo(1) equivalent without the POSIX-specified
-noption. And yes(1) should also be a wrapper around format(1).GNU yes(1) analogueto GNU `yes(1)` analogueOn second thought, I'm fully on board with dropping printf(1p) and using format(1). I wonder if the name could be better though - I still think "format" is vague.
I don't think out(1) is necessary. Even really fresh beginners to C are taught printf(3p) and that requires the newline to be specified.
I still believe yes(1) should be a shell script, wrapping format(1).