This is similar to other problems people have with rustfmt throwing out most input whitespace, for example with column aligned matrices. Most of what keeps me from using rustfmt, at least on projects I do 90% of the work on, is whitespace differences. Here is an alternative hack that rustfmt doesn't mutilate:
function_foo(); // call function_foo
function_boo("a string"); // a longer line
f(x); // a really short line
I believe its rule is to leave comment content alone, generally. Comparisons to gofmt are common, and I've done nearly nothing with go, but I noticed gofmt tends to leave input whitespace alone in many more cases.
Note that one of the fmt-rfcs/principles.md at master ¡ rust-dev-tools/fmt-rfcs ¡ GitHub is to "Prefer block indent over visual indent" (for a variety of reasons including that visual indent is annoying in screen readers), so it's not surprising to me that this isn't supported.
FWIW, I usually do prefer to use block indentation, except in cases where visual indentation clearly enhances readability. To give a more complex, real world example, below is an excerpt from a current project. Interestingly enough, if you put this code snippet through rustfmt (playground) it completely gives up on formatting the match and doesn't change anything! I'm surprised by that and looking forward to getting this formatting into some "rustfmt protected" projects!
// Return CharClass for a char
fn char_class(c: char) -> CharClass {
use CharClass::*;
match c {
'\u{0000}'..='\u{0008}' => Control, // C0 (XML disallowed)
'\u{0009}' | // HT
'\u{000A}' | // LF
'\u{000B}' => WhiteSpace, // VT
'\u{000C}' => Control, // FF (C0)
'\u{000D}' => WhiteSpace, // CR
'\u{000E}'..='\u{001F}' => Control, // C0
'\u{0020}' => WhiteSpace, // SPACE
'\u{007F}' | // DEL (C0)
'\u{0080}'..='\u{009F}' => Control, // C1 (XML disallowed)
'\u{00A0}' => WhiteSpace, // NO-BREAK SPACE (NBSP)
// Not always (zero) white; shows hypen when line is wrapped.
// '\u{00AD}' => Un- // SOFT HYPHEN,
// Not white, rendered with a line:
// '\u{1680}' => Un- // OGHAM SPACE MARK
// Effects subsequent characters in mongolion:
// '\u{180E}' => Un- // MONGOLIAN VOWEL SEPARATOR
'\u{2000}'..='\u{200A}' => WhiteSpace, // EN QUAD..HAIR SPACE
'\u{200B}' | // ZERO WIDTH SPACE
'\u{200C}' => ZeroSpace, // ZERO WIDTH NON-JOINER
'\u{2028}' | // LINE SEPARATOR
'\u{2029}' | // PARAGRAPH SEPARATOR
'\u{202F}' | // NARROW NO-BREAK SPACE
'\u{205F}' => WhiteSpace, // MEDIUM MATHEMATICAL SPACE
'\u{2060}' => ZeroSpace, // WORD JOINER
'\u{3000}' => WhiteSpace, // IDEOGRAPHIC SPACE
'\u{FEFF}' => ZeroSpace, // BOM or ZERO WIDTH NON-BREAKING
'\u{FFFE}' | // Bad BOM (not assigned)
'\u{FFFF}' => Control, // Not assigned (invalid)
_ => Unclassified,
}
}
I'd call this a feature of rustfmt 1.4 that it leaves the original, better formatting alone. Changing it would be breaking WRT format stability, in any case.
What would be a nice improvement in rustfmt 1.5, IMO, would be for it to be able to leave a much wider set of whitespace-only diffs or otherwise "reasonable enough" formatting alone. Some more examples of which might make for an interesting new topic, given the time. One could imagine some sort of heuristic based per-block criteria (how far is current format from rustfmt ideal) and some configurable knob (e.g. 1..10) for how strict rustfmt should be.
I think preferred formatting style is very subjective, however being able to use automated formatting is definitely a plus, especially for cooperating with others.
It would be nice if more vertical alignment and spacing settings were available for rustfmt.
The absence of such settings means that I just don't use rustfmt on my crates. And I haven't found the time to propose the settings or develop something that formats to my liking, so manual formatting for the time being...
What I dream of is something that will just learn from your style, and that doesn't override what you've manually corrected, directly in the editor. Your config file would then be a set of neural network weights...
If I was trying to help rustfmt reformat my above function, based on @Nemo157's observation, the simplest change while preserving comments would be to replace all the | patterns with individual match arms (playground)
That leads to another interesting observation: while rustfmt discards the pattern alignment, it actually inserts SPACEs to visually re-align the trailing commentsâ˝ See diff excerpt of what rustfmt does to the above version, below. Isn't it a bit inconsistent for rustfmt to support visual comment alignment in match, but not for the OP's function calls? Reality seems a bit more complicated than just "prefer block indent".
That said, I have seen a few cases where #[rustfmt::skip] doesn't work because reasons, and some other cases where rustfmt decides to reformat some existing whitespace after an update. It creates some diff noise, but at least the formatting ends up consistent.
I was actually thinking of creating a fork-able parallel-universe rust-format (rfcs) kind of specification that defines my personal set of departures from rustfmt, starting by committing a rustfmt-ed branch to the most successful rust open-source I have; but I'm not sure how popular that effort could be. Your example could benefit (as an example) from more chaos (aka entropy) than the identity matrix. Any suggestions for this line of skepticism?
I think one possiblity is working on rustfmt to add more configuration options so it can be more flexible to other styles. For me, a great hurdle is the limited vertical alignment support.
That way there is no need to decide who's style choices are better, but we can enlargen the group of people that can benefit from automated formatting, and can put a rustfmt config in their repo to ease collaboration.
I think it's up to a project author/maintainer to choose what style they like, as they have to read and deal with the code the most and ultimately take responsibility for it. For me the standard configuration of rustfmt produces unreadable ascii art, but I will happily abide with that when filing PR's. It's out of the question in my own projects though. I wouldn't be able to have the same quality standard if I used this formatting.