m_o/value/
print.rs

1use std::fmt;
2
3use super::Value;
4use crate::value::Arg;
5use pretty::{BoxDoc, Doc};
6
7pub struct PrintOptions {
8    pub indent: usize,
9    pub columns: usize,
10}
11
12impl Default for PrintOptions {
13    fn default() -> Self {
14        PrintOptions {
15            indent: 4,
16            columns: 80,
17        }
18    }
19}
20
21impl<'value> Value<'value> {
22    fn seq_to_doc<'iter, I>(
23        open: &'static str,
24        xs: I,
25        close: &'static str,
26        options: &PrintOptions,
27    ) -> Doc<'value, BoxDoc<'value, ()>>
28    where
29        I: Iterator<Item = Doc<'value, BoxDoc<'value, ()>>>,
30        'value: 'iter,
31    {
32        Doc::text(open)
33            .append(Doc::newline().flat_alt(Doc::nil()))
34            .nest(options.indent)
35            .append(Doc::intersperse(xs, Doc::text(",").append(Doc::space())).nest(options.indent))
36            .append(Doc::newline().flat_alt(Doc::nil()))
37            .append(Doc::text(close))
38            .group()
39    }
40
41    fn dictionary_to_doc<'tmp>(
42        pairs: &'tmp [(Value<'value>, Value<'value>)],
43        options: &PrintOptions,
44    ) -> Doc<'value, BoxDoc<'value, ()>>
45    where
46        'value: 'tmp,
47    {
48        Self::seq_to_doc(
49            "{",
50            pairs.iter().map(|(key, value)| {
51                key.to_doc(options)
52                    .append(Doc::text(": "))
53                    .append(value.to_doc(options))
54            }),
55            "}",
56            options,
57        )
58        .group()
59    }
60
61    fn constructor_to_doc<'tmp>(
62        name: &'value str,
63        args: &'tmp [Arg<'value>],
64        options: &PrintOptions,
65    ) -> Doc<'value, BoxDoc<'value, ()>>
66    where
67        'value: 'tmp,
68    {
69        Doc::text(name)
70            .append(Self::seq_to_doc(
71                "(",
72                args.iter().map(|arg| match arg {
73                    Arg::Arg(value) => value.to_doc(options),
74                    Arg::Kwarg(key, value) => Doc::text(*key)
75                        .append(Doc::text("="))
76                        .append(value.to_doc(options)),
77                }),
78                ")",
79                options,
80            ))
81            .group()
82    }
83}
84
85impl<'value> Value<'value> {
86    pub fn to_doc(&self, options: &PrintOptions) -> Doc<'value, BoxDoc<'value, ()>> {
87        match *self {
88            Value::Int(x) => Doc::text(x.to_string()),
89            Value::Float(x) => Doc::text(x.to_string()),
90            Value::Bool(x) => Doc::text(if x { "True" } else { "False" }),
91            Value::Symbol(x) => Doc::text(x),
92            Value::Str(x) => Doc::text(x),
93            Value::List(ref xs) => {
94                Self::seq_to_doc("[", xs.iter().map(|x| x.to_doc(options)), "]", options)
95            }
96            Value::Tuple(ref xs) => {
97                Self::seq_to_doc("(", xs.iter().map(|x| x.to_doc(options)), ")", options)
98            }
99            Value::Set(ref xs) => {
100                Self::seq_to_doc("{", xs.iter().map(|x| x.to_doc(options)), "}", options)
101            }
102            Value::Dict(ref pairs) => Self::dictionary_to_doc(pairs, options),
103            Value::Constructor(name, ref args) => Self::constructor_to_doc(name, args, options),
104        }
105    }
106}
107
108impl<'a> fmt::Display for Value<'a> {
109    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
110        let options = PrintOptions::default();
111        self.to_doc(&options).render_fmt(options.columns, f)
112    }
113}