rustfmt
rustfmt copied to clipboard
Format markdown documents containing Rust
I was wanting to do something similar to #1695, although in my case I've got a bunch of markdown files containing Rust snippets which I'd like to format.
I knocked up a quick Python script which almost does this (gist).
However it looks like rustfmt will skip any file not ending in *.rs
... Would it be possible to allow non-Rust files if they are explicitly specified using the --file-lines
argument?
Output of running rustfmt from Python:
python rustfmt.py
b"Warning: Extra file listed in file_lines option '/home/michael/Documents/playground/static-analyser-in-rust/src/codemap.md'\nWarning: Extra file listed in file_lines option '/home/michael/Documents/playground/static-analyser-in-rust/src/lib.md'\nWarning: Extra file listed in file_lines option '/home/michael/Documents/playground/static-analyser-in-rust/src/parse.md'\nWarning: Extra file listed in file_lines option '/home/michael/Documents/playground/static-analyser-in-rust/src/lowering.md'\nWarning: Extra file listed in file_lines option '/home/michael/Documents/playground/static-analyser-in-rust/src/analysis.md'\nWarning: Extra file listed in file_lines option '/home/michael/Documents/playground/static-analyser-in-rust/src/errors.md'\nWarning: Extra file listed in file_lines option '/home/michael/Documents/playground/static-analyser-in-rust/src/lex.md'\n\n"
b''
Rustfmt formats Rust programs not Rust files - it runs according to the declared module structure. Therefore, running on markdown files might be a little complicated and I'm not sure how to do it. However, it definitely should be possible - it is basically the same idea as testing snippets in markdown.
Ah that makes sense given how rustfmt-nightly
uses bits of the compiler for parsing and analysis. So the process is a little more complicated than just "here's a string containing some Rust code, please format it".
Would there be any prospects for formatting markdown files or doc-comment examples in the future?
Would there be any prospects for formatting markdown files or doc-comment examples in the future?
Yeah, it seems like something that it would be good to do and I'm pretty sure it is possible, I'm just not sure how to do it :-)
Hi! I'm helping with the translation of TRPL to Brazilian Portuguese (pt-BR) and I'm seeing demand for the same thing. There are many Rust snippets in markdown source that have to be translated, some symbols are translated in batch with search/replace, and it would be nice to run one command to rectify substitutions that have caused formatting mistakes.
Of course this should be super useful to anyone producing Rust content, so the Content Team should be all over this =D Is this the right place to upvote/show support for the feature? Thank you!
I would like to have this same feature. In my case it's the separate .md
doc files that I have that describe the usage of my library. For instance this one: https://github.com/JelteF/derive_more/blob/master/doc/add.md
I too would like to see a feature like this.
It would help with things like this:
https://github.com/rustic-games/things/commit/ae5280d71af606901354d0f62a9f5fe61a25ddfc
Which uses the (unstable) external_doc
feature.
Although, I guess, this would be a bit more complicated, as there are references to modules that only make sense once that external code gets inlined into the main code itself.
Still though, having this would bring this "full circle", allowing you to externally document your library, while still getting proper formatting in those external files.
I've been discussing this with @hukkinj1 for Maud: lambda-fairy/maud#231
The conversation is focused on mdformat, which is written in Python. But I can imagine a hypothetical Markdown formatter using pulldown-cmark that does the same thing.
My quick-and-dirty hack is to:
- create a throwaway Cargo project
- enable
format_code_in_doc_comments
in that project - copy the markdown file into the project's lib.rs as documentation for a function
- format the library
- strip out the documentation comments and function and copy it back to the original file
This seems to work OK.
Script to format markdown
#!/usr/bin/env bash
set -euo pipefail
scratch_dir=$(mktemp -d)
project_dir="${scratch_dir}/scratch"
cargo_toml="${project_dir}/Cargo.toml"
rustfmt_toml="${project_dir}/rustfmt.toml"
lib_rs="${project_dir}/src/lib.rs"
cargo new --lib "${project_dir}"
cat <<-EOF > "${rustfmt_toml}"
format_code_in_doc_comments = true
EOF
for markdown_file in $(git ls-files | rg '.md$'); do
awk '{ print "/// " $0 } END { print "fn dummy() {}"}' "${markdown_file}" > "${lib_rs}"
cargo +nightly fmt --manifest-path="${cargo_toml}"
sed -E -e '$ d' -e 's@/// ?@@' "${lib_rs}" > "${markdown_file}"
done
Also works, doesn't write any files:
cat README.md | (
while IFS= read -r LINE; do
if [[ -z ${LINE} ]]; then
echo "///"
else
echo "/// ${LINE}"
fi
done
echo "fn dummy() {}"
) | rustfmt --check --config unstable_features=true,format_code_in_doc_comments=true,max_width=80
Notably rustfmt
still returns a zero exit code even if it wants to make changes, so you should check that there is no output if this is somehow part of your CI.