1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#[derive(Clone, Debug, Default)]
pub enum LineBreak {
#[default]
Lf,
Crlf,
}
#[derive(Clone, Debug, Default)]
pub enum IndentKind {
#[default]
Space,
Tab,
}
#[derive(Clone, Debug)]
/// Print control options, such as line break and indentation kind.
pub struct PrintOptions {
/// Line break for each line. It can be "\n" (LF) or "\r\n" (CRLF).
///
/// Default value is LF.
///
/// ```
/// use tiny_pretty::{print, Doc, LineBreak, PrintOptions};
///
/// let doc = Doc::list(vec![Doc::text("a"), Doc::hard_line(), Doc::text("b")]);
///
/// let options = PrintOptions {
/// line_break: LineBreak::Lf,
/// ..Default::default()
/// };
/// assert_eq!("a\nb", &print(&doc, &options));
///
/// let options = PrintOptions {
/// line_break: LineBreak::Crlf,
/// ..Default::default()
/// };
/// assert_eq!("a\r\nb", &print(&doc, &options));
/// ```
pub line_break: LineBreak,
/// To use space or tab for indentation.
///
/// Note that when using tabs and calling [`nest`](crate::Doc::nest) with offset,
/// it doesn't mean it will print tabs with the number of offset.
/// Of course, it will print tabs as possible, however if `indent % tab_size != 0`,
/// it will print tabs first and then fill with spaces to match indentation.
/// Specifically, it prints `indent / tab_size` times tabs
/// then prints `indent % tab_size` times spaces.
/// See the documentation and examples of the [`tab_size`](PrintOptions::tab_size) option below.
///
/// Default value is space.
///
/// ```
/// use tiny_pretty::{print, Doc, IndentKind, PrintOptions};
///
/// let doc = Doc::list(vec![Doc::text("a"), Doc::hard_line().nest(2), Doc::text("b")]);
///
/// let options = PrintOptions {
/// indent_kind: IndentKind::Space,
/// ..Default::default()
/// };
/// assert_eq!("a\n b", &print(&doc, &options));
///
/// let options = PrintOptions {
/// indent_kind: IndentKind::Tab,
/// ..Default::default()
/// };
/// assert_eq!("a\n\tb", &print(&doc, &options));
/// ```
pub indent_kind: IndentKind,
/// The limitation that pretty printer should *(but not must)* avoid columns exceeding.
/// Pretty printer will try its best to keep column width less than this value,
/// but it may exceed for some cases, for example, a very very long single word.
///
/// Default value is 80.
///
/// ```
/// use tiny_pretty::{print, Doc, PrintOptions};
///
/// let doc = Doc::list(vec![Doc::text("aaaa"), Doc::line_or_space(), Doc::text("bbbb")]).group();
/// let options = PrintOptions {
/// width: 5,
/// ..Default::default()
/// };
/// assert_eq!("aaaa\nbbbb", &print(&doc, &options));
///
/// let options = PrintOptions {
/// width: 20,
/// ..Default::default()
/// };
/// assert_eq!("aaaa bbbb", &print(&doc, &options));
///
/// let doc = Doc::list(vec![Doc::text("aaaaaaaa"), Doc::line_or_space(), Doc::text("bbbbbbbb")])
/// .group();
/// assert_eq!("aaaaaaaa\nbbbbbbbb", &print(&doc, &PrintOptions {
/// width: 5,
/// ..Default::default()
/// }));
/// ```
pub width: usize,
/// Tab size is not indentation size.
/// If `indent_kind` is set to `Tab`, when indentation level satisfies the `tab_size`,
/// it will convert those spaces to tabs.
///
/// If you're implementing a high-level formatter or pretty printer,
/// it's highly recommended to set this value as same as indentation size of your
/// formatter or pretty printer.
///
/// Default value is 2. It can't be zero.
/// This option will be ignored when `indent_kind` is `Space`.
///
/// ```
/// use tiny_pretty::{print, Doc, IndentKind, PrintOptions};
///
/// let doc = Doc::list(vec![Doc::text("aaaa"), Doc::hard_line(), Doc::text("bbbb")])
/// .group()
/// .nest(8);
///
/// let options = PrintOptions {
/// indent_kind: IndentKind::Tab,
/// tab_size: 5,
/// ..Default::default()
/// };
/// assert_eq!("aaaa\n\t bbbb", &print(&doc, &options));
///
/// let options = PrintOptions {
/// indent_kind: IndentKind::Tab,
/// tab_size: 4,
/// ..Default::default()
/// };
/// assert_eq!("aaaa\n\t\tbbbb", &print(&doc, &options));
///
/// let options = PrintOptions {
/// indent_kind: IndentKind::Space,
/// tab_size: 5,
/// ..Default::default()
/// };
/// assert_eq!("aaaa\n bbbb", &print(&doc, &options));
/// ```
pub tab_size: usize,
}
impl Default for PrintOptions {
fn default() -> Self {
Self {
line_break: Default::default(),
indent_kind: Default::default(),
width: 80,
tab_size: 2,
}
}
}