-
Notifications
You must be signed in to change notification settings - Fork 88
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
feat: implement grit format
command
#595
base: main
Are you sure you want to change the base?
Conversation
💵 To receive payouts, sign up on Algora, link your Github account and connect with Stripe. |
Thanks @Arian8j2 for working on this, just wanted to chime in that it's definitely on the right track for what I had in mind. Once you're ready, feel free to request a review. |
@@ -20,8 +20,9 @@ anyhow = { version = "1.0.70" } | |||
clap = { version = "4.1.13", features = ["derive"] } | |||
indicatif = { version = "0.17.5" } | |||
# Do *NOT* upgrade beyond 1.0.171 until https://github.com/serde-rs/serde/issues/2538 is fixed |
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.
@morgante Is this still important because biome
depends on serde
version 1.0.217
?
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.
Let's avoid changing this in the same PR if we can.
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.
after looking deeper into this, i found out that the main branch doesn't even use serde
version under 1.0.171
😄, cargo lock of main branch shows:
[[package]]
name = "serde"
version = "1.0.208"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
dependencies = [
"serde_derive",
]
even in the very first commit 79a5365, cargo lock was:
[[package]]
name = "serde"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
the current cargo toml is:
serde = { version = "1.0.164", features = ["derive"] }
this allows versions >= 1.0.164, < 2.0.0
according to the cargo book, for exact 1.0.164
version the toml should looked like:
serde = { version = "=1.0.164", features = ["derive"] }
or for under 1.0.171
it should looked like this:
serde = { version = "< 1.0.171", features = ["derive"] }
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.
Ok this is fine then.
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.
ok then do you want me to remove that comment to avoid confusion later?
crates/cli/src/commands/format.rs
Outdated
resolved.sort(); | ||
|
||
let file_path_to_resolved = group_resolved_patterns_by_group(resolved); | ||
for (file_path, resovled_patterns) in file_path_to_resolved { |
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.
This can be easily executed in parallel, however the tests that verify stdout will fail due to inconsistencies in the output
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.
Instead of changing the input to make tests happy, another option is to sort the test output by line so it is stabilized.
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.
done
crates/cli/src/commands/format.rs
Outdated
Ok(()) | ||
} | ||
|
||
fn format_yaml_file(file_content: &str) -> Result<String> { |
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.
@morgante Is it ok to also format the whole yaml
file?
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's the reason?
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.
because we need to parse the whole yaml
and edit the body
and then serialize it back to yaml
format, in this way the yaml
code also get's formatted. i couldn't find a way to just change body
field, also because it's usually multi line string it's also hard to just find the bytes and replace it, because we need additional space and tabs to make it valid yaml
code.
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 should not not serialize/deserialize the whole body. Round-tripping is lossy. We'd also lose any comments in the yaml.
I understand finding and replacing just the bytes is harder but it's very much possible.
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 problem is in finding the code, for example consider this yaml
file:
version: 0.0.1
patterns:
- name: aspect_ratio_yaml
description: Yaml version of aspect_ratio.md
body: |
language css
`a { $props }` where {
$props <: contains `aspect-ratio: $x`
}
- file: ./others/test_move_import.md
i can easily get the grit code:
language css
`a { $props }` where {
$props <: contains `aspect-ratio: $x`
}
and format it no problem, but then changing the body with new formatted code is difficult because how i find the old grit code in the file? each line is prefixed with indent spaces:
language css
`a { $props }` where {
$props <: contains `aspect-ratio: $x`
}
i need to know how much space i need to put before the code (i used to hard code this in the past commits but then it introduces other problems), thats the hard part, and i couldn't think of a way that is not hacky and breakable
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 could try to find the code like this:
for i in 1..10 {
let indent = " ".repeat(i);
let grit_code_with_indent = prefix_each_line(indent, grit_code)
if let Some(pos) = yaml_file_content.position(grit_code_with_indent) {
// ...
break
}
}
but it's a bit hacky
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 actually have a lot of utils in GritQL itself for handling indentation—tested here—so I think you should be able to leverage those.
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.
nice hint, GritQL really shines in these issues but i don't know if it's overkill or not for this, btw i updated the code, now it uses a grit pattern to find and replace yaml bodies with formatted ones
@@ -20,8 +20,9 @@ anyhow = { version = "1.0.70" } | |||
clap = { version = "4.1.13", features = ["derive"] } | |||
indicatif = { version = "0.17.5" } | |||
# Do *NOT* upgrade beyond 1.0.171 until https://github.com/serde-rs/serde/issues/2538 is fixed |
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.
Let's avoid changing this in the same PR if we can.
crates/cli/src/commands/format.rs
Outdated
resolved.sort(); | ||
|
||
let file_path_to_resolved = group_resolved_patterns_by_group(resolved); | ||
for (file_path, resovled_patterns) in file_path_to_resolved { |
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.
Instead of changing the input to make tests happy, another option is to sort the test output by line so it is stabilized.
crates/cli/src/commands/format.rs
Outdated
Ok(()) | ||
} | ||
|
||
fn format_yaml_file(file_content: &str) -> Result<String> { |
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's the reason?
crates/cli_bin/tests/format.rs
Outdated
output.status.success(), | ||
"Command didn't finish successfully" | ||
); | ||
assert_yaml_snapshot!(String::from_utf8(output.stdout)?); |
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.
Instead of snapshotting the test output, leading to these problems, snapshot the final state of the file (after formatting) + assert on test output containing known messages.
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.
leading to these problems
what problems? the link just opens pull request file changes.
also, in format_patterns_with_rewrite
i snapshot the file contents, you mean don't snapshot the stdout at all? and only test with the write
flag on?
assert on test output containing known messages
in case of errors? for example putting a file that can't be parsed and check for couldn't format file: parse error
in stderr?
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.
in case of errors? for example putting a file that can't be parsed and check for couldn't format file: parse error in stderr?
Right.
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 problems? the link just opens pull request file changes.
It links to the test snapshot.
Yes, you should avoid snapshot testing stdout. Focus snapshot testing the formatted files.
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.
done
crates/cli/src/commands/format.rs
Outdated
if hunks.is_empty() { | ||
return input.to_string(); | ||
} | ||
hunks.sort_by_key(|hunk| hunk.starting_byte); |
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.
Since you're sorting it, just reverse the order (apply last to first) and use replace_range.
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.
Nice idea, Done
/// bubble clause that finds a grit pattern with name "\<pattern_name\>" in yaml and | ||
/// replaces it's body to "\<new_body\>", `format_yaml_file` uses this pattern to replace | ||
/// pattern bodies with formatted ones | ||
const YAML_REPLACE_BODY_PATERN: &str = r#" |
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.
Composing a string then parsing it is going to be error prone / run into escaping issues.
Better to just build the pattern directly in Rust.
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.
Composing a string then parsing it is going to be error prone / run into escaping issues.
Yeah, i was thinking about inserting variable to runtime and use it in the pattern, But couldn't find how to do it
Better to just build the pattern directly in Rust.
That's gonna be hard :), Is there any place that i can see examples of this?
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's gonna be hard :), Is there any place that i can see examples of this?
Unfortunately don't have many examples today, you would have to build it up via the different pattern structs. I'm probably ok merging this as-is.
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.
Is escaping just double quote ok? if so yeah i think it can be merged.
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 double quotes should be sufficient.
@Arian8j2 Please make sure all tests / clippy pass. |
grit format
commandgrit format
command
@morgante Couldn't build
Should we perhaps increase the CI rust version? |
trying to resolve #574
this is just a proof of concept right now and needs more work and time to get complete
/claim #574