Macro create_capture

Source
create_capture!() { /* proc-macro */ }
Expand description

A macro to create a Regular Expression capturing struct.

This macro will create an helper struct for capture regular expression groups for a hard coded regular expression.

The macro has two arguments, the first one should be the name of the struct to create and the second one is the regular expression, either as raw regular expression or as a DSL (See regex_dsl! for syntax).

The struct will be a tuple with the first filed as a &str with the entire capture text (i.e. capture group 0) and the rest will be Option<&str> with the content of the capture group (for any capture group in the regular expression). That is, for [a-z]+ the struct will have only (&str) and for ([a-z]+)([0-9]+)([a-z]+) the struct will have (&str, Option<&str>, Option<&str>, Option<&str>). If the regular expression has any named capture groups, the struct will have a public function to retrieve them with the same name as the group name (snake case). The struct will have a get_capture method that will return the first member of the tuple.

The struct will have three static public functions:

  • catch that accept a string reference and return an Option with the struct if it matches the argument.
  • catch_all that accept a string reference and return an Iterator over all the places the expression was caught in the argument.
  • regex that return a reference to the regular expression.

Please note, The capturing groups are optionals for regular expressions like: ([a-z]+)|([0-9]+).

For example:

use rust_regex_dsl::create_capture;

create_capture!(MyRegexCapture, "([0-9]+)");

assert!(MyRegexCapture::catch("Foo").is_none());
let caught = MyRegexCapture::catch("33").unwrap();
assert_eq!(caught.0, "33");
assert_eq!(caught.get_capture(), "33");
assert_eq!(caught.1, Some("33"));

let all: Vec<_> = MyRegexCapture::catch_all("100 90 80").collect();
assert_eq!(all.len(), 3);
assert_eq!(all[0].0, "100");
assert_eq!(all[1].0, "90");
assert_eq!(all[2].0, "80");

A more complex example:

use rust_regex_dsl::create_capture;

create_capture!(MyRegexCapture,
  any {
    group {
      name: Letters,
      repeat {
         any_of {
           #letter
         }
       }
    }, group {
      name: Digits,
      repeat {
         any_of {
           #digit
         }
       }
   }
  });

let caught = MyRegexCapture::catch("hello").unwrap();
assert_eq!(caught.0, "hello");
assert_eq!(caught.get_capture(), "hello");
assert_eq!(caught.1, Some("hello"));
assert_eq!(caught.letters(), Some("hello"));
assert_eq!(caught.2, None);
assert_eq!(caught.digits(), None);

let caught = MyRegexCapture::catch("321").unwrap();
assert_eq!(caught.0, "321");
assert_eq!(caught.get_capture(), "321");
assert_eq!(caught.1, None);
assert_eq!(caught.letters(), None);
assert_eq!(caught.2, Some("321"));
assert_eq!(caught.digits(), Some("321"));

let all: Vec<_> = MyRegexCapture::catch_all("A1234B33").collect();
assert_eq!(all.len(), 4);
assert_eq!(all[0].1, Some("A"));
assert_eq!(all[1].2, Some("1234"));
assert_eq!(all[2].letters(), Some("B"));
assert_eq!(all[3].digits(), Some("33"));