Formatting a subtree of a file
Edit: I changed the scope of this to just a subtree, and made the opposite (formatting everything but a subtree) a new issue #114
There have been requests to only format certain things (code, not comments; code, not macros; just comments). As a deterministic formatter genemichaels isn't built to consider original formatting at all, but it's something to consider if there's a way to do it that's sufficient and not a huge burden.
The main difficulties are:
- If the chunk shares lines with other code, it would be easy to go over the line limit since we wouldn't be to touch the chunk code
- For blacklisted chunks, indentation changes would somehow need to be applied, while keeping the same structure. The subtree indentation could be estimated from the leading whitespace on the first line, unless the first line was shared with other code. Similarly for whitelisted chunks, we'd need to somehow determine the indentation from surrounding text
This is a common pattern with partial formatting - rustfmt keeps growing indentation in split strings for example and you need to periodically go in and un-indent stuff manually.
So there needs to be a way to either peek what's nearby the input and do what genemichaels would do regardless of existing format, or initialize formatter state from the input based on heuristics. This is really a selection formatting problem, which I don't think genemichaels supports. I don't know what metrics genemichaels tracks, but those could be read-in from the peeked code and then only mangling the procedural indentation to match adjacent lines depending on semantics.
To summarize, format everything at once, but don't clobber code outside the bounds of the selection. Match source indentation of the adjacent lines if applicable, such as when formatting a selection or a comment within nested code.
To clarify, I think there are two cases here:
- Formatting a file with genemichaels but skipping a chunk (generated code, or a very weird macro invocation, or something else that might need artisanal formatting)
- Formatting a file with rustfmt but formatting modified lines with genemichaels
IIRC this issue and the use cases people mentioned that led to it were mostly about 1. I think 2 is unlikely to be widely useful (other developers undoing the formatting, project rustfmt linters rejecting it).
But as for heuristics (if you're curious), I think primarily the only information required based on the current formatting approach is the indentation of the nearest "wrapped" parent element, i.e. if you're formatting:
{
{
{ a, b, some
.very
.very
.long
.expression() }
}
}
to
{
{
{ a, b, some
.very
.very
.long
.expression() }
}
}
and not
{
{
{ a, b, some
.very
.very
.long
.expression() }
}
}
That is, you'd want to know the indentation of the children of the first two { since they're wrapped, but not the 3rd { since it's not wrapped. It might be reasonable to just assume every parent block is wrapped though.
If there's a good use case for 2 let's make it into a new issue.