1#![warn(missing_docs)]
2
3#[allow(missing_docs)]
8mod buffer;
9#[allow(missing_docs)]
10mod format_element;
11#[allow(missing_docs)]
12mod formatter;
13#[allow(missing_docs)]
14mod macros;
15#[allow(missing_docs)]
17pub mod prelude;
18#[allow(missing_docs)]
19mod printer;
20
21pub use crate::buffer::{Buffer, VecBuffer};
23pub use crate::format_element::{
25 Document, FormatElement, LineMode, best_fit, group, hard_line_break, indent, soft_line_break,
26 soft_line_break_or_space, space, text, token, verbatim,
27};
28pub use crate::formatter::{
30 Format, FormatContext, FormatError, FormatOptions, FormatResult, Formatted, Formatter,
31 SimpleFormatContext, SimpleFormatOptions,
32};
33pub use crate::printer::{IndentStyle, LineEnding, PrintError, Printed, Printer, PrinterOptions};
35
36#[cfg(test)]
37mod tests {
38 use crate::prelude::*;
39 use crate::{SimpleFormatContext, SimpleFormatOptions, format};
40
41 #[test]
42 fn prints_indented_hard_lines() {
43 let context = SimpleFormatContext::new(SimpleFormatOptions::default());
44 let doc = Document::from_elements(vec![
45 text("if"),
46 hard_line_break(),
47 indent(Document::from_elements(vec![
48 text("echo hi"),
49 hard_line_break(),
50 text("echo bye"),
51 ])),
52 ]);
53
54 let printed = format!(context, [doc]).unwrap().print().unwrap();
55 assert_eq!(printed.as_code(), "if\n\techo hi\n\techo bye");
56 }
57
58 #[test]
59 fn group_flattens_when_content_fits() {
60 let context = SimpleFormatContext::new(SimpleFormatOptions::default());
61 let doc = Document::from_element(group(Document::from_elements(vec![
62 text("echo"),
63 soft_line_break_or_space(),
64 text("hello"),
65 ])));
66
67 let printed = format!(context, [doc]).unwrap().print().unwrap();
68 assert_eq!(printed.as_code(), "echo hello");
69 }
70
71 #[test]
72 fn group_expands_when_content_overflows() {
73 let mut options = SimpleFormatOptions::default();
74 options.printer_options.line_width = 8;
75 let context = SimpleFormatContext::new(options);
76 let doc = Document::from_element(group(Document::from_elements(vec![
77 text("echo"),
78 soft_line_break_or_space(),
79 text("long-value"),
80 ])));
81
82 let printed = format!(context, [doc]).unwrap().print().unwrap();
83 assert_eq!(printed.as_code(), "echo\nlong-value");
84 }
85
86 #[test]
87 fn best_fit_chooses_expanded_variant() {
88 let mut options = SimpleFormatOptions::default();
89 options.printer_options.line_width = 6;
90 let context = SimpleFormatContext::new(options);
91 let doc = Document::from_element(best_fit(
92 Document::from_elements(vec![text("alpha"), space(), text("beta")]),
93 Document::from_elements(vec![text("alpha"), hard_line_break(), text("beta")]),
94 ));
95
96 let printed = format!(context, [doc]).unwrap().print().unwrap();
97 assert_eq!(printed.as_code(), "alpha\nbeta");
98 }
99
100 #[test]
101 fn group_expands_for_wide_unicode_text() {
102 let mut options = SimpleFormatOptions::default();
103 options.printer_options.line_width = 3;
104 let context = SimpleFormatContext::new(options);
105 let doc = Document::from_element(group(Document::from_elements(vec![
106 text("a"),
107 soft_line_break_or_space(),
108 text("界"),
109 ])));
110
111 let printed = format!(context, [doc]).unwrap().print().unwrap();
112 assert_eq!(printed.as_code(), "a\n界");
113 }
114
115 #[test]
116 fn hard_lines_use_configured_crlf_endings() {
117 let mut options = SimpleFormatOptions::default();
118 options.printer_options.line_ending = LineEnding::CrLf;
119 let context = SimpleFormatContext::new(options);
120 let doc = Document::from_elements(vec![token("a"), hard_line_break(), token("b")]);
121
122 let printed = format!(context, [doc]).unwrap().print().unwrap();
123 assert_eq!(printed.as_code(), "a\r\nb");
124 }
125
126 #[test]
127 fn verbatim_preserves_source_text() {
128 let context = SimpleFormatContext::new(SimpleFormatOptions::default());
129 let doc = Document::from_elements(vec![
130 text("begin"),
131 hard_line_break(),
132 verbatim(" raw\ntext"),
133 ]);
134
135 let printed = format!(context, [doc]).unwrap().print().unwrap();
136 assert_eq!(printed.as_code(), "begin\n raw\ntext");
137 }
138
139 #[test]
140 fn nested_groups_and_indents_expand_consistently() {
141 let mut options = SimpleFormatOptions::default();
142 options.printer_options.line_width = 8;
143 let context = SimpleFormatContext::new(options);
144 let doc = Document::from_element(group(Document::from_elements(vec![
145 token("if"),
146 soft_line_break_or_space(),
147 token("true"),
148 token(";"),
149 soft_line_break(),
150 indent(Document::from_elements(vec![
151 token("echo"),
152 soft_line_break_or_space(),
153 token("long-value"),
154 ])),
155 ])));
156
157 let printed = format!(context, [doc]).unwrap().print().unwrap();
158 assert_eq!(printed.as_code(), "if\ntrue;\n\techo\n\tlong-value");
159 }
160
161 #[test]
162 fn indents_with_spaces_when_configured() {
163 let mut options = SimpleFormatOptions::default();
164 options.printer_options.indent_style = IndentStyle::Space;
165 options.printer_options.indent_width = 2;
166 let context = SimpleFormatContext::new(options);
167 let doc = Document::from_elements(vec![
168 token("if"),
169 hard_line_break(),
170 indent(Document::from_elements(vec![
171 token("echo hi"),
172 hard_line_break(),
173 token("echo bye"),
174 ])),
175 ]);
176
177 let printed = format!(context, [doc]).unwrap().print().unwrap();
178 assert_eq!(printed.as_code(), "if\n echo hi\n echo bye");
179 }
180}