-
Notifications
You must be signed in to change notification settings - Fork 459
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
Respect .editorconfig
settings for formatting shell via shfmt
#2031
Respect .editorconfig
settings for formatting shell via shfmt
#2031
Conversation
@@ -23,7 +23,7 @@ | |||
import com.diffplug.spotless.shell.ShfmtStep; | |||
|
|||
public class ShellExtension extends FormatExtension { | |||
private static final String SHELL_FILE_EXTENSION = "*.sh"; | |||
private static final String SHELL_FILE_EXTENSION = "**/*.sh"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's very likely that project's aren't storing their shell scripts as siblings to the build file so this updates the search to be more inclusive by default.
.editorconfig
support for shfmt
shell formatting.editorconfig
settings for formatting shell via shfmt
String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { | ||
if (args == null) { | ||
args = List.of(exe.confirmVersionAndGetAbsolutePath(), "-i", "2", "-ci"); | ||
args = List.of(exe.confirmVersionAndGetAbsolutePath(), file.getAbsolutePath()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the second run, still using the first file path?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm.. Looks like this formatter doesn't work when there is more than one file to format. I'll have to make sure I add a test case for multiple files that need formatted and verify the output. The second file ends up containing the formatted contents of the first file that was formatted. Do you have any suggestions here? I assumed that the file
variable was going to contain the current file that needs formatted, but that doesn't seem to actually be the case.
I rescind my ask. I was able to format it properly via standard input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Goooler this should all be fixed now. The solution turned out to be simpler than I thought in the end. Please re-review this PR at your earliest convenience 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my observation, --filename
is not a necessary param for shfmt, we can remove it. Am I missing anything here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the documentation your assumption/observation would be correct. However, without the --filename
parameter and the path, the .editorconfig
settings aren't respected.
I did some digging to try to understand this better myself. This commit for shfmt seems to explain why the filename
flag is necessary when reading from stdin: mvdan/sh@fa7035e
And this was the original issue related to the change: mvdan/sh#577
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we must input the file path here, it might be something like Goooler@ae75240?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but now might be the best time to do it
That would be great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we must input the file path here, it might be something like Goooler@ae75240?
Would you be fine with something like the following instead? I don't think args
needs to be an instance variable as of right now. If args need provided to the State
constructor eventually, then someone can refactor it for their needs. Unless args
is somehow used implicitly for something that I'm unaware of.
String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException {
final List<String> args = List.of(exe.confirmVersionAndGetAbsolutePath(), "--filename", file.getPath());
return runner.exec(input.getBytes(StandardCharsets.UTF_8), args).assertExitZero(StandardCharsets.UTF_8);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only concern is if it's necessary to check the executable file for every formatting. Otherwise, I'm okay with your snippet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took some time to see what you're talking about here and how this all works. I will absolutely go with your original suggestion. It makes a lot more sense. I didn't realize that args
would be reused once it was set the first time. This explains why I kept seeing the same filename in my testing too.
"}", | ||
"repositories { mavenCentral() }", | ||
"spotless {", | ||
" shell {", | ||
" shfmt()", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can add an option to override .editorconfig
path like BaseKotlinExtension.KtlintConfig#setEditorConfigPath
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I can tell, when configuring ktlint for formatting, you actually provide the .editorconfig path to ktlint and that is an input supported by ktlint. As far as I can tell, there is no way to provide an .editorconfig
path to shfmt
🙁
With that said, I did request that an input flag be added for situations like this: mvdan/sh#1055
c2ae79b
to
1b3335d
Compare
Co-authored-by: Zongle Wang <[email protected]>
|
||
[homepage](https://github.com/mvdan/sh). [changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md). | ||
|
||
When formatting shell scripts via `shfmt`, configure `shfmt` settings via `.editorconfig`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can note a bit more here, that the .editorconfig
file only be supported at the same level as shell files, you can't override it's path due to mvdan/sh#1055.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is an incorrect assumption, surprisingly. If I were to have the following project structure, all shell files will respect the .editorconfig
settings. I can write tests to validate and solidify this claim, but this is the behavior I've seen in a standalone test project. shfmt
tries to be smart when looking for an .editorconfig
. I'm not sure I know what the process for finding the .editorconfig
is, but the developer's https://github.com/mvdan/editorconfig library is used instead of the default Go library and I think that plays a factor in finding the editorconfig.
repository-name/
├── client/
│ └── scripts/
│ ├── foobar.sh
│ └── barfoo.sh
├── scripts/
│ ├── foo.sh
│ └── bar.sh
├── .editorconfig
├── init.sh
└── build.gradle.kts
void shfmtMultipleFilesWithEditorconfig() throws IOException { | ||
String fileDir = "shell/shfmt/multifile/with-config/"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only difference between shfmtMultipleFilesWithoutEditorconfig
with shfmtMultipleFilesWithEditorconfig
is the last folder in the path, can we merge them to using @ParameterizedTest
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can only keep these 2 cases, and remove shfmtWithoutEditorconfig
and shfmtWithEditorconfig
, it should be enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah! I can merge those tests together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up creating a more complex test directory to validate multiple shell scripts. In attempting to merge some of the tests, I realized that it would take some checking based on parameterized input to determine if there is more than 1 file to check and thought that looked a little ugly and maybe hard to understand.
I believe testing a complex directory structure should cover the necessary test cases, but please let me know if you really prefer having single file tests for some reason.
Co-authored-by: Zongle Wang <[email protected]>
.github/workflows/ci.yml
Outdated
@@ -23,28 +23,32 @@ jobs: | |||
uses: actions/checkout@v4 | |||
with: | |||
fetch-depth: 0 | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert these format changes, including the array style changes.
Amazing teamwork, great PR! |
Closes #2014. Note that this removes the previous "default" formatting settings for shfmt that was provided by spotless in the previous versions.