mvdan / sh

A shell parser, formatter, and interpreter with bash support; includes shfmt
https://pkg.go.dev/mvdan.cc/sh/v3
BSD 3-Clause "New" or "Revised" License
7.16k stars 338 forks source link

shfmt should repair tab indented here docs. #758

Closed docwhat closed 2 years ago

docwhat commented 2 years ago

From the bash man page:

If the redirection operator is <<-, then all leading tab characters are stripped from input lines and the line containing delimiter. This allows here-documents within shell scripts to be indented in a natural fashion.

Given this:

# spaces not tab.
fun() {
    cat <<-DOC
        some important text
    DOC
}

... I would like shfmt to repair this... because a lot of editors have a hard time with this if you're using spaces for indentation overall.

mvdan commented 2 years ago

Can you clarify what you mean by "repair"? Perhaps give me an input file and how you run shfmt on it, and what you expect the output to be.

docwhat commented 2 years ago

Given

# spaces not tab.
fun() {
    cat <<-DOC
        some important text
    DOC
}

for i in {1..10}; do
    echo "run $i"
    fun
done

When you run:

shfmt -i 4 -s script-with-spaces.bash   

I would expect:

# spaces not tab.
fun() {
    cat <<-DOC
      some important text
    DOC
}

for i in {1..10}; do
    echo "run $i"
    fun
done

But I get:

/tmp/foo.bash:3:9: unclosed here-document 'DOC'

Basically, shfmt would detect that DOC isn't closed and try to repair it by replacing the first n spaces with a tab. n would be calculated by looking at the stop line.

mvdan commented 2 years ago

Basically, shfmt would detect that DOC isn't closed and try to repair it by replacing the first n spaces with a tab. n would be calculated by looking at the stop line.

Hmm. shfmt is just a formatter, though - if its input is invalid Bash, it generally shouldn't try to fix it automatically. In other words, the parser should error if the input is invalid. We don't have a middle ground where we may return warnings or fix the program for the user. See https://github.com/mvdan/sh/issues/765 as another example, for instance.

I think your suggestion falls under the kind of tool to spot bugs or auto-fix common shell mistakes. You could certainly build a tool like that on top of our Go syntax package. For instance, if that tool runs the parser and encounters /tmp/foo.bash:3:9: unclosed here-document 'DOC', it could look at the following lines to see if one could be the closing heredoc line by replacing leading spaces with tabs.

mvdan commented 2 years ago

I'm going to close this as per the last comment. If someone wants to coordinate writing such a "fix common mistakes" tool, please feel free to open an umbrella issue or discussion on this repository, like https://github.com/mvdan/sh/issues/730. Thanks!