Does anyone use a customized configuration for rustfmt?

Personally, I really appreciate the consistency that a team gets from auto-code formatting. IMO makes the code easier to read when the entire code base looks the same.

Here is the contents of my rustfmt.toml

max_width = 140
chain_width = 100
fn_call_width = 100

Not much I know... but it was enough for our team.

Unfortunately, I'm working a private project and I couldn't post the code here. However, I will gradually make simpler examples where rustfmt doesn't work well and submit them to the rustfmt repository.

1 Like

A lot of the "_width" parameters are worth looking at, because they have a lot of impact on the formatting and fairly odd defaults. @Nocker and @kornel comments above get at this. I use:

chain_width = 100
fn_call_width = 100
struct_lit_width = 60
struct_variant_width = 50

I am using this:

brace_style = "AlwaysNextLine"
control_brace_style = "AlwaysNextLine"
tab_spaces = 2
fn_args_layout = "Compressed"
max_width = 120
struct_lit_width = 100
chain_width = 100

But I only just started using rustfmt, I am experimenting with it. If I published a crate, I would probably use the default settings.

Every time this topic comes up I have a plea to make:

Can't we all just use the out of the box defaults of rustfmt rather than messing around with our own ideas of how code should look?

That way we end up with a global pool of software all written to the same standard with no jarring surprises. Making reading Rust code much smoother for everyone.

Also saves us all from having to waste time thinking about this over and over again. Laying down project standards and so on. As was the case for every software project I have worked on over decades. Endless bickering over tabs vs spaces, how many spaces to indent, Camel case vs underscores, etc, etc. A senseless waste of human life.

4 Likes

Thank you all for good discussions here. I personally also think it's good if everyone can stick to a good default formatting configuration, however, I do see lots of issues with the default rustfmt settings.

  1. The following code
if x == y { // comments 

is formatted to

if x == y {
    // comments

I personally prefer if x == y { // comments as the comment is for the line if x == y { rather than the following line. I guess the this is mainly personal preference and people would argue that I can just place // comments before the line if x == y {.
2. The following code

s as f64 + match some_expression {
    branch code 
}

is formatted to

s as f64 
    + match some_expression {
        branch code 
}

even if the first line is less than 70 characters. This increase indention which makes code look ugly if you have several layers of nested code.
3. The default rustfmt settings (not sure whether customized settings can fix it or not) is inconsistent about formatting. Sometimes it has the following formatted code

score + {
    ...

while sometimes it has

score 
    + {
        ...

Obviously, rustfmt has lots of other inconsistent behaviors. For examples, sometimes an obviously too long line is not break into multiple lines even if it can break into multiples to increase readability. Sometimes, rustfmt over break a not very long line and produces multiple very short lines.
4. In a special case, rustfmt formats my code to have 2 curly braces in 2 separate lines but in the same column and things in the block are miss indented, which greatly affects readability.

...
        }
        }
  1. Perhaps the worst thing (likely a bug) about rustfmt is that trailing spaces after code makes rustfmt fail to work while trailing spaces in comments is OK.

The first 2 examples might be personal preference but the last 3 examples definitely show issues of rustfmt. I will gradually create small examples which reproduces those issues and submit them to the rustfmt repository.

2 Likes

Inspired by Lisp style identation, I dealt with single line ) nd } via Rustfmt option to put all )})'s on the same line? - #8 by zeroexcuses

I am very happy with this decision so far.

If only! But rustfmt defaults leave room for just such messing. You can freely choose from any of the options below without rustfmt interfering

use serde::Deserialize;

use serde::Serialize;
use serde::Serialize;

use serde::Deserialize;
use serde::Serialize;
use serde::Deserialize;
use serde::{Serialize, Deserialize};

By configuring rustfmt, I can at least automatically enforce one of them in my projects, even if someone might disagree with the exact options I chose.

The reason I don't use the defaults is primarily because I want stricter formatting, not different. Annotating reasoning to the file from my previous comment:

// I can't rely on contributors using .editorconfig
newline_style = "unix"
// require the shorthand instead of it being optional
use_field_init_shorthand = true
// outdated default — `?` was unstable at the time
// additionally the `try!` macro is deprecated now
use_try_shorthand = true

// Unstable features below
unstable_features = true
version = "Two"
// code can be 100 characters, why not comments?
comment_width = 100
// force contributors to follow the formatting requirement
error_on_line_overflow = true
// next 4: why not?
format_code_in_doc_comments = true
format_macro_bodies = true
format_macro_matchers = true
format_strings = true
// better grepping
imports_granularity = "Module"
// quicker manual lookup
group_imports = "StdExternalCrate"
// why use an attribute if a normal doc comment would suffice?
normalize_doc_attributes = true
// why not?
wrap_comments = true

(using // instead of # for syntax highlighting purposes)

The only thing I'd even consider changing is group_imports. Aside from that, imports_granularity enforces a certain standard as opposed to letting anything fly, comment_width's default is inconsistent with code, imports_module is useful for external tooling, and everything else (for the most part) is only enforcing stricter formatting or changing outdated defaults.

Personally I don't find formatting to be a hassle for any project. Just enable format-on-save (or format-on-type if you've already lost it) and call it a day.

2 Likes

IMO the defaults are pretty good, except for the line delimiters, which I always set to

newline_style = "unix"

which should have been the default. It's pretty annoying to see PRs containing a lot of (unintentional) meaningless line delimiter changes.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.