support formatter ordering #20

Merged
brianmcgee merged 4 commits from feat/formatter-ordering into main 2024-01-12 11:46:05 +00:00
Member

Allows specifying the order in which formatters are applied.

Very simple for now, adding a Before field to the formatted config which allows the user to say that formatter x needs to be applied before formatted y.

[formatter.statix]
command = "statix"
includes = ["*.nix"]
before = "deadnix"

[formatter.deadnix]
command = "statix"
includes = ["*.nix"]

Signed-off-by: Brian McGee brian@bmcgee.ie

Allows specifying the order in which formatters are applied. Very simple for now, adding a `Before` field to the formatted config which allows the user to say that formatter `x` needs to be applied _before_ formatted `y`. ```toml [formatter.statix] command = "statix" includes = ["*.nix"] before = "deadnix" [formatter.deadnix] command = "statix" includes = ["*.nix"] ``` Signed-off-by: Brian McGee <brian@bmcgee.ie>
brianmcgee added 1 commit 2024-01-08 16:21:47 +00:00
Signed-off-by: Brian McGee <brian@bmcgee.ie>
Author
Member

@zimbatm what do you think about allowing the user to configure a formatter as needing to be before another?

Essentially, it restricts things to simple linear behaviour. I can't envision a scenario that would require a more complex config.

In a real-world scenario, you would have statix before deadnix for example.

test.WriteConfig(t, configPath, format.Config{
		Formatters: map[string]*format.Formatter{
			"hs-a": {
				Command:  "echo",
				Includes: []string{"*.hs"},
				Before:   "hs-b",
			},
			"hs-b": {
				Command:  "echo",
				Includes: []string{"*.hs"},
				Before:   "hs-c",
			},
			"hs-c": {
				Command:  "echo",
				Includes: []string{"*.hs"},
			},
			"py-a": {
				Command:  "echo",
				Includes: []string{"*.py"},
				Before:   "py-b",
			},
			"py-b": {
				Command:  "echo",
				Includes: []string{"*.py"},
			},
		},
	})
@zimbatm what do you think about allowing the user to configure a formatter as needing to be before another? Essentially, it restricts things to simple linear behaviour. I can't envision a scenario that would require a more complex config. In a real-world scenario, you would have `statix` before `deadnix` for example. ```go test.WriteConfig(t, configPath, format.Config{ Formatters: map[string]*format.Formatter{ "hs-a": { Command: "echo", Includes: []string{"*.hs"}, Before: "hs-b", }, "hs-b": { Command: "echo", Includes: []string{"*.hs"}, Before: "hs-c", }, "hs-c": { Command: "echo", Includes: []string{"*.hs"}, }, "py-a": { Command: "echo", Includes: []string{"*.py"}, Before: "py-b", }, "py-b": { Command: "echo", Includes: []string{"*.py"}, }, }, }) ```
brianmcgee requested review from zimbatm 2024-01-08 16:24:56 +00:00
zimbatm approved these changes 2024-01-08 17:03:04 +00:00
zimbatm left a comment
Owner

I haven't wrapped my head around the concurrent aspect of the code, but the rest looks good.

In some cases, you might want to declare that deadnix is run before both statix and nixpkgs-fmt. The intent can't be expressed with the current design, but this can be added in a comment. I think this is good for the first iteration.

I haven't wrapped my head around the concurrent aspect of the code, but the rest looks good. In some cases, you might want to declare that deadnix is run before both statix and nixpkgs-fmt. The intent can't be expressed with the current design, but this can be added in a comment. I think this is good for the first iteration.
@ -67,0 +72,4 @@
if !ok {
return fmt.Errorf(
"formatter %v is before %v but config for %v was not found",
name, formatter.Before, formatter.Before,

formatter.Before is there 2 times

formatter.Before is there 2 times
Author
Member

If you look at the string you can see why it's listed twice

If you look at the string you can see why it's listed twice
brianmcgee marked this conversation as resolved
@ -67,0 +74,4 @@
"formatter %v is before %v but config for %v was not found",
name, formatter.Before, formatter.Before,
)
}

You need a second for loop here to check for the dependency cycle.

You need a second for loop here to check for the dependency cycle.
Author
Member

Yeah I haven't done the dependency cycle check yet

Yeah I haven't done the dependency cycle check yet
Author
Member

Addressed in 23c86cee02

Addressed in 23c86cee027e133181577f749f7716e1ad0986cb
brianmcgee marked this conversation as resolved
@ -25,2 +25,4 @@
// Excludes is an optional list of glob patterns used to exclude certain files from this Formatter.
Excludes []string
// Before is the name of another formatter which must process a path after this one
Before string

Personal taste thing: because of how many public/private fields there are, I would split this into a FormatterConfig that only contains the config and serializes/deserializes, and then the Formatter that gets generated from the config. That way, how to interact with the structs in the rest of the code becomes clearer. I don't think the Before field should be mutated in the code for example.

Personal taste thing: because of how many public/private fields there are, I would split this into a FormatterConfig that only contains the config and serializes/deserializes, and then the Formatter that gets generated from the config. That way, how to interact with the structs in the rest of the code becomes clearer. I don't think the Before field should be mutated in the code for example.
Author
Member

It was a fair point, I've separated things out in c542655177

It was a fair point, I've separated things out in https://git.numtide.com/numtide/treefmt/commit/c54265517754f4d67684e5810c87cbba0644ae0d
brianmcgee marked this conversation as resolved
Author
Member

In some cases, you might want to declare that deadnix is run before both statix and nixpkgs-fmt. The intent can't be expressed with the current design, but this can be added in a comment. I think this is good for the first iteration.

In the example you provide, deadnix would be before statix which would be before nixpkgs-fmt:

[deadnix]
...
Before = "statix"

[statix]
...
Before = "nixpkgs-fmt"

[nixpkgs-fmt]
...

I agree, this could be more expressive but as a first iteration it would solve some existing problems.

> In some cases, you might want to declare that deadnix is run before both statix and nixpkgs-fmt. The intent can't be expressed with the current design, but this can be added in a comment. I think this is good for the first iteration. In the example you provide, `deadnix` would be before `statix` which would be before `nixpkgs-fmt`: ```toml [deadnix] ... Before = "statix" [statix] ... Before = "nixpkgs-fmt" [nixpkgs-fmt] ... ``` I agree, this could be more expressive but as a first iteration it would solve some existing problems.
brianmcgee added 1 commit 2024-01-10 14:28:32 +00:00
Signed-off-by: Brian McGee <brian@bmcgee.ie>
brianmcgee force-pushed feat/formatter-ordering from c542655177 to d323715fa8 2024-01-12 09:44:07 +00:00 Compare
brianmcgee added 1 commit 2024-01-12 10:08:21 +00:00
Signed-off-by: Brian McGee <brian@bmcgee.ie>
brianmcgee changed title from WIP: support formatter ordering to support formatter ordering 2024-01-12 10:09:08 +00:00
brianmcgee merged commit c7d0138a02 into main 2024-01-12 11:46:05 +00:00
This repo is archived. You cannot comment on pull requests.
No reviewers
No Milestone
No project
No Assignees
2 Participants
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: numtide/treefmt#20
No description provided.