# Tool configs in Cargo.toml (e.g. rustfmt, clippy) and alternatives brainstorming

**URL:** <https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055>\
**Category:** tools and infrastructure\
**Created:** [December 18, 2018, 6:17pm UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055 "2018-12-18T18:17:38Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![kestred](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kestred/32/4896_2.png) [@kestred](https://internals.rust-lang.org/u/kestred)\
**Post date:** [December 18, 2018, 6:17pm UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/1 "2018-12-18T18:17:38Z")

</div>

As more tools become available to the rust community, each tool adopts a new `mytool.toml` configuration file, which leads to a proliferation of config files at the root of a typical project (or sometimes subproject in a workspace).

Intuitively, I prefer to minimize the number of configuration files present at the root of my project. I'll try to put that intuition a bit into words, but hopefully others will also be able to come along with more directly informed experiences to reinforce the motivation.

- More files, particularly at a project root, can make it more difficult for a newcomer to scan a explore a project's file directory to figure out where to get started.

- Particularily, if each tool adopts its own non-standard config file naming scheme it beomes more difficult for scan for files of a particular file you may be looking for.

- More "community standard" configuration files increases the learning curve around project organization for newcomers to _rust_; although this is specifically when stepping in to an existing project, rather than learning via `cargo new` which doesn't impose any knowledge on the subject.

This problem is substantially mitigated, because Rust tools tend to reach a very high bar in terms of design and usability before becoming widely adopted by the community; and additionally tend to have widely applicable defaults that are useful for a majority of cases. However desiring just a single custom config rule leads to managing/teaching about a new config file.

### Prior work

The NPM community (known perhaps for have _too much_ and _non-standardized_ tooling) has nonetheless come up with the prior art of supporting the majority of lint/test/format configuration in the `package.json` file (most equivalent to `Cargo.toml`, specifically dependency management). The NPM communities approach to this is fragmented because it is a de-facto rather than explicit standard; in particular the config subsections are inconsistently named (e.g. `eslintConfig`, `browserlist`, `jest`).

### Idea - Add `[tools]` section in `Cargo.toml`

> **N.B.** as noted in @sflacker's and @steveklabnik's quick feedback, there is an existing `[package.metadata]` section which behaves in the same way as described below.
> 
> Instead--- would we want to update `rustfmt` and `clippy` to support loading their configuration from this section, and update surrounding documentation to encourage new tools to do the same.
> 
> Perhaps we could add develop a `cargo-config` crate which automates a community recommended configuration config standard which could for example, automatically look in `Cargo.toml` for `metadata` as well as `.<tool>.toml` and `tool.toml` like rustfmt and clippy do currently.

A tools section in the cargo manifest would provide a standard place to store config files for both community blesses as well as custom or experimental tools.

Documentation about the `[tools]` section in the cargo manifest will inform the normative behavior for naming the config subsection to be `[tools.<tool_name>]`, e.g. `[tools.rustfmt]` or `[tools.clippy]`. Cargo would mostly ignore this section, but other optional standards could also be introduced to integrate the tools.

Example:

```toml
[package]
name = "mycrate"

[tools.rustfmt]
reorder_imports = false

[tools.clippy]
blacklisted-names = ["toto", "tata", "titi"]

```

In many, I feel this is similar extension compared to [tool lints and attributes](https://github.com/rust-lang/rfcs/blob/master/text/2103-tool-attributes.md).

### Alternative - More configuration as code

Another reasonable alternative is to try to continue to expand the capabilities or just standardization of the "configuration as code pattern" (largely used by clippy in the form of `tool_lints`, although it also has its own config file for some things which I believe cannot be expressed as attributes such as clippy's `blacklisted-names`).

Specifically, we could move more tool configuration in to `{main,lib}.rs` attributes.

_Possible syntax:_

```rust
#![rustfmt::config(reorder_imports = false)]

```

* * *

Looking forward to feedback!

---

<div class="post-metadata">

**Author:** ![sfackler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sfackler/32/9_2.png) [@sfackler](https://internals.rust-lang.org/u/sfackler)\
**Post date:** [December 18, 2018, 6:30pm UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/2 "2018-12-18T18:30:54Z")

</div>

The `[package.metadata]` section of Cargo.toml is already reserved for this kind of thing. Your example would look like

```rust
[package]
name = "mycrate"

[package.metadata.rustfmt]
reorder_imports = false

[package.metadata.clippy]
blacklisted-names = ["toto", "tata", "titi"]

```

---

<div class="post-metadata">

**Author:** ![steveklabnik](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steveklabnik/32/4524_2.png) [@steveklabnik](https://internals.rust-lang.org/u/steveklabnik)\
**Post date:** [December 18, 2018, 6:49pm UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/3 "2018-12-18T18:49:58Z")

</div>

For an example of a crate that does this: [https://github.com/rust-osdev/bootimage#configuration](https://github.com/rust-osdev/bootimage#configuration)

---

<div class="post-metadata">

**Author:** ![kestred](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kestred/32/4896_2.png) [@kestred](https://internals.rust-lang.org/u/kestred)\
**Post date:** [December 18, 2018, 6:57pm UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/4 "2018-12-18T18:57:06Z")

</div>

> [@sfackler](#):
>
> The `[package.metadata]` section of Cargo.toml is already reserved for this kind of thing. Your example would look like

I missed that section, but yeah that makes sense.

The follow up would be, is it desirable to have `rustfmt` and `clippy` respect configuration defined in `[package.metadata.rustfmt]` and `[package.metadata.clippy]` respectively.

Separately, should it then be encouraged specifically by updating the documentation for the `[package.metadata]` section and in `clippy` and `rustfmt`'s configuration section? (Possibly, not initially, but overtime after getting more experience with combined vs separated config files?)

---

<div class="post-metadata">

**Author:** ![kestred](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kestred/32/4896_2.png) [@kestred](https://internals.rust-lang.org/u/kestred)\
**Post date:** [December 18, 2018, 7:06pm UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/5 "2018-12-18T19:06:11Z")

</div>

Updated the opening post.

As a follow up, if there was consensus about using `[package.metadata]`, it might make sense to have a community recommended `cargo_config` (or similar) crate that automatically looks in the recommended places, possibly including:

- The `[package.metdata.<tool>]` key in `Cargo.toml`
- The `<tool>.toml` and `.<tool>.toml` like rustfmt and clippy do currently.

---

<div class="post-metadata">

**Author:** ![johnthagen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/johnthagen/32/2005_2.png) [@johnthagen](https://internals.rust-lang.org/u/johnthagen)\
**Post date:** [December 18, 2018, 7:46pm UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/6 "2018-12-18T19:46:01Z")

</div>

Related prior work: [Python specifies a `pyproject.toml` that has a `[tools]` section](https://www.python.org/dev/peps/pep-0518/#tool-table).

---

<div class="post-metadata">

**Author:** ![JeanMertz](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jeanmertz/32/4536_2.png) [@JeanMertz](https://internals.rust-lang.org/u/JeanMertz)\
**Post date:** [December 18, 2018, 10:07pm UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/7 "2018-12-18T22:07:02Z")

</div>

I would love to see this situation become a reality.

Specifically, the current situation for us right now is:

- `rust-toolchain` to specify the Rust version of a project
- `rustfmt.toml` for rustfmt specific configuration
- no config file support for Clippy, requiring all configs to be defined in the library/application code itself (repeated, when using a workspace)

It would be great if (at least) these three could be unified in some way. I guess `rust-toolchain` is a bit of an odd ball in this list, and it’s the one that causes the least amount of “pain” in this situation, as far as I’m concerned.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [December 18, 2018, 10:07pm UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/8 "2018-12-18T22:07:53Z")

</div>

[`cargo-deb`](https://crates.rs/crates/cargo-deb) uses the `[package.metadata]` approach. For it, and similar tools, I’m maintaining [the `cargo_toml` crate](https://crates.rs/crates/cargo_toml), which is a simple Serde-compatible definition that can read `Cargo.toml` with your custom metadata.

---

<div class="post-metadata">

**Author:** ![Screwtapello](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/screwtapello/32/1076_2.png) [@Screwtapello](https://internals.rust-lang.org/u/Screwtapello)\
**Post date:** [December 19, 2018, 4:50am UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/9 "2018-12-19T04:50:50Z")

</div>

I have a use-case for standalone config files: I have my editor set up so that if a `rustfmt.toml` or `.rustfmt.toml` file exists, and the `rustfmt` executable is present, it will automatically reformat files as I save them.

I could permanently enable auto-formatting, but sometimes I contribute to projects that don’t use auto-formatting, and it would be rude to include formatting changes in a non-formatting-related pull request.

I could enable auto-formatting manually, but then it wouldn’t be very “auto”.

I could add another clause to my test, like "`Cargo.toml` contains a line matching `^\s*\[package.metadata.rustfmt[].]` but it feels wrong for an empty section in a config file to be semantically significant… more wrong than an empty file, at any rate.

I would feel better about this if I could query `Cargo.toml` via `cargo`, instead of trying to interpret complex structured data with regexes. Perhaps something like a `cargo metadata --uses-tool rustfmt` command that returns 0 if there’s evidence of a `package.metadata.rustfmt` section (or any other convention) in `Cargo.toml`.

(I don’t have this same issue with Clippy, because Clippy does not change file content so I’m happy to leave it permanently enabled)

---

<div class="post-metadata">

**Author:** ![ehuss](https://avatars.discourse-cdn.com/v4/letter/e/9de0a6/32.png) [@ehuss](https://internals.rust-lang.org/u/ehuss)\
**Post date:** [December 19, 2018, 6:25am UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/10 "2018-12-19T06:25:58Z")

</div>

One problem with `[package.metadata]` is that it does not support virtual workspaces.

I’m not convinced yet that `Cargo.toml` is the right place for tool configuration. If an organization wants to share settings across projects, but they don’t use a monolithic workspace, then they wouldn’t be able to share them. That may not be a common enough need, though. What are the considerations of using `Cargo.toml` over `.cargo/config`?

I recently wrote up some questions regarding lint configuration here: [https://github.com/rust-lang/cargo/pull/5728#issuecomment-447073103](https://github.com/rust-lang/cargo/pull/5728#issuecomment-447073103)

---

<div class="post-metadata">

**Author:** ![phansch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/phansch/32/3856_2.png) [@phansch](https://internals.rust-lang.org/u/phansch)\
**Post date:** [December 19, 2018, 7:08am UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/11 "2018-12-19T07:08:47Z")

</div>

I’m currently working on a lint configuration Mini-RFC with @detrumi, that would be mildly related to this proposal. It’s good to see other people thinking about this 🙂

@ehussOne of the advantages of taking `Cargo.toml` over `.cargo/config` is that users already have a `Cargo.toml` in their projects. I suppose almost no-one has a `.cargo/config` file. It would probably lead to a situation where people are confused as to what configuration goes into which file? But yes, as you noted it would not be possible to share files across projects, unless we add a new `inherits_from` key or something like that to `Cargo.toml`.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:31am UTC](https://internals.rust-lang.org/t/tool-configs-in-cargo-toml-e-g-rustfmt-clippy-and-alternatives-brainstorming/9055/12 "2019-03-25T08:31:19Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
