use super::{
NUMBER_COLOR, PrettySimple, STRING_CONTENT_COLOR, STRING_QUOTE_COLOR, Writer, escape_string,
format_bracket_list, sub_expr, with_brackets,
};
use crate::format_constructor;
use crate::format_enum;
use crate::format_record;
use crate::types::{
Ann, Binder, Expression, Item, ParamAttr, Parameter, Selector, SimpleSelector, Span,
StringPart, Term, Token, TrailingComment, Trivia, Trivium, Whole,
};
macro_rules! simple_atom {
($ty:ty, |$self_:ident, $w:ident| $body:expr) => {
impl PrettySimple for $ty {
fn format<W: Writer>(&self, $w: &mut W) {
let $self_ = self;
$body
}
fn is_simple(&self) -> bool {
true
}
fn is_atomic(&self) -> bool {
true
}
}
};
}
simple_atom!(&str, |s, w| {
w.write_colored("\"", STRING_QUOTE_COLOR);
w.write_colored(&escape_string(s), STRING_CONTENT_COLOR);
w.write_colored("\"", STRING_QUOTE_COLOR);
});
simple_atom!(String, |s, w| s.as_str().format(w));
simple_atom!(isize, |n, w| w.write_colored(&n.to_string(), NUMBER_COLOR));
simple_atom!(usize, |n, w| w.write_colored(&n.to_string(), NUMBER_COLOR));
simple_atom!(bool, |b, w| w.write_plain(if *b {
"True"
} else {
"False"
}));
impl PrettySimple for Whole<Expression> {
fn format<W: Writer>(&self, w: &mut W) {
self.value.format(w);
w.newline(); }
}
impl PrettySimple for Expression {
fn format<W: Writer>(&self, w: &mut W) {
format_enum!(self, w, {
Term(term) => [term],
With(kw, expr1, semi, expr2) => [kw, &**expr1, semi, &**expr2],
Let(kw, items, in_kw, body) => [kw, &items.0, in_kw, &**body],
Assert(kw, expr1, semi, expr2) => [kw, &**expr1, semi, &**expr2],
If(if_kw, cond, then_kw, then_expr, else_kw, else_expr) => [if_kw, &**cond, then_kw, &**then_expr, else_kw, &**else_expr],
Abstraction(param, colon, body) => [param, colon, &**body],
Application(func, arg) => [&**func, &**arg],
Operation(left, op, right) => [&**left, op, &**right],
MemberCheck(expr, question, selectors) => [&**expr, question, selectors],
Negation(minus, expr) => [minus, &**expr],
Inversion(not, expr) => [not, &**expr],
});
}
}
impl PrettySimple for Term {
fn format<W: Writer>(&self, w: &mut W) {
format_enum!(self, w, {
Token(leaf) => [leaf],
SimpleString(string) => [string],
IndentedString(string) => [string],
Path(path) => [path],
List(open, items, close) => [open, &items.0, close],
Set(rec, open, items, close) => [rec, open, &items.0, close],
Selection(term, selectors, or_default) => [&**term, selectors, or_default],
Parenthesized(open, expr, close) => [open, &**expr, close],
});
}
}
impl<T: PrettySimple> PrettySimple for Item<T> {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::Item(inner) => {
format_constructor!(w, "Item", [inner]);
}
Self::Comments(trivia) => {
w.write_plain("Comments");
sub_expr(w, trivia);
}
}
}
fn is_simple(&self) -> bool {
match self {
Self::Item(_) => false,
Self::Comments(trivia) => trivia.is_simple(),
}
}
}
impl PrettySimple for Binder {
fn format<W: Writer>(&self, w: &mut W) {
format_enum!(self, w, {
Inherit(kw, from, selectors, semi) => [kw, from, selectors, semi],
Assignment(sels, eq, expr, semi) => [sels, eq, expr, semi],
});
}
}
impl PrettySimple for Selector {
fn format<W: Writer>(&self, w: &mut W) {
format_constructor!(w, "Selector", [&self.dot, &self.selector]);
}
}
impl PrettySimple for SimpleSelector {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::ID(leaf) => {
format_constructor!(w, "IDSelector", [leaf]);
}
Self::Interpol(part) => {
format_constructor!(w, "InterpolSelector", [part]);
}
Self::String(string) => {
format_constructor!(w, "StringSelector", [string]);
}
}
}
}
impl PrettySimple for Trivium {
fn format<W: Writer>(&self, w: &mut W) {
format_enum!(self, w, {
EmptyLine() => [],
LineComment(text) => [text],
BlockComment(is_doc, lines) => [is_doc, lines],
LanguageAnnotation(text) => [text],
});
}
fn is_simple(&self) -> bool {
match self {
Self::EmptyLine() | Self::LineComment(_) | Self::LanguageAnnotation(_) => true,
Self::BlockComment(_is_doc, lines) => lines.is_simple(),
}
}
fn is_atomic(&self) -> bool {
matches!(self, Self::EmptyLine())
}
}
impl PrettySimple for Trivia {
fn format<W: Writer>(&self, w: &mut W) {
w.write_plain("fromList");
sub_expr(w, &self.to_vec());
}
fn renders_inline_parens(&self) -> bool {
self.to_vec().is_simple()
}
}
impl PrettySimple for Parameter {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::ID(leaf) => {
format_constructor!(w, "IDParameter", [leaf]);
}
Self::Set(open, attrs, close) => {
format_constructor!(w, "SetParameter", [open, attrs, close]);
}
Self::Context(left, at, right) => {
format_constructor!(w, "ContextParameter", [&**left, at, &**right]);
}
}
}
}
impl PrettySimple for ParamAttr {
fn format<W: Writer>(&self, w: &mut W) {
format_enum!(self, w, {
ParamAttr(name, default, comma) => [name, default, comma],
ParamEllipsis(ellipsis) => [ellipsis],
});
}
}
impl PrettySimple for StringPart {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::TextPart(text) => {
format_constructor!(w, "TextPart", [text]);
}
Self::Interpolation(whole) => {
w.write_plain("Interpolation");
w.write_plain(" ");
whole.value.format(w);
}
}
}
fn is_simple(&self) -> bool {
match self {
Self::TextPart(_) => true,
Self::Interpolation(_) => false,
}
}
}
impl PrettySimple for Token {
fn format<W: Writer>(&self, w: &mut W) {
format_enum!(self, w, {
Integer(s) => [&s.as_str()],
Float(s) => [&s.as_str()],
Identifier(s) => [&s.as_str()],
EnvPath(s) => [&s.as_str()],
_ => {
w.write_plain(&format!("{self:?}"));
}
});
}
fn is_simple(&self) -> bool {
true
}
}
#[derive(Debug)]
struct SpanWrapper(Span);
impl PrettySimple for SpanWrapper {
fn format<W: Writer>(&self, w: &mut W) {
use crate::error::context::ErrorContext;
w.write_plain("Pos ");
let ctx = ErrorContext::new(w.source(), None);
let pos = ctx.position(self.0.start);
pos.line.format(w);
}
fn is_simple(&self) -> bool {
true
}
}
impl PrettySimple for TrailingComment {
fn format<W: Writer>(&self, w: &mut W) {
with_brackets(w, "(", ")", true, |w, _| {
w.write_plain(" ");
format_constructor!(w, "TrailingComment", [&&*self.0]);
w.write_plain(" ");
});
}
fn has_delimiters(&self) -> bool {
true
}
}
impl<T: PrettySimple> PrettySimple for Ann<T> {
fn format<W: Writer>(&self, w: &mut W) {
w.write_plain("Ann");
format_record!(
w,
[
("preTrivia", &self.pre_trivia),
("sourceLine", &SpanWrapper(self.span)),
("value", &self.value),
("trailComment", &self.trail_comment),
]
);
}
}
impl<T: PrettySimple> PrettySimple for Vec<T> {
fn format<W: Writer>(&self, w: &mut W) {
format_bracket_list(w, self, true);
}
fn is_simple(&self) -> bool {
if self.is_empty() {
return true;
}
if self.len() == 1 {
let item = &self[0];
return item.is_atomic() || (item.is_simple() && item.has_delimiters());
}
false
}
fn has_delimiters(&self) -> bool {
true
}
fn is_empty(&self) -> bool {
<Self>::is_empty(self)
}
}
impl<T: PrettySimple> PrettySimple for Option<T> {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Some(value) => {
format_constructor!(w, "Just", [value]);
}
None => {
w.write_plain("Nothing");
}
}
}
fn is_simple(&self) -> bool {
self.is_none()
}
}
impl<A: PrettySimple, B: PrettySimple> PrettySimple for (A, B) {
fn format<W: Writer>(&self, w: &mut W) {
with_brackets(w, "(", ")", true, |w, paren_color| {
w.write_plain(" ");
self.0.format(w);
w.newline();
w.write_colored(",", paren_color);
w.write_plain(" ");
self.1.format(w);
w.newline();
});
}
fn has_delimiters(&self) -> bool {
true
}
}
impl<T: PrettySimple> PrettySimple for Box<T> {
fn format<W: Writer>(&self, w: &mut W) {
(**self).format(w);
}
fn is_simple(&self) -> bool {
(**self).is_simple()
}
}