-
-
Notifications
You must be signed in to change notification settings - Fork 6
feat: add format range functionality for partial code formatting #48
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
base: main
Are you sure you want to change the base?
Conversation
Implement the ability to format specific ranges of CSS code instead of entire files, enabling editor integrations where users can select and format only portions of 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.
Pull request overview
This PR implements range formatting functionality for Malva, enabling users to format specific portions of CSS/SCSS/Sass/Less code rather than entire files. This is particularly valuable for editor integrations where users select and format only a portion of their code.
Key changes:
- Implements
format_rangefunction that intelligently expands selections to complete syntactic units (statements or declarations) - Calculates and preserves base indentation levels for formatted ranges
- Adds comprehensive test suite with snapshot testing across multiple CSS dialects
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| malva/src/range.rs | Core implementation of range formatting logic with node detection and indent calculation |
| malva/src/lib.rs | Exports public API for format_range function and FormatRangeResult type |
| malva/src/error.rs | Adds RangeOutOfBounds error variant for range validation |
| malva/tests/fmt_range.rs | Comprehensive test suite including unit tests and snapshot tests |
| malva/tests/fmt_range/**/*.{css,scss,less} | Test fixtures for range formatting |
| malva/tests/fmt_range/**/*.range | Range specification files for test cases |
| malva/tests/fmt_range/**/*.snap | Expected output snapshots for test cases |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Wrap with base indent | ||
| let doc = doc.nest(base_indent); | ||
|
|
||
| // Print => doc |
Copilot
AI
Jan 2, 2026
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 comment "Print => doc" appears to be backwards or confusing. It should likely say "Print doc" or "Print the doc" since this is converting the doc to a string, not converting print to doc.
| // Print => doc | |
| // Print doc |
|
|
||
| let output = format_range(&input, start..end, syntax, &options).unwrap(); | ||
| let output = { | ||
| let mut result = input.clone(); |
Copilot
AI
Jan 2, 2026
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 variable input is a string slice, so calling .clone() on line 119 is unnecessary and potentially misleading. Since input is an &str, you should use .to_string() or just construct the result directly without the intermediate clone.
| let mut result = input.clone(); | |
| let mut result = input.to_string(); |
| fn find_range_node<'a, 's>( | ||
| stylesheet: &'a Stylesheet<'s>, | ||
| range: &Range<usize>, | ||
| _source: &str, |
Copilot
AI
Jan 2, 2026
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 parameter _source is prefixed with an underscore indicating it's unused, but it's included in the function signature. If this parameter is genuinely not needed, it should be removed to avoid confusion. If it's kept for future use or consistency, a comment explaining why would be helpful.
| _source: &str, | |
| _source: &str, // kept for API compatibility / potential future use; intentionally unused |
|
|
||
| } | ||
| @function grid-width($n) { | ||
| @return $very-very-very-very-very-very-vey-long-var * $very-very-very-very-very-very-vey-long-var + ($very-very-very-very-very-very-vey-long-var - 1) * $very-very-very-very-very-very-vey-long-var; |
Copilot
AI
Jan 2, 2026
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 word "vey" appears to be a typo and should be "very". This typo is repeated multiple times in this line.
|
|
||
| } | ||
| @function grid-width($n) { | ||
| @return $very-very-very-very-very-very-vey-long-var * $very-very-very-very-very-very-vey-long-var + ($very-very-very-very-very-very-vey-long-var - 1) * $very-very-very-very-very-very-vey-long-var; |
Copilot
AI
Jan 2, 2026
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 word "vey" appears to be a typo and should be "very". This typo is repeated multiple times in this line.
|
|
||
| /// Represents a node or a list of sibling nodes that should be formatted together. | ||
| enum RangeNode<'a, 's> { | ||
| /// No formatable node found in the range. |
Copilot
AI
Jan 2, 2026
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 word "formatable" should be spelled "formattable" with double 't'.
| /// No formatable node found in the range. | |
| /// No formattable node found in the range. |
| /// - A single node that completely contains the range, or | ||
| /// - Multiple sibling nodes that together contain the range | ||
| /// | ||
| /// For CSS, the minimum formatable unit is a "line-level" node: |
Copilot
AI
Jan 2, 2026
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 word "formatable" should be spelled "formattable" with double 't'.
| /// For CSS, the minimum formatable unit is a "line-level" node: | |
| /// For CSS, the minimum formattable unit is a "line-level" node: |
Implement the ability to format specific ranges of CSS code instead of entire files, enabling editor integrations where users can select and format only portions of code.