Re: question about sound
On Fri, 19 Aug 2022 at 14:13, David Wright <deblis@lionunicorn.co.uk> wrote:
> On Thu 18 Aug 2022 at 06:58:20 (-0400), Greg Wooledge wrote:
> > On Wed, Aug 17, 2022 at 10:58:17PM -0500, David Wright wrote:
> > > $ type soxy
> > > soxy is a function
> > > soxy ()
> > > {
> > > [ -z "$1" ] && printf '%s\n' "Usage: ${FUNCNAME[0]} path-to/sound-file-of-any-type [trim 20 2]
> > > runs sox to play the file with any arguments given.
> > > The example above reminds you to put the full argument." 1>&2 && return 1;
> > > local From="$1";
> > > shift;
> > > sox -q "$From" -t alsa default "$@"
> > > }
> >
> > Pedantic note: your error checking can fail. If the printf fails for
> > some reason (e.g. because stderr has been closed, or is redirected to
> > a file on a file system that's full), the return won't execute.
>
> True—I guess I was willing to carry the risk. Thanks for noting that.
>
> > It's best just to use "if" in the normal way:
> >
> > if [ -z "$1" ]; then
> > printf ...
> > return 1
> > fi
> >
> > That way, the return will still be executed even if the printf fails.
> >
> > If you *insist* on using && because you think it's tres chic or something,
> > then you need to use a command group:
> >
> > [ -z "$1" ] && {
> > printf ...
> > return 1
> > }
> >
> > But this is not the recommended practice.
>
> Not so much très chic as bijou⁰. I can edit, eg
> [ -z "$Thepagecount" ] && printf '%s\n' "$1 has no pages!" ¹>&2 && return 1
> to
> [ -z "$Thepagecount" ] && { printf '%s\n' "$1 has no pages!" ¹>&2 ; return 1 ; }
> very easily. (I think I have about 350 such constructions in ~/.bash*.)
>
> The attraction of a one-liner is partly because of screens
> being around four times wider than high (characterwise).
> Wouldn't it be nice if bash had Perl's die ….
Hi David
Some further bash script thoughts ...
Considating hundreds of identical "printf '%s\n' 1>&2" constructs
into one function seems like it would remove a lot of visual noise,
and streamline reading and writing that code. My style would be:
msg_stderr() {
printf '%s\n' "$@" 1>&2
}
soxy() {
if [[ -z "$1" ]] ; then
msg_stderr "Usage: ${FUNCNAME[0]}
path-to/sound-file-of-any-type [trim 20 2]
runs sox to play the file with any arguments given.
The example above reminds you to put the full argument."
return 1
fi
}
I find that style easier to read and reason about, but it would involve
more editing of your existing code.
Aside: I see that you are using ${FUNCNAME[0]}, so bash features
are acceptable. Using an array to pass the message lines to the
same function would preserve the code indentation, which
further improves readability for me.
soxy() {
if [[ -z "$1" ]] ; then
local m=(
"Usage: ${FUNCNAME[0]} path-to/sound-file-of-any-type
[trim 20 2]"
"runs sox to play the file with any arguments given."
"The example above reminds you to put the full argument."
)
msg_stderr "${m[@]}"
return 1
fi
}
If you want to stay close to the oneliner style that you already
have, it could be done like this:
die() {
printf '%s\n' "$@" 1>&2
return 0
}
soxy() {
[[ -z "$1" ]] && die "message" && return 1
}
This avoids the issue of unexpected errors in printf, makes all
return values explicit, and avoids mixing && and || operators.
And hopefully not much trouble for you to edit, either :)
Reply to: