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
#[derive(Debug)]
pub enum Token {
Literal(char),
/// `?`
Any,
/// `*`
ZeroOrMore,
/// `{`
StartAlternative,
/// `,`
NextAlternative,
/// `}`
EndAlternative,
/// `[`
StartClass,
/// `!`
NegateClass,
/// `]`
EndClass,
ClassContent(char),
}
impl Token {
/// Append a regex representation of Token to the supplied pattern string
pub fn append_regex(&self, pattern: &mut String, is_first_in_component: bool) {
match self {
Token::Literal(c) => pattern.push_str(®ex::escape(&c.to_string())),
// `?` matches any single character, except for `.` at the start of
// a filename.
Token::Any => {
if is_first_in_component {
#[cfg(not(windows))]
pattern.push_str("[^./]");
#[cfg(windows)]
pattern.push_str("[^./\\\\]");
} else {
#[cfg(not(windows))]
pattern.push_str("[^/]");
#[cfg(windows)]
pattern.push_str("[^/\\\\]");
}
}
// `*` matches 0 or more of any character,
// except for `.` at the start of a filename.
Token::ZeroOrMore => {
if is_first_in_component {
#[cfg(not(windows))]
pattern.push_str("[^./][^/]*");
#[cfg(windows)]
pattern.push_str("[^./\\\\][^/\\\\]*");
} else {
#[cfg(not(windows))]
pattern.push_str("[^/]*");
#[cfg(windows)]
pattern.push_str("[^/\\\\]*");
}
}
Token::StartAlternative => pattern.push('('),
Token::NextAlternative => pattern.push('|'),
Token::EndAlternative => pattern.push(')'),
Token::StartClass => pattern.push('['),
Token::NegateClass => pattern.push('^'),
Token::EndClass => pattern.push(']'),
Token::ClassContent(c) => pattern.push(*c),
}
}
}