Struct broot::pattern::PatternParts
source · pub struct PatternParts { /* private fields */ }
Expand description
An intermediate parsed representation of the raw string
Implementations§
source§impl PatternParts
impl PatternParts
sourcepub fn push(&mut self, c: char)
pub fn push(&mut self, c: char)
Examples found in repository?
src/command/parts.rs (line 53)
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
pub fn from<S: Into<String>>(raw: S) -> Self {
let mut raw = raw.into();
let mut invocation_start_pos: Option<usize> = None;
let mut pt = BeTree::new();
let mut chars = raw.char_indices().peekable();
let mut escape_cur_char = false;
let mut escape_next_char = false;
// we loop on chars and build the pattern tree until we reach an unescaped ' ' or ':'
while let Some((pos, cur_char)) = chars.next() {
let between_slashes = pt.current_atom()
.map_or(
false,
|pp: &PatternParts| pp.is_between_slashes(),
);
match cur_char {
c if escape_cur_char => {
// Escaping is used to prevent characters from being consumed at the
// composite pattern level (or, and, parens) or as the separator between
// the pattern and the verb. An escaped char is usable in a pattern atom.
pt.mutate_or_create_atom(PatternParts::default).push(c);
}
'\\' => {
// Pattern escaping rules:
// - when after '/': only ' ', ':', '/' and '\' need escaping
// - otherwise, '&,' '|', '(', ')' need escaping too ('(' is only here for
// symmetry)
let between_slashes = match pt.current_atom() {
Some(pattern_parts) => pattern_parts.is_between_slashes(),
None => false,
};
escape_next_char = match chars.peek() {
None => false, // End of the string, we can't be escaping
Some((_, next_char)) => match (next_char, between_slashes) {
(' ' | ':' | '/' | '\\', _) => true,
('&' | '|' | '!' | '(' | ')', false) => true,
_ => false,
}
};
if !escape_next_char {
// if the '\' isn't used for escaping, it's used as its char value
pt.mutate_or_create_atom(PatternParts::default).push('\\');
}
}
' ' | ':' => { // ending the pattern part
invocation_start_pos = Some(pos);
break;
}
'/' => { // starting an atom part
pt.mutate_or_create_atom(PatternParts::default).add_part();
}
'|' if !between_slashes && pt.accept_binary_operator() => {
pt.push_operator(PatternOperator::Or);
}
'&' if !between_slashes && pt.accept_binary_operator() => {
pt.push_operator(PatternOperator::And);
}
'!' if !between_slashes && pt.accept_unary_operator() => {
pt.push_operator(PatternOperator::Not);
}
'(' if !between_slashes && pt.accept_opening_par() => {
pt.open_par();
}
')' if !between_slashes && pt.accept_closing_par() => {
pt.close_par();
}
_ => {
pt.mutate_or_create_atom(PatternParts::default).push(cur_char);
}
}
escape_cur_char = escape_next_char;
escape_next_char = false;
}
let mut verb_invocation = None;
if let Some(pos) = invocation_start_pos {
verb_invocation = Some(VerbInvocation::from(&raw[pos + 1..]));
raw.truncate(pos);
}
CommandParts {
raw_pattern: raw,
pattern: pt,
verb_invocation,
}
}
sourcepub fn is_between_slashes(&self) -> bool
pub fn is_between_slashes(&self) -> bool
Examples found in repository?
src/command/parts.rs (line 46)
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
pub fn from<S: Into<String>>(raw: S) -> Self {
let mut raw = raw.into();
let mut invocation_start_pos: Option<usize> = None;
let mut pt = BeTree::new();
let mut chars = raw.char_indices().peekable();
let mut escape_cur_char = false;
let mut escape_next_char = false;
// we loop on chars and build the pattern tree until we reach an unescaped ' ' or ':'
while let Some((pos, cur_char)) = chars.next() {
let between_slashes = pt.current_atom()
.map_or(
false,
|pp: &PatternParts| pp.is_between_slashes(),
);
match cur_char {
c if escape_cur_char => {
// Escaping is used to prevent characters from being consumed at the
// composite pattern level (or, and, parens) or as the separator between
// the pattern and the verb. An escaped char is usable in a pattern atom.
pt.mutate_or_create_atom(PatternParts::default).push(c);
}
'\\' => {
// Pattern escaping rules:
// - when after '/': only ' ', ':', '/' and '\' need escaping
// - otherwise, '&,' '|', '(', ')' need escaping too ('(' is only here for
// symmetry)
let between_slashes = match pt.current_atom() {
Some(pattern_parts) => pattern_parts.is_between_slashes(),
None => false,
};
escape_next_char = match chars.peek() {
None => false, // End of the string, we can't be escaping
Some((_, next_char)) => match (next_char, between_slashes) {
(' ' | ':' | '/' | '\\', _) => true,
('&' | '|' | '!' | '(' | ')', false) => true,
_ => false,
}
};
if !escape_next_char {
// if the '\' isn't used for escaping, it's used as its char value
pt.mutate_or_create_atom(PatternParts::default).push('\\');
}
}
' ' | ':' => { // ending the pattern part
invocation_start_pos = Some(pos);
break;
}
'/' => { // starting an atom part
pt.mutate_or_create_atom(PatternParts::default).add_part();
}
'|' if !between_slashes && pt.accept_binary_operator() => {
pt.push_operator(PatternOperator::Or);
}
'&' if !between_slashes && pt.accept_binary_operator() => {
pt.push_operator(PatternOperator::And);
}
'!' if !between_slashes && pt.accept_unary_operator() => {
pt.push_operator(PatternOperator::Not);
}
'(' if !between_slashes && pt.accept_opening_par() => {
pt.open_par();
}
')' if !between_slashes && pt.accept_closing_par() => {
pt.close_par();
}
_ => {
pt.mutate_or_create_atom(PatternParts::default).push(cur_char);
}
}
escape_cur_char = escape_next_char;
escape_next_char = false;
}
let mut verb_invocation = None;
if let Some(pos) = invocation_start_pos {
verb_invocation = Some(VerbInvocation::from(&raw[pos + 1..]));
raw.truncate(pos);
}
CommandParts {
raw_pattern: raw,
pattern: pt,
verb_invocation,
}
}
sourcepub fn add_part(&mut self)
pub fn add_part(&mut self)
Examples found in repository?
src/command/parts.rs (line 82)
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
pub fn from<S: Into<String>>(raw: S) -> Self {
let mut raw = raw.into();
let mut invocation_start_pos: Option<usize> = None;
let mut pt = BeTree::new();
let mut chars = raw.char_indices().peekable();
let mut escape_cur_char = false;
let mut escape_next_char = false;
// we loop on chars and build the pattern tree until we reach an unescaped ' ' or ':'
while let Some((pos, cur_char)) = chars.next() {
let between_slashes = pt.current_atom()
.map_or(
false,
|pp: &PatternParts| pp.is_between_slashes(),
);
match cur_char {
c if escape_cur_char => {
// Escaping is used to prevent characters from being consumed at the
// composite pattern level (or, and, parens) or as the separator between
// the pattern and the verb. An escaped char is usable in a pattern atom.
pt.mutate_or_create_atom(PatternParts::default).push(c);
}
'\\' => {
// Pattern escaping rules:
// - when after '/': only ' ', ':', '/' and '\' need escaping
// - otherwise, '&,' '|', '(', ')' need escaping too ('(' is only here for
// symmetry)
let between_slashes = match pt.current_atom() {
Some(pattern_parts) => pattern_parts.is_between_slashes(),
None => false,
};
escape_next_char = match chars.peek() {
None => false, // End of the string, we can't be escaping
Some((_, next_char)) => match (next_char, between_slashes) {
(' ' | ':' | '/' | '\\', _) => true,
('&' | '|' | '!' | '(' | ')', false) => true,
_ => false,
}
};
if !escape_next_char {
// if the '\' isn't used for escaping, it's used as its char value
pt.mutate_or_create_atom(PatternParts::default).push('\\');
}
}
' ' | ':' => { // ending the pattern part
invocation_start_pos = Some(pos);
break;
}
'/' => { // starting an atom part
pt.mutate_or_create_atom(PatternParts::default).add_part();
}
'|' if !between_slashes && pt.accept_binary_operator() => {
pt.push_operator(PatternOperator::Or);
}
'&' if !between_slashes && pt.accept_binary_operator() => {
pt.push_operator(PatternOperator::And);
}
'!' if !between_slashes && pt.accept_unary_operator() => {
pt.push_operator(PatternOperator::Not);
}
'(' if !between_slashes && pt.accept_opening_par() => {
pt.open_par();
}
')' if !between_slashes && pt.accept_closing_par() => {
pt.close_par();
}
_ => {
pt.mutate_or_create_atom(PatternParts::default).push(cur_char);
}
}
escape_cur_char = escape_next_char;
escape_next_char = false;
}
let mut verb_invocation = None;
if let Some(pos) = invocation_start_pos {
verb_invocation = Some(VerbInvocation::from(&raw[pos + 1..]));
raw.truncate(pos);
}
CommandParts {
raw_pattern: raw,
pattern: pt,
verb_invocation,
}
}
pub fn is_empty(&self) -> bool
sourcepub fn core(&self) -> &str
pub fn core(&self) -> &str
Examples found in repository?
More examples
src/pattern/pattern.rs (line 39)
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
pub fn new(
raw_expr: &BeTree<PatternOperator, PatternParts>,
search_modes: &SearchModeMap,
content_search_max_file_size: usize,
) -> Result<Self, PatternError> {
let expr: BeTree<PatternOperator, Pattern> = raw_expr
.try_map_atoms::<_, PatternError, _>(|pattern_parts| {
let core = pattern_parts.core();
Ok(
if core.is_empty() {
Pattern::None
} else {
let parts_mode = pattern_parts.mode();
let mode = search_modes.search_mode(parts_mode)?;
let flags = pattern_parts.flags();
match mode {
SearchMode::NameExact => Self::NameExact(
ExactPattern::from(core)
),
SearchMode::NameFuzzy => Self::NameFuzzy(
FuzzyPattern::from(core)
),
SearchMode::NameRegex => Self::NameRegex(
RegexPattern::from(core, flags.unwrap_or(""))?
),
SearchMode::NameTokens => Self::NameTokens(
TokPattern::new(core)
),
SearchMode::PathExact => Self::PathExact(
ExactPattern::from(core)
),
SearchMode::PathFuzzy => Self::PathFuzzy(
FuzzyPattern::from(core)
),
SearchMode::PathRegex => Self::PathRegex(
RegexPattern::from(core, flags.unwrap_or(""))?
),
SearchMode::PathTokens => Self::PathTokens(
TokPattern::new(core)
),
SearchMode::ContentExact => Self::ContentExact(
ContentExactPattern::new(core, content_search_max_file_size)
),
SearchMode::ContentRegex => Self::ContentRegex(
ContentRegexPattern::new(
core,
flags.unwrap_or(""),
content_search_max_file_size,
)?
),
}
}
)
})?;
Ok(if expr.is_empty() {
Pattern::None
} else if expr.is_atomic() {
expr.atoms().pop().unwrap()
} else {
Self::Composite(CompositePattern::new(expr))
})
}
sourcepub fn mode(&self) -> Option<&String>
pub fn mode(&self) -> Option<&String>
Examples found in repository?
src/pattern/pattern.rs (line 44)
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
pub fn new(
raw_expr: &BeTree<PatternOperator, PatternParts>,
search_modes: &SearchModeMap,
content_search_max_file_size: usize,
) -> Result<Self, PatternError> {
let expr: BeTree<PatternOperator, Pattern> = raw_expr
.try_map_atoms::<_, PatternError, _>(|pattern_parts| {
let core = pattern_parts.core();
Ok(
if core.is_empty() {
Pattern::None
} else {
let parts_mode = pattern_parts.mode();
let mode = search_modes.search_mode(parts_mode)?;
let flags = pattern_parts.flags();
match mode {
SearchMode::NameExact => Self::NameExact(
ExactPattern::from(core)
),
SearchMode::NameFuzzy => Self::NameFuzzy(
FuzzyPattern::from(core)
),
SearchMode::NameRegex => Self::NameRegex(
RegexPattern::from(core, flags.unwrap_or(""))?
),
SearchMode::NameTokens => Self::NameTokens(
TokPattern::new(core)
),
SearchMode::PathExact => Self::PathExact(
ExactPattern::from(core)
),
SearchMode::PathFuzzy => Self::PathFuzzy(
FuzzyPattern::from(core)
),
SearchMode::PathRegex => Self::PathRegex(
RegexPattern::from(core, flags.unwrap_or(""))?
),
SearchMode::PathTokens => Self::PathTokens(
TokPattern::new(core)
),
SearchMode::ContentExact => Self::ContentExact(
ContentExactPattern::new(core, content_search_max_file_size)
),
SearchMode::ContentRegex => Self::ContentRegex(
ContentRegexPattern::new(
core,
flags.unwrap_or(""),
content_search_max_file_size,
)?
),
}
}
)
})?;
Ok(if expr.is_empty() {
Pattern::None
} else if expr.is_atomic() {
expr.atoms().pop().unwrap()
} else {
Self::Composite(CompositePattern::new(expr))
})
}
sourcepub fn flags(&self) -> Option<&str>
pub fn flags(&self) -> Option<&str>
Examples found in repository?
src/pattern/pattern.rs (line 46)
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
pub fn new(
raw_expr: &BeTree<PatternOperator, PatternParts>,
search_modes: &SearchModeMap,
content_search_max_file_size: usize,
) -> Result<Self, PatternError> {
let expr: BeTree<PatternOperator, Pattern> = raw_expr
.try_map_atoms::<_, PatternError, _>(|pattern_parts| {
let core = pattern_parts.core();
Ok(
if core.is_empty() {
Pattern::None
} else {
let parts_mode = pattern_parts.mode();
let mode = search_modes.search_mode(parts_mode)?;
let flags = pattern_parts.flags();
match mode {
SearchMode::NameExact => Self::NameExact(
ExactPattern::from(core)
),
SearchMode::NameFuzzy => Self::NameFuzzy(
FuzzyPattern::from(core)
),
SearchMode::NameRegex => Self::NameRegex(
RegexPattern::from(core, flags.unwrap_or(""))?
),
SearchMode::NameTokens => Self::NameTokens(
TokPattern::new(core)
),
SearchMode::PathExact => Self::PathExact(
ExactPattern::from(core)
),
SearchMode::PathFuzzy => Self::PathFuzzy(
FuzzyPattern::from(core)
),
SearchMode::PathRegex => Self::PathRegex(
RegexPattern::from(core, flags.unwrap_or(""))?
),
SearchMode::PathTokens => Self::PathTokens(
TokPattern::new(core)
),
SearchMode::ContentExact => Self::ContentExact(
ContentExactPattern::new(core, content_search_max_file_size)
),
SearchMode::ContentRegex => Self::ContentRegex(
ContentRegexPattern::new(
core,
flags.unwrap_or(""),
content_search_max_file_size,
)?
),
}
}
)
})?;
Ok(if expr.is_empty() {
Pattern::None
} else if expr.is_atomic() {
expr.atoms().pop().unwrap()
} else {
Self::Composite(CompositePattern::new(expr))
})
}
Trait Implementations§
source§impl Clone for PatternParts
impl Clone for PatternParts
source§fn clone(&self) -> PatternParts
fn clone(&self) -> PatternParts
Returns a copy of the value. Read more
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source
. Read moresource§impl Debug for PatternParts
impl Debug for PatternParts
source§impl Default for PatternParts
impl Default for PatternParts
source§impl Display for PatternParts
impl Display for PatternParts
source§impl PartialEq<PatternParts> for PatternParts
impl PartialEq<PatternParts> for PatternParts
source§fn eq(&self, other: &PatternParts) -> bool
fn eq(&self, other: &PatternParts) -> bool
This method tests for
self
and other
values to be equal, and is used
by ==
.impl StructuralPartialEq for PatternParts
Auto Trait Implementations§
impl RefUnwindSafe for PatternParts
impl Send for PatternParts
impl Sync for PatternParts
impl Unpin for PatternParts
impl UnwindSafe for PatternParts
Blanket Implementations§
§impl<T> Pointable for T
impl<T> Pointable for T
source§impl<R, P> ReadPrimitive<R> for Pwhere
R: Read + ReadEndian<P>,
P: Default,
impl<R, P> ReadPrimitive<R> for Pwhere
R: Read + ReadEndian<P>,
P: Default,
source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
Read this value from the supplied reader. Same as
ReadEndian::read_from_little_endian()
.