diff --git a/cmd/shfmt/main.go b/cmd/shfmt/main.go index aa4afbdb9..c13424f42 100644 --- a/cmd/shfmt/main.go +++ b/cmd/shfmt/main.go @@ -320,7 +320,11 @@ func walkPath(path string, entry fs.DirEntry) error { return filepath.SkipDir } if useEditorConfig { - props, err := ecQuery.Find(path) + // We don't know the language variant at this point yet, as we are walking directories + // and we first want to tell if we should skip a path entirely. + // TODO: Should the call to Find with the language name check "ignore" too, then? + // Otherwise a [[bash]] section with ignore=true is effectively never used. + props, err := ecQuery.Find(path, []string{"shell"}) if err != nil { return err } @@ -420,9 +424,23 @@ func formatPath(path string, checkShebang bool) error { return formatBytes(readBuf.Bytes(), path, fileLang) } +func editorConfigLangs(l syntax.LangVariant) []string { + // All known shells match [[shell]]. + // As a special case, bash and the bash-like bats also match [[bash]] + // We can later consider others like [[mksh]] or [[posix-shell]], + // just consider what list of languages the EditorConfig spec might eventually use. + switch l { + case syntax.LangBash, syntax.LangBats: + return []string{"shell", "bash"} + case syntax.LangPOSIX, syntax.LangMirBSDKorn, syntax.LangAuto: + return []string{"shell"} + } + return nil +} + func formatBytes(src []byte, path string, fileLang syntax.LangVariant) error { if useEditorConfig { - props, err := ecQuery.Find(path) + props, err := ecQuery.Find(path, editorConfigLangs(fileLang)) if err != nil { return err } diff --git a/cmd/shfmt/shfmt.1.scd b/cmd/shfmt/shfmt.1.scd index ecd2ff11f..58456b2d9 100644 --- a/cmd/shfmt/shfmt.1.scd +++ b/cmd/shfmt/shfmt.1.scd @@ -139,6 +139,10 @@ function_next_line = true ignore = true ``` +EditorConfig sections may also use `[[shell]]` or `[[bash]]` to match any shell or bash scripts, +which is particularly useful when scripts use a shebang but no extension. +Note that this feature is outside of the EditorConfig spec and may be changed in the future. + shfmt can also replace *bash -n* to check shell scripts for syntax errors. It is more exhaustive, as it parses all syntax statically and requires valid UTF-8: diff --git a/cmd/shfmt/testdata/script/editorconfig.txtar b/cmd/shfmt/testdata/script/editorconfig.txtar index 5fbbf299f..f98d1a912 100644 --- a/cmd/shfmt/testdata/script/editorconfig.txtar +++ b/cmd/shfmt/testdata/script/editorconfig.txtar @@ -53,6 +53,11 @@ stdout 'regular\.sh' ! stdout 'ignored\.sh' ! stderr . +# Check EditorConfig [[language]] sections, used primarily for extension-less strings with shebangs. +exec shfmt -d shebang +! stdout . +! stderr . + -- .editorconfig -- root = true @@ -156,3 +161,29 @@ echo foo echo foo -- ignored/3_regular/regular.sh -- echo foo +-- shebang/.editorconfig -- +root = true + +[*] +indent_style = space +indent_size = 1 + +[[shell]] +indent_size = 2 + +[[bash]] +indent_size = 4 + +-- shebang/binsh -- +#!/bin/sh + +{ + indented +} +-- shebang/binbash -- +#!/bin/bash + +{ + indented +} +array=(elem) diff --git a/go.mod b/go.mod index eb9b26a98..ebb41b4d9 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( golang.org/x/sync v0.5.0 golang.org/x/sys v0.15.0 golang.org/x/term v0.15.0 - mvdan.cc/editorconfig v0.2.0 + mvdan.cc/editorconfig v0.2.1-0.20231228180347-1925077f8eb2 ) require ( diff --git a/go.sum b/go.sum index 2b98eac5c..3caeab6c4 100644 --- a/go.sum +++ b/go.sum @@ -25,5 +25,7 @@ golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -mvdan.cc/editorconfig v0.2.0 h1:XL+7ys6ls/RKrkUNFQvEwIvNHh+JKx8Mj1pUV5wQxQE= -mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0= +mvdan.cc/editorconfig v0.2.1-0.20231227223507-ad7477e883b4 h1:SUMDYCoRUx5kuz3pkNWvsvpO0b4gN4pxXll47TsWHe0= +mvdan.cc/editorconfig v0.2.1-0.20231227223507-ad7477e883b4/go.mod h1:r8RiQJRtzrPrZdcdEs5VCMqvRxAzYDUu9a4S9z7fKh8= +mvdan.cc/editorconfig v0.2.1-0.20231228180347-1925077f8eb2 h1:8nmqQGVnHUtHuT+yvuA49lQK0y5il5IOr2PtCBkDI2M= +mvdan.cc/editorconfig v0.2.1-0.20231228180347-1925077f8eb2/go.mod h1:r8RiQJRtzrPrZdcdEs5VCMqvRxAzYDUu9a4S9z7fKh8=