radian-software / apheleia

🌷 Run code formatter on buffer contents without moving point, using RCS patches and dynamic programming.
MIT License
518 stars 73 forks source link

Feature Request: Support cargo fmt #278

Open amy-keibler opened 6 months ago

amy-keibler commented 6 months ago

Found this project via a Doom Emacs GitHub Issue that pointed here. Seems like a cool project, so thanks for this contribution to the Emacs ecosystem.

Ideally, I would expect formatting of Rust code to default to using cargo fmt. It's the command that the rustfmt documentation recommends running. As documented, this would rely on cargo to provide the correct edition of Rust to pass along to rustc. For other examples in the Rust ecosystem, rust-analyzer appears to replicate the cargo functionality internally.

As it currently stands, users need to duplicate their configuration into a rustfmt.toml and keep it in sync with their Cargo.toml. Changing the current default would impact users who write Rust without using cargo, but would be more consistent with the ecosystem. If I understand the user guide correctly, I can override the default behavior of calling rustfmt myself, but I wanted to prompt a discussion on if the current default makes sense.


Edit: setting the configuration with

(setf (alist-get 'rustfmt apheleia-formatters)
      '("cargo" "--quiet" "fmt" "--" "--quiet" "--emit" "stdout"))

runs in the src/ folder rather than the root of the project and results in

Wed Jan  3 16:50:16 2024 :: /home/amy/code/example_workspace/example_crate/src/
$ cargo --quiet fmt -- --quiet --emit stdout

Failed to find targets

so it would appear to require more effort than changing the configuration alone.

raxod502 commented 6 months ago

I've got no objection to changing the default. What I want to ensure is that formatting still runs even when there is no project configuration, instead of erroring out.

Would I would expect as a user is that if there is Cargo configuration in the project, then Cargo would be used. Otherwise, rustfmt would be used. This should be possible with a small shell script. As for the working directory issue, try apheleia-from-project-root.

fosskers commented 5 months ago

What I want to ensure is that formatting still runs even when there is no project configuration, instead of erroring out.

This is especially relevant for say, org-babel source blocks that contain Rust code.

amy-keibler commented 4 months ago

Thank you for the suggestion. Unfortunately, with the configuration of

(setf (alist-get 'rustfmt apheleia-formatters)
      '("apheleia-from-project-root" "Cargo.lock" "cargo" "--quiet" "fmt" "--" "--quiet" "--emit" "stdout")))

I end up with a formatted copy of the source below the original contents in the file, rather than the original contents of the file modified via the formatter. Anything I'm doing that's obviously incorrect? I'm on the latest version of doom Emacs, which appears to be using (package! apheleia :pin "96a9805ecb75aac2adde7568d26b3e3b3ffc19af"), if that's helpful.

raxod502 commented 4 months ago

I'm not sure. That looks fine to me, and I tried that formatter definition in my own configuration and it seemed to work properly.

dcarley commented 2 months ago

I end up with a formatted copy of the source below the original contents in the file, rather than the original contents of the file modified via the formatter.

cargo fmt will discover all files in a project, even when given STDIN or a single path: https://github.com/rust-lang/rustfmt/issues/4485#issuecomment-957798514

When combined with --emit stdout this results in the contents of all the files being concentated together and dumped back into the buffer.

raxod502 commented 2 months ago

Erm, that seems crazy. It formats and concatenates all files in a project even when you explicitly ask it to format a single file? Sounds like this needs to be fixed upstream.