sh icon indicating copy to clipboard operation
sh copied to clipboard

syntax: support {varname} redirects

Open jmcantrell opened this issue 4 years ago • 5 comments

The shfmt tool altering the following valid code, making it invalid:

coproc foo {
    echo test
}

exec {foo[1]}>&-  # converts to: exec {foo[1]} >&-

jmcantrell avatar Aug 13 '21 06:08 jmcantrell

I'm not sure I follow what the exec line is doing. What's the syntax there, and where is it documented?

mvdan avatar Aug 16 '21 12:08 mvdan

It's closing the file descriptor stored at index 1 of the foo array. The previous coproc command puts file descriptors into the array.

The syntax for both closing a file descriptor and providing the file descriptor using a variable are described in the second paragraph here: https://www.gnu.org/software/bash/manual/bash.html#Redirections

And since there can't be any space between the file descriptor and the redirection, it produces the error.

jmcantrell avatar Aug 22 '21 10:08 jmcantrell

Ah I see, thank you. I was not aware you could close file descriptors stored inside a variable or array. So the parser indeed thinks that you wrote exec {foo[1]} >&-. This will require a bit of an internal refactor to add support for the syntax.

For my own convenience, here's the relevant bit of the docs:

Each redirection that may be preceded by a file descriptor number may instead be preceded by a word of the form {varname}. In this case, for each redirection operator except >&- and <&-, the shell will allocate a file descriptor greater than 10 and assign it to {varname}. If >&- or <&- is preceded by {varname}, the value of varname defines the file descriptor to close. If {varname} is supplied, the redirection persists beyond the scope of the command, allowing the shell programmer to manage the file descriptor’s lifetime manually.

mvdan avatar Aug 31 '21 12:08 mvdan

I just got hit by this one as well 😄 Is there a way to disable this behavior for a file or a line? currently it blocks any usage of shfmt due to breaking flock usage like this

exec {lock_fd}>"$file"
# (...)
exec {lock_fd}>&-

being turned into

exec {lock_fd}>"$file"
# (...)
exec {lock_fd} >&-  # notice the space here

Perhaps some other workaround?

jippi avatar Feb 10 '24 17:02 jippi