1use std::fmt::Write;
7use std::str;
8
9pub const DEFAULT_WIDTH: usize = 80;
11
12pub trait Emittable: std::fmt::Debug {
14 fn write_on(&self, f: &mut Formatter);
16}
17
18#[derive(Clone, PartialEq, Eq)]
20pub enum VerticalMode {
21 Variable,
22 Normal,
23 ExtraNewline,
24}
25
26pub trait Vertical {
28 fn set_vertical_mode(&mut self, mode: VerticalMode);
29 fn write_vertically_on(&self, f: &mut Formatter);
30}
31
32pub type Item = std::rc::Rc<dyn Emittable>;
34
35#[derive(Clone)]
37pub struct Sequence {
38 pub items: Vec<Item>,
39 pub vertical_mode: VerticalMode,
40 pub separator: &'static str,
41 pub terminator: &'static str,
42}
43
44#[derive(Clone)]
47pub struct Grouping {
48 pub sequence: Sequence,
49 pub open: &'static str,
50 pub close: &'static str,
51}
52
53pub struct Formatter {
55 pub width: usize,
57 indent_delta: String,
58 current_indent: String,
59 pub buffer: String,
61}
62
63impl Formatter {
64 pub fn new() -> Self {
66 Formatter {
67 width: DEFAULT_WIDTH,
68 indent_delta: " ".to_owned(),
69 current_indent: "\n".to_owned(),
70 buffer: String::new(),
71 }
72 }
73
74 pub fn copy_empty(&self) -> Formatter {
76 Formatter {
77 width: self.width,
78 indent_delta: self.indent_delta.clone(),
79 current_indent: self.current_indent.clone(),
80 buffer: String::new(),
81 }
82 }
83
84 pub fn indent_size(self) -> usize {
86 self.indent_delta.len()
87 }
88
89 pub fn set_indent_size(&mut self, n: usize) {
91 self.indent_delta = str::repeat(" ", n)
92 }
93
94 pub fn write<E: Emittable>(&mut self, e: E) {
96 e.write_on(self)
97 }
98
99 pub fn newline(&mut self) {
101 self.buffer.push_str(&self.current_indent)
102 }
103
104 pub fn to_string<E: Emittable>(e: E) -> String {
107 let mut f = Formatter::new();
108 f.write(e);
109 f.buffer
110 }
111
112 pub fn with_indent<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R {
116 let old_indent = self.current_indent.clone();
117 self.current_indent += &self.indent_delta;
118 let r = f(self);
119 self.current_indent = old_indent;
120 r
121 }
122}
123
124impl Default for Formatter {
125 fn default() -> Self {
126 Self::new()
127 }
128}
129
130impl Default for VerticalMode {
131 fn default() -> Self {
132 Self::Variable
133 }
134}
135
136impl Emittable for &str {
139 fn write_on(&self, f: &mut Formatter) {
140 f.buffer.push_str(self)
141 }
142}
143
144impl Emittable for String {
145 fn write_on(&self, f: &mut Formatter) {
146 f.write(self.as_str())
147 }
148}
149
150impl<'a, E: Emittable> Emittable for &'a Vec<E>
151where
152 &'a E: Emittable,
153{
154 fn write_on(&self, f: &mut Formatter) {
155 for e in self.iter() {
156 f.write(e)
157 }
158 }
159}
160
161impl Emittable for Sequence {
162 fn write_on(&self, f: &mut Formatter) {
163 if self.vertical_mode != VerticalMode::Variable {
164 self.write_vertically_on(f)
165 } else {
166 let mut need_sep = false;
167 for e in self.items.iter() {
168 if need_sep {
169 self.separator.write_on(f)
170 } else {
171 need_sep = true
172 }
173 e.write_on(f)
174 }
175 if !self.items.is_empty() {
176 self.terminator.write_on(f)
177 }
178 }
179 }
180}
181
182impl Vertical for Sequence {
183 fn set_vertical_mode(&mut self, vertical_mode: VerticalMode) {
184 self.vertical_mode = vertical_mode;
185 }
186
187 fn write_vertically_on(&self, f: &mut Formatter) {
188 let mut i = self.items.len();
189 let mut first = true;
190 for e in self.items.iter() {
191 if !first {
192 if self.vertical_mode == VerticalMode::ExtraNewline {
193 f.write("\n");
194 }
195 f.newline();
196 }
197 first = false;
198 e.write_on(f);
199 let delim = if i == 1 {
200 self.terminator
201 } else {
202 self.separator
203 };
204 delim
205 .trim_end_matches(|c: char| c.is_whitespace() && c != '\n')
206 .write_on(f);
207 i = i - 1;
208 }
209 }
210}
211
212impl Emittable for Grouping {
213 fn write_on(&self, f: &mut Formatter) {
214 if self.sequence.vertical_mode != VerticalMode::Variable {
215 self.write_vertically_on(f)
216 } else {
217 let mut g = f.copy_empty();
218 self.open.write_on(&mut g);
219 g.write(&self.sequence);
220 self.close.write_on(&mut g);
221 let s = g.buffer;
222 if s.len() <= f.width {
223 f.write(&s)
224 } else {
225 self.write_vertically_on(f)
226 }
227 }
228 }
229}
230
231impl Vertical for Grouping {
232 fn set_vertical_mode(&mut self, vertical_mode: VerticalMode) {
233 self.sequence.set_vertical_mode(vertical_mode);
234 }
235
236 fn write_vertically_on(&self, f: &mut Formatter) {
237 self.open.write_on(f);
238 if !self.sequence.items.is_empty() {
239 f.with_indent(|f| {
240 f.newline();
241 self.sequence.write_vertically_on(f)
242 });
243 f.newline()
244 }
245 self.close.write_on(f);
246 }
247}
248
249impl<'a, E: Emittable> Emittable for &'a E {
250 fn write_on(&self, f: &mut Formatter) {
251 (*self).write_on(f)
252 }
253}
254
255impl Emittable for Item {
256 fn write_on(&self, f: &mut Formatter) {
257 (**self).write_on(f)
258 }
259}
260
261impl std::fmt::Debug for Sequence {
262 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
263 f.write_str(&Formatter::to_string(self))
264 }
265}
266
267impl std::fmt::Debug for Grouping {
268 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
269 f.write_str(&Formatter::to_string(self))
270 }
271}
272
273pub fn escape_string(s: &str) -> String {
282 let mut buf = String::new();
283 buf.push('"');
284 for c in s.chars() {
285 match c {
286 '\\' => buf.push_str("\\\\"),
287 '"' => buf.push_str("\\\""),
288 _ if c >= ' ' && c <= '~' => buf.push(c),
289 _ => write!(&mut buf, "\\u{{{:x}}}", c as i32).expect("no IO errors building a string"),
290 }
291 }
292 buf.push('"');
293 buf
294}
295
296pub fn escape_bytes(bs: &[u8]) -> String {
304 let mut buf = String::new();
305 buf.push_str("b\"");
306 for b in bs {
307 let c = *b as char;
308 match c {
309 '\\' => buf.push_str("\\\\"),
310 '"' => buf.push_str("\\\""),
311 _ if c >= ' ' && c <= '~' => buf.push(c),
312 _ => write!(&mut buf, "\\x{:02x}", b).expect("no IO errors building a string"),
313 }
314 }
315 buf.push('"');
316 buf
317}
318
319pub mod constructors {
323 use super::Emittable;
324 use super::Grouping;
325 use super::Item;
326 use super::Sequence;
327 use super::Vertical;
328 use super::VerticalMode;
329
330 pub fn item<E: 'static + Emittable>(i: E) -> Item {
332 std::rc::Rc::new(i)
333 }
334
335 pub fn name(pieces: Vec<Item>) -> Sequence {
337 Sequence {
338 items: pieces,
339 vertical_mode: VerticalMode::default(),
340 separator: "::",
341 terminator: "",
342 }
343 }
344
345 pub fn seq(items: Vec<Item>) -> Sequence {
347 Sequence {
348 items: items,
349 vertical_mode: VerticalMode::default(),
350 separator: "",
351 terminator: "",
352 }
353 }
354
355 pub fn commas(items: Vec<Item>) -> Sequence {
357 Sequence {
358 items: items,
359 vertical_mode: VerticalMode::default(),
360 separator: ", ",
361 terminator: "",
362 }
363 }
364
365 pub fn parens(items: Vec<Item>) -> Grouping {
367 Grouping {
368 sequence: commas(items),
369 open: "(",
370 close: ")",
371 }
372 }
373
374 pub fn brackets(items: Vec<Item>) -> Grouping {
376 Grouping {
377 sequence: commas(items),
378 open: "[",
379 close: "]",
380 }
381 }
382
383 pub fn anglebrackets(items: Vec<Item>) -> Grouping {
385 Grouping {
386 sequence: commas(items),
387 open: "<",
388 close: ">",
389 }
390 }
391
392 pub fn braces(items: Vec<Item>) -> Grouping {
394 Grouping {
395 sequence: commas(items),
396 open: "{",
397 close: "}",
398 }
399 }
400
401 pub fn block(items: Vec<Item>) -> Grouping {
403 Grouping {
404 sequence: Sequence {
405 items: items,
406 vertical_mode: VerticalMode::default(),
407 separator: " ",
408 terminator: "",
409 },
410 open: "{",
411 close: "}",
412 }
413 }
414
415 pub fn codeblock(items: Vec<Item>) -> Grouping {
417 vertical(false, block(items))
418 }
419
420 pub fn semiblock(items: Vec<Item>) -> Grouping {
422 Grouping {
423 sequence: Sequence {
424 items: items,
425 vertical_mode: VerticalMode::default(),
426 separator: "; ",
427 terminator: "",
428 },
429 open: "{",
430 close: "}",
431 }
432 }
433
434 pub fn vertical<V: Vertical>(spaced: bool, mut v: V) -> V {
438 v.set_vertical_mode(if spaced {
439 VerticalMode::ExtraNewline
440 } else {
441 VerticalMode::Normal
442 });
443 v
444 }
445
446 pub fn indented(sequence: Sequence) -> Grouping {
448 Grouping {
449 sequence,
450 open: "",
451 close: "",
452 }
453 }
454}
455
456pub mod macros {
460 #[macro_export]
464 macro_rules! name {
465 ($($item:expr),*) => {$crate::syntax::block::constructors::name(vec![$(std::rc::Rc::new($item)),*])}
466 }
467
468 #[macro_export]
472 macro_rules! seq {
473 ($($item:expr),*) => {$crate::syntax::block::constructors::seq(vec![$(std::rc::Rc::new($item)),*])}
474 }
475
476 #[macro_export]
480 macro_rules! commas {
481 ($($item:expr),*) => {$crate::syntax::block::constructors::commas(vec![$(std::rc::Rc::new($item)),*])}
482 }
483
484 #[macro_export]
488 macro_rules! parens {
489 ($($item:expr),*) => {$crate::syntax::block::constructors::parens(vec![$(std::rc::Rc::new($item)),*])}
490 }
491
492 #[macro_export]
496 macro_rules! brackets {
497 ($($item:expr),*) => {$crate::syntax::block::constructors::brackets(vec![$(std::rc::Rc::new($item)),*])}
498 }
499
500 #[macro_export]
504 macro_rules! anglebrackets {
505 ($($item:expr),*) => {$crate::syntax::block::constructors::anglebrackets(vec![$(std::rc::Rc::new($item)),*])}
506 }
507
508 #[macro_export]
512 macro_rules! braces {
513 ($($item:expr),*) => {$crate::syntax::block::constructors::braces(vec![$(std::rc::Rc::new($item)),*])}
514 }
515
516 #[macro_export]
520 macro_rules! block {
521 ($($item:expr),*) => {$crate::syntax::block::constructors::block(vec![$(std::rc::Rc::new($item)),*])}
522 }
523
524 #[macro_export]
527 macro_rules! codeblock {
528 ($($item:expr),*) => {$crate::syntax::block::constructors::codeblock(vec![$(std::rc::Rc::new($item)),*])}
529 }
530
531 #[macro_export]
535 macro_rules! semiblock {
536 ($($item:expr),*) => {$crate::syntax::block::constructors::semiblock(vec![$(std::rc::Rc::new($item)),*])}
537 }
538}