diff --git a/cmd/root_test.go b/cmd/root_test.go index eb5068dc..074ab473 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -2502,19 +2502,19 @@ func TestConcurrentInvocation(t *testing.T) { as.NoError(eg.Wait()) } -func TestMaxBatchSize(t *testing.T) { +func TestNoPositionalArgSupport(t *testing.T) { tempDir := test.TempExamples(t) configPath := filepath.Join(tempDir, "/treefmt.toml") test.ChangeWorkDir(t, tempDir) - maxBatchSize := 1 + noPositionalArgSupport := true cfg := &config.Config{ FormatterConfigs: map[string]*config.Formatter{ "echo": { - Command: "test-fmt-only-one-file-at-a-time", - Includes: []string{"*"}, - MaxBatchSize: &maxBatchSize, + Command: "test-fmt-only-one-file-at-a-time", + Includes: []string{"*"}, + NoPositionalArgSupport: &noPositionalArgSupport, }, }, } diff --git a/config/config.go b/config/config.go index c6b1bc72..79a63103 100644 --- a/config/config.go +++ b/config/config.go @@ -62,8 +62,9 @@ type Formatter struct { Excludes []string `mapstructure:"excludes,omitempty" toml:"excludes,omitempty"` // Indicates the order of precedence when executing this Formatter in a sequence of Formatters. Priority int `mapstructure:"priority,omitempty" toml:"priority,omitempty"` - // The maximum number of files we should pass to this Formatter at once. - MaxBatchSize *int `mapstructure:"max-batch-size" toml:"max-batch-size"` + // Does this formatter violate [rule 1] of the formatter spec? + // [rule 1]: https://treefmt.com/latest/reference/formatter-spec/#1-files-passed-as-arguments + NoPositionalArgSupport *bool `mapstructure:"no-positional-arg-support" toml:"no-positional-arg-support"` } // SetFlags appends our flags to the provided flag set. diff --git a/docs/site/getting-started/configure.md b/docs/site/getting-started/configure.md index 81c16005..77f55adb 100644 --- a/docs/site/getting-started/configure.md +++ b/docs/site/getting-started/configure.md @@ -450,7 +450,6 @@ command = "deadnix" options = ["-e"] includes = ["*.nix"] priority = 2 -max-batch-size = 1024 ``` ### `command` @@ -473,13 +472,12 @@ An optional list of [glob patterns](#glob-patterns-format) used to exclude certa Influences the order of execution. Greater precedence is given to lower numbers, with the default being `0`. -### `max-batch-size` +### `no-positional-arg-support` -Invoke the formatter with no more than this many files at once. If there are -more files to format, treefmt will invoke the formatter multiple times in -smaller batches. Defaults to 1024. +If `true`, `treefmt` will invoke the formatter with no more than 1 file at a time. -This is useful for [non-compliant](https://treefmt.com/latest/reference/formatter-spec/#1-files-passed-as-arguments) formatters which can only format 1 file at a time. +Enable this if the formatter can only format 1 file at a time (a violation of +[rule 1 of the formatter spec](https://treefmt.com/latest/reference/formatter-spec/#1-files-passed-as-arguments)). ## Same file, multiple formatters? diff --git a/format/formatter.go b/format/formatter.go index 35cada7a..870fb4b8 100644 --- a/format/formatter.go +++ b/format/formatter.go @@ -27,7 +27,10 @@ const ( var ( ErrInvalidName = errors.New("formatter name must only contain alphanumeric characters, `_` or `-`") // ErrCommandNotFound is returned when the Command for a Formatter is not available. - ErrCommandNotFound = errors.New("formatter command not found in PATH") + ErrCommandNotFound = errors.New("formatter command not found in PATH") + ErrNoPositionalArgSupport = errors.New( + "formatter cannot format multiple files at once (it violates rule 1 of the formatter specification)", + ) nameRegex = regexp.MustCompile("^[a-zA-Z0-9_-]+$") ) @@ -50,12 +53,12 @@ func (f *Formatter) Name() string { return f.name } -func (f *Formatter) MaxBatchSize() int { - if f.config.MaxBatchSize == nil { - return BatchSize +func (f *Formatter) HasNoPositionalArgSupport() bool { + if f.config.NoPositionalArgSupport == nil { + return false } - return *f.config.MaxBatchSize + return *f.config.NoPositionalArgSupport } func (f *Formatter) Priority() int { @@ -90,8 +93,8 @@ func (f *Formatter) Hash(h hash.Hash) error { } func (f *Formatter) Apply(ctx context.Context, files []*walk.File) error { - if len(files) > f.MaxBatchSize() { - return fmt.Errorf("formatter cannot format %d files at once (max batch size: %d)", len(files), f.MaxBatchSize()) + if len(files) > 1 && f.HasNoPositionalArgSupport() { + return ErrNoPositionalArgSupport } start := time.Now() diff --git a/format/scheduler.go b/format/scheduler.go index b4e23b96..6adb4bb0 100644 --- a/format/scheduler.go +++ b/format/scheduler.go @@ -145,7 +145,12 @@ func (s *scheduler) schedule(ctx context.Context, key batchKey, batch []*walk.Fi for _, name := range key.sequence() { formatter := s.formatters[name] - for chunk := range slices.Chunk(batch, formatter.MaxBatchSize()) { + maxBatchSize := len(batch) + if formatter.HasNoPositionalArgSupport() { + maxBatchSize = 1 + } + + for chunk := range slices.Chunk(batch, maxBatchSize) { if err := formatter.Apply(ctx, chunk); err != nil { formatErrors = append(formatErrors, err) } diff --git a/nix/devshells/default.nix b/nix/devshells/default.nix index 36b8d771..c94c3175 100644 --- a/nix/devshells/default.nix +++ b/nix/devshells/default.nix @@ -1,7 +1,7 @@ {pkgs, ...}: pkgs.mkShellNoCC { env = { - GOROOT = "${pkgs.go_1_24}/share/go"; + GOROOT = "${pkgs.go_1_26}/share/go"; CGO_ENABLED = "0"; };