Expand description
This crate provides alternative syntax for
write!
, writeln!
, print!
, println!
and format!
macros.
It also introduces macros to print on stderr
.
The names of macros in this crate are formed by
removing the letter r
from their std
counterparts.
Index: examples •
syntax:
"string"
,
()
, []
,
{}
,
for
,
if
,
match
,
=
•
troubleshooting •
macros
§Examples
use fomat_macros::pintln;
fn main() {
pintln!("Hello, World!");
pintln!("Display trait: "(2+2));
pintln!("Debug trait: "[vec![1, 2, 3]]);
pintln!("Multiple " "parameters" (1) " " [2]);
pintln!("Formatting parameters: " {(1./3.):5.2}); // 0.333
pintln!("Debug: "[= 2 + 2]); // Debug: 2 + 2 = 4
}
This crate also contains a small templating language,
allowing you to mix constructs like for
with
the printing syntax. The following should print 1 :: 2 :: 3 :: nil
.
let list = [1, 2, 3];
pintln!( for x in &list { (x) " :: " } "nil" );
You can also use the macros without importing them
fomat_macros::pintln!("2 + 2 = "(2 + 2));
§Syntax overview
All the macros share the same syntax, so it will be described in this section.
The macros take list of things to print as an argument.
Each thing could be either a string literal, something
inside brackets (()
, []
or {}
) or a Rust construct
(for
, if let
, if
or match
). There has to be
no separator (like a comma) between those things.
Whitespace is ignored outside the string literals.
§String literals
String literals will be formatted directly as they are.
Note that this also applies to {
and }
characters.
let s = fomat!("Hi." "{}");
assert_eq!(s, "Hi.{}");
§Expressions in ()
and []
brackets.
Expressions in these brackets will be evaluated and printed using:
Display
trait for(expr)
(equivalent to{}
format).Debug
trait for[expr]
(equivalent to{:?}
format).
Like in std
, they are implicitly borrowed.
let s = fomat!( ("string") (2 + 2) ", " [vec![1]] );
assert_eq!(s, "string4, [1]")
§Curly braces
§write!
passthrough
If you want to use regular format!
syntax for some
part of your string, place format!
arguments
inside the curly braces:
use std::io::Write;
let mut v = vec![];
wite!(v, "foo " {"{} baz {}", "bar", "quux"});
assert_eq!(v, "foo bar baz quux".as_bytes());
§Single argument
If you only want to print a single argument
with a custom format parameters,
you can use the {token_tree:format_parameters}
syntax.
The following will use binary format, zero-aligned to 8 places.
let s = fomat!({13:08b});
assert_eq!(s, "00001101");
Please note that there can be only a single
token tree before the colon – usually
a literal or an identifier. Anything
longer has to be wrapped in parentheses
(like that {(10+3):08b}
).
§For loops
For loops use the regular Rust syntax, except the body will use this printing syntax again.
let list = [1, 2, 3];
let s = fomat!( for x in &list { (x) " :: " } "nil" );
assert_eq!(s, "1 :: 2 :: 3 :: nil");
For loops can also use an optional separator,
denoted by sep
or separated
keyword.
let s = fomat!(
for (i, x) in list.iter().enumerate() { (i) " → " (x) }
separated { ", " }
);
assert_eq!(s, "0 → a, 1 → b");
For loops (and other syntax elements) can also be nested:
let matrix = [[0, 1], [2, 3]];
assert_eq!(
fomat!( for row in &matrix { for x in row { {x:3} } "\n" } ),
" 0 1\n 2 3\n"
);
§If and if let
They use the regular Rust syntax,
except of the body (inside {}
),
which uses the printing syntax.
The benefits of using this syntax instead
of getting if
“outside” of the printing
macros is apparent when the conditional is
a part of a longer string (you don’t
have to split this into three separate write!
s):
let opt = Some(5);
let s = fomat!(
"a\n"
if let Some(x) = opt { (x) "\n" } else { "nothing\n" }
"b\n"
);
assert_eq!(s, "a\n5\nb\n");
The else
clause is optional.
else if
-chaining is not supported. As a workaround,
use else { if ... }
or match
.
§Match
Match uses the regular Rust syntax,
except arms has to use {}
blocks,
which will be interpreted using printing syntax.
let v = [Some(1), None, Some(2)];
let s = fomat!(
for x in &v {
match *x {
Some(x) => { (x) }
None => { "_" }
}
}
);
assert_eq!(s, "1_2");
Match arms should not be separated by commas.
§Debugging shorthand
If you want to print both the expression and the value, place equal sign as a first character in brackets. The trait used to print the value will depend on the kind of brackets used.
let word = "foo";
let arr = [10];
let s = fomat!( (=word) ", " [=&arr] ", " {=5:#b} );
assert_eq!(s, "word = foo, &arr = [10], 5 = 0b101");
§Troubleshooting
§Recursion depth
If you hit the error about recursion depth,
which occurs when you try to print more than
about 50 elements, you can use this workaround
instead of increasing the limit: split everything
into two (or more) dummy if true
blocks.
§Errors in macro parsing
If you hit expected a literal
, that either means
either you’ve made a syntactic mistake
or really a string literal is expected here.
Remember, naked identifiers won’t be printed
unless you put them in parentheses.
Macros§
- epint
- Prints to stderr. Analogous to
eprint!
. - epintln
- Prints to stderr, with an appended newline. Analogous to
eprintln!
. - fomat
- Creates a formatted string. Analogous to
format!
. - lazy_
fomat - Creates a displayable object based on its arguments.
- perr
Deprecated - Same as
epint
- perrln
Deprecated - Same as
epintln
- pint
- Prints to stdout. Analogous to
print!
. - pintln
- Prints to stdout, with an appended newline. Analoguous to
println!
. - wite
- Writes to a specified writer. Analogous to
write!
. - witeln
- Writes to a specified writer, with an appended newline. Analogous to
writeln!
.
Structs§
- Display
Fn - Wrapper implementing Display for every closure with matching signature