Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syntax: allow printing redirections before all arguments #942

Closed
mikez opened this issue Nov 13, 2022 · 4 comments · Fixed by #1027
Closed

syntax: allow printing redirections before all arguments #942

mikez opened this issue Nov 13, 2022 · 4 comments · Fixed by #1027

Comments

@mikez
Copy link

mikez commented Nov 13, 2022

Sometimes, to improve readability, I put logfile redirections at the beginning of the line:

>>$LOGFILE echo "[label]" 1 2 3
>>$LOGFILE some_command 4 5 6

This is currently, as of shfmt v3.5.1, incorrectly reformatted as follows:

echo >> $LOGFILE "[label]" 1 2 3
some_command >> $LOGFILE 4 5 6

Research

Putting redirects at various places in-between arguments and at the end seems to have been supported from the very beginning of sh in 1971. Putting redirects at the beginning was not supported in UNIX V1, but emerged sometime later. I haven't found out when.

UNIX V1 manual (1971-03-11) (and code):

Each command is a sequence of non-blank command arguments separated by blanks. [...] Two characters [i.e., "<" or ">"] cause the immediately following string to be interpreted as a special argument to the shell itself, not passed to the command. An argument of the form <arg causes the file arg to be used as the standard input file of the given command; an argument of the form “>arg” causes file “arg” to be used as the standard output file for the given command.

Bash documentation, section 3.6 (2022-11-13):

The following redirection operators may precede or appear anywhere within a simple command or may follow a command. Redirections are processed in the order they appear, from left to right. [...]

Bash documentation, section 3.7.1 (2022-11-13):

When a simple command is executed, the shell performs the following expansions, assignments, and redirections, from left to right, in the following order: 1. The words that the parser has marked as variable assignments (those preceding the command name) and redirections are saved for later processing. [...]

@mvdan
Copy link
Owner

mvdan commented Nov 18, 2022

The formatter wants to enforce a somewhat canonical and consistent format - it could be far more conservative and only fix up whitespace like indentation, but then it would be far less useful in practice :)

I realise that redirections can appear anywhere, but we currently only allow them after the first argument, or after all arguments. See #389 for a previous discussion.

I guess we could also allow them to appear before all arguments as a third option. That isn't a big change, and you're not the first person to suggest it (cc @dcsobral @ale5000-git), so perhaps I should reconsider.

One objective reason in favor of supporting it is that, in your example, keeping the redirections in the first place does help with alignment. In some other cases, the alignment could be better if the redirection was after the first argument - the user can choose in each instance. I don't think we should get into the business of writing a heuristic for it.

@mvdan mvdan changed the title Bug report: format redirections not at the end syntax: allow printing redirections before all arguments Nov 18, 2022
@mikez
Copy link
Author

mikez commented Nov 18, 2022

@mvdan Thank you for the reference to #389 and pointing out that >>a echo b is equivalent to echo >> b a. I had previously incorrectly understood that Bash only permitted the echo >>b a syntax, i.e., without space. Sorry for this.

In some other cases, the alignment could be better if the redirection was after the first argument - the user can choose in each instance. I don't think we should get into the business of writing a heuristic for it.

👍

Out of curiosity, do you have an example of these some other cases?
For my use case, putting the redirection first, helps readability:

>>$LOGFILE echo "[label]" 1 2 3
…
>>$LOGFILE some_command 4 5 6
…
>>$LOGFILE do_this 7 8 9

is more easy to skim than this

echo >>$LOGFILE "[label]" 1 2 3
…
some_command >>$LOGFILE 4 5 6
…
do_this >>$LOGFILE 7 8 9

Most importantly, thank you for your continued work on shfmt. I use it a lot. 🌻

@mvdan
Copy link
Owner

mvdan commented Nov 21, 2022

If your redirections are all the same length, but the commands aren't, then placing them first helps with alignment:

>foo cmd1 args...
>foo cmd234 args...

In the opposite scenario, it helps to place the first argument at the beginning:

cmd >foo1 args...
cmd >foo234 args...

@mikez
Copy link
Author

mikez commented Nov 21, 2022

@mvdan Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants