easy_regex/
group.rs

1//! Creates a group pattern in many different ways as desired.
2//! 
3//! This module consists of methods needed to create a group in many different ways, having different options/settings.
4//! The main one is the [`group`](../struct.EasyRegex.html#method.group) method which takes an expression as argument
5//! and a set of meta as ```GroupSettings``` creates a group for it.
6//! Other methods starting with the ```into``` word followed by an underline makes all previously chained expressions into a group.
7//! They mostly take no arguments for settings and are useful to be added to the latter part of a method chain.
8
9use crate::{
10    settings::{GroupSettings, Settings, base::DEFAULT},
11    EasyRegex,
12};
13
14impl EasyRegex {
15    /// Creates a group of expressions.
16    ///  
17    /// This method takes an expression (a segment of entire pattern) followed
18    /// by a set of settings (```GroupSettings``` struct) that will be concatenated/inserted to the expression itself,
19    /// outputing the previous pattern followed by this group.
20    ///
21    /// # Examples
22    ///
23    /// ```
24    /// use easy_regex::{EasyRegex, settings::group::OPTIONAL_GROUP};
25    /// 
26    /// let result = EasyRegex::new_section().group("expression", &OPTIONAL_GROUP);
27    /// assert_eq!("(expression)?", result.get_regex().unwrap().as_str());
28    /// ```
29    pub fn group(self, expression: &str, group_sttings: &GroupSettings) -> Self {
30        let mut final_result = EasyRegex::new_section();
31
32        // to make the regex itself clearer, this extra if condition is added.
33        if group_sttings.other.flags.is_some() && group_sttings.is_non_capture {
34            final_result.0 = format!(
35                "({}:{})",
36                group_sttings.other.flags.unwrap().as_str(),
37                expression
38            );
39        } else {
40            final_result = final_result
41                .literal(
42                    expression,
43                    &Settings {
44                        flags: group_sttings.other.flags,
45                        ..Default::default()
46                    },
47                )
48                .into_group(&Settings {
49                    flags: None,
50                    ..group_sttings.other
51                });
52            if group_sttings.is_non_capture {
53                final_result.0.insert_str(1, "?:");
54            }
55        }
56
57        self.literal(&final_result.0, &DEFAULT)
58    }
59
60    /// Same as the ```group``` method with the option to add a custom name to the group.
61    ///
62    /// # Examples
63    ///
64    /// ```
65    /// use easy_regex::{EasyRegex, settings::group::OPTIONAL_GROUP};
66    /// 
67    /// let result = EasyRegex::new_section().named_group("my_group", "expression", &OPTIONAL_GROUP);
68    /// assert_eq!("(?P<my_group>expression)?", result.get_regex().unwrap().as_str());
69    /// ```
70    pub fn named_group(self, name: &str, expression: &str, group_settings: &GroupSettings) -> Self {
71        let final_result = format!("?P<{}>{}", name, expression);
72        self.group(&final_result, &group_settings)
73    }
74
75    /// Turns the previous expressions into a **capturing** group. It uses ```Settings``` struct for the settings parameter.
76    ///
77    /// # Examples
78    ///
79    /// ```
80    /// use easy_regex::{EasyRegex, settings::base::OPTIONAL};
81    /// 
82    /// let result = EasyRegex::new(r"\d{3}").into_group(&OPTIONAL);
83    /// assert_eq!(r"(\d{3})?", result.get_regex().unwrap().as_str());
84    /// ```
85    pub fn into_group(self, settings: &Settings) -> Self {
86        let raw_result = format!("({})", self.0);
87        let final_result = EasyRegex(String::new()).literal(&raw_result, &settings);
88        final_result
89    }
90
91    /// A variation of ```into_group``` having *name* option **(?P\<name\>RegExp)**.
92    pub fn into_named_group(self, name: &str, settings: &Settings) -> Self {
93        let raw_result = format!("(?P<{}>{})", name, self.0);
94        let final_result = EasyRegex(String::new()).literal(&raw_result, &settings);
95        final_result
96    }
97
98    /// A variation of ```into_group``` having *non-capturing* option **(?:RegExp)**.
99    pub fn into_non_capturing(self) -> Self {
100        let result = format!("(?:{})", self.0);
101        EasyRegex(result)
102    }
103    ////////////////////////////////////////////////////////////////
104    /// A variation of ```into_group``` having *Insensitive* flag **(?i)**.
105    pub fn into_insensitive_group(self) -> Self {
106        let result = format!("((?i){})", self.0);
107        EasyRegex(result)
108    }
109
110    /// A variation of ```into_group``` having *Multiline* flag **(?m)**.
111    pub fn into_multline_group(self) -> Self {
112        let result = format!("((?m){})", self.0);
113        EasyRegex(result)
114    }
115
116    /// A variation of ```into_group``` having *Dot All* flag **(?s)**.
117    pub fn into_dot_match_newline_group(self) -> Self {
118        let result = format!("((?s){})", self.0);
119        EasyRegex(result)
120    }
121
122    /// A variation of ```into_group``` ignoring *whitespaces* **(?x)**.
123    pub fn into_ignore_whitespace_group(self) -> Self {
124        let result = format!("((?x){})", self.0);
125        EasyRegex(result)
126    }
127    ////////////////////////////////////////////////////////////////
128    /// A variation of ```into_non_capturing``` having *Insensitive* flag **(?i)**.
129    pub fn into_insensitive_non_capturing(self) -> Self {
130        let result = format!("(?i:{})", self.0);
131        EasyRegex(result)
132    }
133
134    /// A variation of ```into_non_capturing``` having *Multiline* flag **(?m)**.
135    pub fn into_multiline_non_capturing(self) -> Self {
136        let result = format!("(?m:{})", self.0);
137        EasyRegex(result)
138    }
139
140    /// A variation of ```into_non_capturing``` having *Dot All* flag **(?s)**.
141    pub fn into_dot_match_newline_non_capturing(self) -> Self {
142        let result = format!("(?s:{})", self.0);
143        EasyRegex(result)
144    }
145
146    /// A variation of ```into_non_capturing``` ignoring *whitespaces* **(?x)**.
147    pub fn into_ignore_whitespace_non_capturing(self) -> Self {
148        let result = format!("(?x:{})", self.0);
149        EasyRegex(result)
150    }
151    ////////////////////////////////////////////////////////////////
152    /// A variation of ```into_group``` having *Insensitive* flag cleared **(?-i)**.
153    pub fn into_sensitive_group(self) -> Self {
154        let result = format!("((?-i){})", self.0);
155        EasyRegex(result)
156    }
157
158    /// A variation of ```into_group``` having *Multiline* flag cleared **(?-m)**.
159    pub fn into_single_line_group(self) -> Self {
160        let result = format!("((?-m){})", self.0);
161        EasyRegex(result)
162    }
163
164    /// A variation of ```into_group``` having *Dot All* flag cleared **(?-s)**.
165    pub fn into_dot_dismatch_newline_group(self) -> Self {
166        let result = format!("((?-s){})", self.0);
167        EasyRegex(result)
168    }
169
170    /// A variation of ```into_group``` taking *whitespaces* into account **(?-x)**.
171    pub fn into_include_whitespace_group(self) -> Self {
172        let result = format!("((?-x){})", self.0);
173        EasyRegex(result)
174    }
175    ////////////////////////////////////////////////////////////////
176    /// A variation of ```into_non_capturing``` having *Insensitive* flag cleared **(?-i)**.
177    pub fn into_sensitive_non_capturing(self) -> Self {
178        let result = format!("(?-i:{})", self.0);
179        EasyRegex(result)
180    }
181
182    /// A variation of ```into_non_capturing``` having *Multiline* flag cleared **(?-m)**.
183    pub fn into_single_line_non_capturing(self) -> Self {
184        let result = format!("(?-m:{})", self.0);
185        EasyRegex(result)
186    }
187
188    /// A variation of ```into_non_capturing``` having *Dot All* flag cleared **(?-s)**.
189    pub fn into_dot_dismatch_newline_non_capturing(self) -> Self {
190        let result = format!("(?-s:{})", self.0);
191        EasyRegex(result)
192    }
193
194    /// A variation of ```into_non_capturing``` taking *whitespaces* into account **(?-x)**.
195    pub fn into_include_whitespace_non_capturing(self) -> Self {
196        let result = format!("(?-x:{})", self.0);
197        EasyRegex(result)
198    }
199}
200
201#[cfg(test)]
202mod tests {
203    use self::EasyRegex;
204    use super::*;
205    use crate::settings::group::{DEFAULT_GROUP, INSENSITIVE_GROUP, INSENSITIVE_NON_CAPTURE};
206
207    #[test]
208    fn group_works() {
209        let initial_exp = EasyRegex::new("initial_");
210        let result = initial_exp.group("group", &DEFAULT_GROUP);
211        assert_eq!("initial_(group)", result.0);
212    }
213
214    #[test]
215    fn optional_non_capture_group_works() {
216        let initial_exp = EasyRegex::start_of_line();
217        let group_settings = GroupSettings {
218            other: Settings {
219                is_optional: true,
220                ..Default::default()
221            },
222            is_non_capture: true,
223        };
224
225        let result = initial_exp.group("group", &group_settings);
226        assert_eq!("^(?:group)?", result.0);
227    }
228
229    #[test]
230    fn insensitive_group_works() {
231        let result = EasyRegex::start_of_line()
232            .group("group", &INSENSITIVE_GROUP)
233            .get_regex()
234            .unwrap();
235        assert_eq!("^((?i)group)", result.as_str());
236    }
237
238    #[test]
239    fn insensitive_non_capturing_group_works() {
240        let result = EasyRegex::start_of_line()
241            .group("group", &INSENSITIVE_NON_CAPTURE)
242            .get_regex()
243            .unwrap();
244        assert_eq!("^(?i:group)", result.as_str());
245    }
246
247    #[test]
248    fn into_group_works() {
249        let initial_exp = EasyRegex::new("group");
250        let result = initial_exp.into_group(&DEFAULT);
251
252        assert_eq!("(group)", result.0);
253    }
254
255    ////////////////////////////////////////////////// ERRORS /////////////////////////////////////////////////////
256    // #[test]
257    //     fn into_negative_group_added_optional_exp_not_works() {
258    //         let initial_exp = MetaFuncRegex::new("group");
259    //         let result = initial_exp
260    //             // .into_negative_group()
261    //             .literal_exp(&String::new(), &OPTIONAL);
262    //         let err = result.get_regex().unwrap_err();
263    //         let re = regex::Regex::new("/(?!group)/").unwrap();
264    //         // regex::Regex::is_matchbuild(&re).unwrap();
265    //         // println!("{}", &after);
266    //         assert_eq!(
267    //             regex::Error::Syntax(
268    //                 "regex parse error:
269    //     (?!group)?
270    //     ^^^
271    // error: look-around, including look-ahead and look-behind, is not supported"
272    //                     .to_string()
273    //             ),
274    //             err
275    //         );
276    //     }
277
278    // #[test]
279    //     fn optional_negative_group_not_works() {
280    //         let initial_exp = MetaFuncRegex::new("^");
281    //         let group_settings = GroupSettings {
282    //             other: Settings {
283    //                 is_optional: true,
284    //                 ..Default::default()
285    //             },
286    //             is_non_capture: false,
287    //             flags: None,
288    //         };
289
290    //         let result = initial_exp.group("group", &group_settings);
291    //         let err = result.get_regex().unwrap_err();
292    //         assert_eq!(
293    //             regex::Error::Syntax(
294    //                 "regex parse error:
295    //     ^(?!group)?
296    //      ^^^
297    // error: look-around, including look-ahead and look-behind, is not supported"
298    //                     .to_string()
299    //             ),
300    //             err
301    //         );
302    //     }
303}