pub fn format<K: TokenKind + Ord>(
tree: &Node<K>,
source: &str,
style: &Style<K>,
width: usize,
) -> Result<String, FormatError>Expand description
Formats the source tree was parsed from, at width columns.
tree must be a lossless tree of source (its tokens, trivia included,
cover a contiguous range of source); it may be a whole file or any
subtree, and may contain error nodes. The output covers the tree’s range.
§Layout
Between every two neighbouring significant tokens (a node named by
Rules::verbatim counts as one token), the formatter asks every rule that
applies to the gap: the left token’s after, the right token’s before,
the after of nodes ending there and the before of nodes starting there,
and the delimiter and separator rules of the node holding both tokens. The
most generous answer wins; if none applies, the source’s whitespace is kept.
Groups and indentation come from the node rules; pretty_lang then picks
the line breaks that fit width.
§Comments
Comments (any trivia token that is not all whitespace) are attached by where they sit in the source:
- trailing: no line break between the comment and the token before it. It stays on that token’s line, after one space.
- leading: the comment started a line. It starts a line in the output, at the indentation of the gap it sits in, keeping up to the configured number of blank lines before it.
- dangling: a leading comment just before the closing delimiter of an
indented body (
Indent::Block). It is indented with the body.
A comment followed by a line break in the source is followed by one in the output, so a line comment always ends its line. Comments never cross a token, so their order is preserved, and their text is written unchanged.
§Errors
A FormatError if the tree’s tokens do not describe source: a span out
of bounds or inside a character, or tokens with gaps or overlaps between
them.
§Examples
use fmt_lang::syntax_lang::{Builder, Span, Token, TokenKind};
use fmt_lang::{format, Rules, Space, TokenRule};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
enum K { Sum, Num, Plus, Ws }
impl TokenKind for K {
fn is_trivia(&self) -> bool { matches!(self, K::Ws) }
}
// `1 +2`, lexed and built by hand.
let source = "1 +2";
let mut b = Builder::new();
b.start_node(K::Sum);
b.token(Token::new(K::Num, Span::new(0, 1)));
b.token(Token::new(K::Ws, Span::new(1, 4)));
b.token(Token::new(K::Plus, Span::new(4, 5)));
b.token(Token::new(K::Num, Span::new(5, 6)));
b.finish_node();
let tree = b.finish()?;
let style = Rules::new()
.final_newline(false)
.token(TokenRule::new("+").around(Space::Single))
.compile(|name| (name == "+").then_some(K::Plus))?;
assert_eq!(format(&tree, source, &style, 80)?, "1 + 2");