1use std::io::Read;
19
20use tabnas_css::{Css, Options};
21
22fn main() {
23 let mut options = Options::default();
24 let mut lines = false;
25 for arg in std::env::args().skip(1) {
26 match arg.as_str() {
27 "--position" => options.position = true,
28 "--lowercase-properties" => options.lowercase_properties = true,
29 "--lines" => lines = true,
30 other => {
31 eprintln!("parse: unknown argument {other:?}");
32 eprintln!("usage: parse [--position] [--lowercase-properties] [--lines]");
33 std::process::exit(2);
34 }
35 }
36 }
37
38 let mut input = String::new();
39 if std::io::stdin().read_to_string(&mut input).is_err() {
40 eprintln!("parse: stdin is not valid UTF-8");
41 std::process::exit(2);
42 }
43
44 let css = Css::with_options(options);
45 if lines {
46 let mut rows: Vec<&str> = input.split('\n').collect();
50 if Some(&"") == rows.last() {
51 rows.pop();
52 }
53 for line in rows {
54 println!("{}", report(&css, &decode(line)));
55 }
56 } else {
57 println!("{}", report(&css, &input));
58 }
59}
60
61fn report(css: &Css, src: &str) -> String {
62 match css.parse(src) {
63 Ok(ast) => ast.to_json(),
64 Err(err) => format!("ERROR:{}", err.code),
65 }
66}
67
68fn decode(line: &str) -> String {
70 let mut out = String::with_capacity(line.len());
71 let mut chars = line.chars();
72 while let Some(c) = chars.next() {
73 if '\\' != c {
74 out.push(c);
75 continue;
76 }
77 match chars.next() {
78 Some('n') => out.push('\n'),
79 Some('r') => out.push('\r'),
80 Some('t') => out.push('\t'),
81 Some('\\') => out.push('\\'),
82 Some(other) => {
83 out.push('\\');
84 out.push(other);
85 }
86 None => out.push('\\'),
87 }
88 }
89 out
90}