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
use std::collections::BTreeMap;
use std::io::Read;
use tree_sitter::{Parser, Language, Tree, Node};
use regex::Regex;
mod error;
mod parser;
mod resolver;
mod style;
use crate::error::{BoxedError, Error};
pub use crate::style::{Style, Colour, StyleBuilder, Setting};
pub use resolver::Context;
extern "C" {
fn tree_sitter_syncat_stylesheet() -> Language;
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
enum SelectorSegment {
Any,
Kind(String),
Token(String),
TokenPattern(String),
DirectChild(Box<SelectorSegment>),
BranchCheck(Vec<SelectorSegment>),
NoChildren(Box<SelectorSegment>),
}
impl SelectorSegment {
pub fn score(&self) -> (usize, usize) {
use SelectorSegment::*;
match self {
Any => (0, 0),
Kind(..) => (0, 1),
Token(..) => (1, 0),
TokenPattern(..) => (1, 0),
DirectChild(child) => child.score(),
BranchCheck(child) => child.iter().map(SelectorSegment::score).fold((0, 0), |(a, b), (c, d)| (a + c, b + d)),
NoChildren(..) => (1, 0),
}
}
}
#[derive(Default, Debug)]
pub struct Stylesheet {
style: StyleBuilder,
scopes: BTreeMap<SelectorSegment, Stylesheet>,
}
impl Stylesheet {
pub fn from_reader<R: Read>(input: &mut R) -> Result<Stylesheet, BoxedError> {
let mut parser = Parser::new();
unsafe {
parser.set_language(tree_sitter_syncat_stylesheet()).unwrap();
}
let mut source = String::new();
input.read_to_string(&mut source).map_err(Box::new)?;
let tree = parser.parse(&source, None).unwrap();
Stylesheet::parse(&source, tree)
}
}
impl std::str::FromStr for Stylesheet {
type Err = BoxedError;
fn from_str(input: &str) -> Result<Stylesheet, BoxedError> {
let mut parser = Parser::new();
unsafe {
parser.set_language(tree_sitter_syncat_stylesheet()).unwrap();
}
let tree = parser.parse(input, None).unwrap();
Stylesheet::parse(input, tree)
}
}