70 %

Piping Rust code to rustfmt with configuration for shorter code examples in blog posts

The way I write code is not the way I read code, especially when I read code on the web (such as my own personal site). Lines that are fine in my editor are often too long for the web to comfortably read without swiping back and forth. This is why I run my Rust code through a custom rustfmt config.

First we need to write out a rustfmt toml file. We can use the default one like this:

rustfmt --print-config default ./rustfmt.toml

The config looks like this, which I remove most of

./rustfmt.toml
toml
max_width = 100
hard_tabs = false
tab_spaces = 4
newline_style = "Auto"
use_small_heuristics = "Default"
indent_style = "Block"
wrap_comments = false
format_code_in_doc_comments = false
comment_width = 80
normalize_comments = false
normalize_doc_attributes = false
license_template_path = ""
format_strings = false
format_macro_matchers = false
format_macro_bodies = true
empty_item_single_line = true
struct_lit_single_line = true
fn_single_line = false
where_single_line = false
imports_indent = "Block"
imports_layout = "Mixed"
merge_imports = false
reorder_imports = true
reorder_modules = true
reorder_impl_items = false
type_punctuation_density = "Wide"
space_before_colon = false
space_after_colon = true
spaces_around_ranges = false
binop_separator = "Front"
remove_nested_parens = true
combine_control_expr = true
overflow_delimited_expr = false
struct_field_align_threshold = 0
enum_discrim_align_threshold = 0
match_arm_blocks = true
force_multiline_blocks = false
fn_args_layout = "Tall"
brace_style = "SameLineWhere"
control_brace_style = "AlwaysSameLine"
trailing_semicolon = true
trailing_comma = "Vertical"
match_block_trailing_comma = false
blank_lines_upper_bound = 1
blank_lines_lower_bound = 0
edition = "2015"
version = "One"
inline_attribute_width = 0
merge_derives = true
use_try_shorthand = false
use_field_init_shorthand = false
force_explicit_abi = true
condense_wildcard_suffixes = false
color = "Auto"
required_version = "1.4.17"
unstable_features = false
disable_all_formatting = false
skip_children = false
hide_parse_errors = false
error_on_line_overflow = false
error_on_unformatted = false
report_todo = "Never"
report_fixme = "Never"
ignore = []
emit_mode = "Files"
make_backup = false

The line I care most about is max_width = 100 which I set to something like 60 for the web.

To use this configuration, on mac os I copy code into my clipboard and then use pbpaste to pipe it to rustfmt and back to my clipboard.

shell
pbpaste | rustfmt --config-path ~/github/christopherbiscardi/dotfiles/rustfmt.toml | pbcopy

Example

code before formatting:

rust
pub fn atx_heading(input: &[u8]) -> IResult<&[u8], ATXHeading, MDXError<&[u8]>> {
let (input, hashes) = hashtags(input).map_err(Err::convert)?;
if hashes.len() > 6 {
return Err(Error(MDXError::TooManyHashes));
}
let (input, _) = spaces(input).map_err(Err::convert)?;
let (input, val) = rest_of_line(std::str::from_utf8(input).unwrap()).map_err(Err::convert)?;
Ok((
input.as_bytes(),
ATXHeading {
level: hashes.len(),
value: val.as_bytes(),
},
))
}

code after formatting. Note that comments don't change, so if you have a particularly long comment you may need a nightly rustfmt feature to deal with that pertaining to comment wrapping.

rust
pub fn atx_heading(
input: &[u8],
) -> IResult<&[u8], ATXHeading, MDXError<&[u8]>> {
let (input, hashes) =
hashtags(input).map_err(Err::convert)?;
if hashes.len() > 6 {
return Err(Error(MDXError::TooManyHashes));
}
let (input, _) = spaces(input).map_err(Err::convert)?;
let (input, val) =
rest_of_line(std::str::from_utf8(input).unwrap())
.map_err(Err::convert)?;
Ok((
input.as_bytes(),
ATXHeading {
level: hashes.len(),
value: val.as_bytes(),
},
))
}