Crate tiny_pretty
source ·Expand description
Tiny implementation of Wadler-style pretty printing algorithm.
§Basic Usage
Supposed we’re going to print a code snippet of function calls, and we already have data structure defined as:
struct FunctionCall {
name: String,
args: Vec<FunctionCall>,
}
We may have a function call that is very very long, so we need to pretty print it for better readability. Our function call may behave like:
let fn_call = FunctionCall {
name: "foo".into(),
args: vec![
FunctionCall { name: "really_long_arg".into(), args: vec![] },
FunctionCall { name: "omg_so_many_parameters".into(), args: vec![] },
FunctionCall { name: "we_should_refactor_this".into(), args: vec![] },
FunctionCall { name: "is_there_seriously_another_one".into(), args: vec![] },
],
};
(This example is copied from Prettier with modifications.)
Now we’re going to implement about building Doc
from the data structure above.
We expect arguments should be placed on a single line as possible.
If they’re too long to fit, we insert line break with indentation:
- When being on a single line, there’re no spaces after left paren and before right paren, and there must be a space after each argument comma.
- When being splitted into different lines, there must be indentation when printing arguments, and there must be a line break between arguments.
So, we can build Doc
like this:
use itertools::Itertools;
use tiny_pretty::Doc;
fn build_doc(fn_call: &FunctionCall) -> Doc {
Doc::text(&fn_call.name)
.append(Doc::text("("))
.append(
Doc::line_or_nil()
.append(Doc::list(Itertools::intersperse(
fn_call.args.iter().map(build_doc),
Doc::text(",").append(Doc::line_or_space())
).collect()))
.nest(2)
.append(Doc::line_or_nil())
.group()
)
.append(Doc::text(")"))
}
Once we have a Doc
, we can pretty print it:
use tiny_pretty::{print, PrintOptions};
assert_eq!(r#"
foo(
really_long_arg(),
omg_so_many_parameters(),
we_should_refactor_this(),
is_there_seriously_another_one()
)"#.trim(), &print(&build_doc(&fn_call), &PrintOptions::default()));
Besides, if we have a function call which is short enough to fit on single line:
use tiny_pretty::{print, PrintOptions};
let fn_call = FunctionCall {
name: "foo".into(),
args: vec![
FunctionCall { name: "a".into(), args: vec![] },
FunctionCall { name: "b".into(), args: vec![] },
FunctionCall { name: "c".into(), args: vec![] },
FunctionCall { name: "d".into(), args: vec![] },
],
};
assert_eq!(
"foo(a(), b(), c(), d())",
&print(&build_doc(&fn_call), &PrintOptions::default()),
);
You can specify advanced printing options, such as controlling line break and
indentation kind. See PrintOptions
for details.
§Text Width Measurement
By default, text width is measured as “visual width”. This strategy makes it satisfy the width limitation visually.
But sometimes for some Unicode characters, you may want the column to
be close to width limitation as possible, though it will exceed visually.
To achieve that, please enable the unicode-width
feature gate.
Structs§
- Print control options, such as line break and indentation kind.
Enums§
- The data structure that describes about pretty printing.
Functions§
- Pretty print a doc.