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

Add --find0 and --list0 flags #1097

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 52 additions & 16 deletions cmd/shfmt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,29 @@ import (
"mvdan.cc/sh/v3/syntax/typedjson"
)

type boolString string

func (s *boolString) Set(val string) error {
*s = boolString(val)
return nil
}
func (s *boolString) Get() any { return string(*s) }
func (s *boolString) String() string { return string(*s) }
func (*boolString) IsBoolFlag() bool { return true }

type multiFlag[T any] struct {
short, long string
val T
}

var (
versionFlag = &multiFlag[bool]{"", "version", false}
list = &multiFlag[bool]{"l", "list", false}
list = &multiFlag[boolString]{"l", "list", "false"}

write = &multiFlag[bool]{"w", "write", false}
simplify = &multiFlag[bool]{"s", "simplify", false}
minify = &multiFlag[bool]{"mn", "minify", false}
find = &multiFlag[bool]{"f", "find", false}
find = &multiFlag[boolString]{"f", "find", "false"}
diff = &multiFlag[bool]{"d", "diff", false}
applyIgnore = &multiFlag[bool]{"", "apply-ignore", false}

Expand Down Expand Up @@ -89,6 +99,13 @@ func init() {
if name := f.long; name != "" {
flag.BoolVar(&f.val, name, f.val, "")
}
case *multiFlag[boolString]:
if name := f.short; name != "" {
flag.Var(&f.val, name, "")
}
if name := f.long; name != "" {
flag.Var(&f.val, name, "")
}
case *multiFlag[string]:
if name := f.short; name != "" {
flag.StringVar(&f.val, name, f.val, "")
Expand Down Expand Up @@ -130,13 +147,14 @@ directory, all shell scripts found under that directory will be used.

--version show version and exit

-l, --list list files whose formatting differs from shfmt's
-w, --write write result to file instead of stdout
-d, --diff error with a diff when the formatting differs
-s, --simplify simplify the code
-mn, --minify minify the code to reduce its size (implies -s)
--apply-ignore always apply EditorConfig ignore rules
--filename str provide a name for the standard input file
-l[=0], --list[=0] list files whose formatting differs from shfmt;
paths are separated by a newline or a null character if -l=0
-w, --write write result to file instead of stdout
-d, --diff error with a diff when the formatting differs
-s, --simplify simplify the code
-mn, --minify minify the code to reduce its size (implies -s)
--apply-ignore always apply EditorConfig ignore rules
--filename str provide a name for the standard input file

Parser options:

Expand All @@ -154,9 +172,10 @@ Printer options:

Utilities:

-f, --find recursively find all shell files and print the paths
--to-json print syntax tree to stdout as a typed JSON
--from-json read syntax tree from stdin as a typed JSON
-f[=0], --find[=0] recursively find all shell files and print the paths;
paths are separated by a newline or a null character if -f=0
--to-json print syntax tree to stdout as a typed JSON
--from-json read syntax tree from stdin as a typed JSON

Formatting options can also be read from EditorConfig files; see 'man shfmt'
for a detailed description of the tool's behavior.
Expand All @@ -181,6 +200,14 @@ For more information and to report bugs, see https://github.com/mvdan/sh.
fmt.Fprintf(os.Stderr, "-p and -ln=lang cannot coexist\n")
return 1
}
if list.val != "true" && list.val != "false" && list.val != "0" {
fmt.Fprintf(os.Stderr, "only -l and -l=0 allowed\n")
return 1
}
if find.val != "true" && find.val != "false" && find.val != "0" {
fmt.Fprintf(os.Stderr, "only -f and -f=0 allowed\n")
return 1
}
if minify.val {
simplify.val = true
}
Expand Down Expand Up @@ -248,7 +275,7 @@ For more information and to report bugs, see https://github.com/mvdan/sh.
}
status := 0
for _, path := range flag.Args() {
if info, err := os.Stat(path); err == nil && !info.IsDir() && !applyIgnore.val && !find.val {
if info, err := os.Stat(path); err == nil && !info.IsDir() && !applyIgnore.val && find.val == "false" {
// When given paths to files directly, always format them,
// no matter their extension or shebang.
//
Expand Down Expand Up @@ -424,9 +451,14 @@ func formatPath(path string, checkShebang bool) error {
}
readBuf.Write(copyBuf[:n])
}
if find.val {
switch find.val {
case "true":
fmt.Println(path)
return nil
case "0":
fmt.Print(path)
fmt.Print("\000")
return nil
}
if _, err := io.CopyBuffer(&readBuf, f, copyBuf); err != nil {
return err
Expand Down Expand Up @@ -492,8 +524,12 @@ func formatBytes(src []byte, path string, fileLang syntax.LangVariant) error {
printer.Print(&writeBuf, node)
res := writeBuf.Bytes()
if !bytes.Equal(src, res) {
if list.val {
switch list.val {
case "true":
fmt.Println(path)
case "0":
fmt.Print(path)
fmt.Print("\000")
}
if write.val {
info, err := os.Lstat(path)
Expand Down Expand Up @@ -537,7 +573,7 @@ func formatBytes(src []byte, path string, fileLang syntax.LangVariant) error {
return errChangedWithDiff
}
}
if !list.val && !write.val && !diff.val {
if list.val == "false" && !write.val && !diff.val {
os.Stdout.Write(res)
}
return nil
Expand Down
10 changes: 6 additions & 4 deletions cmd/shfmt/shfmt.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ predictable. Some aspects of the format can be configured via printer flags.
*--version*
Show version and exit.

*-l*, *--list*
List files whose formatting differs from shfmt's.
*-l[=0]*, *--list[=0]*
List files whose formatting differs from shfmt's;
paths are separated by a newline or a null character if -l=0

*-w*, *--write*
Write result to file instead of stdout.
Expand Down Expand Up @@ -101,8 +102,9 @@ predictable. Some aspects of the format can be configured via printer flags.

## Utility flags

*-f*, *--find*
Recursively find all shell files and print the paths.
*-f[=0]*, *--find[=0]*
Recursively find all shell files and print the paths;
paths are separated by a newline or a null character if -f=0.

*--to-json*
Print syntax tree to stdout as a typed JSON.
Expand Down