regex_dsl!() { /* proc-macro */ }
Expand description
A DSL for creating Regular Expressions.
This macro will introduce a domain specific language to create a regular expression that is easier to read.
The macro support a few types of arguments, if the macro has more than one argument, it will concat all the arguments.
The supported arguments are:
§A literal string.
That is - "<something>"
- this is the same as equals, i.e. it will produce a regular expression to compare that the string is exactly the same as the argument. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl!("Foo");
assert!(regex.is_match("Foo"));
assert!(!regex.is_match("Bar"));
It will also escape any character that need to be escaped, for example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl!("Foo\\Bar");
assert!(regex.is_match("Foo\\Bar"));
assert!(!regex.is_match("Bar-Bar"));
§A literal character.
That is - 'a'
- this is the same as the String but for a single character. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl!(
"Foo",
'-',
"Bar"
);
assert!(regex.is_match("Foo-Bar"));
assert!(!regex.is_match("Bar=Bar"));
§Class name
That is - #<class_name>
- a character from a unicode class. See more details in here. This is equivalent to \p{<class_name>}
. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl!{
#latin,
#greek,
};
assert!(regex.is_match("aα"));
assert!(!regex.is_match("αa"));
§Not a class name
That is - ~<class_name>
- anything but a character from a unicode class. See more details in here. This is equivalent to \P{<class_name>}
. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl!{
~latin,
~greek,
};
assert!(!regex.is_match("aα"));
assert!(regex.is_match("αa"));
§special cases:
That is - something
- a special regular expression type of character or boundary. Available types are:
any_character
- Any character (besides new line unless theallow_dot
flag is set). This is equivalent to.
digit
- A digit (similar to#digit
and#Nd
). This is equivalent to\d
not_digit
- Not a digit. This is equivalent to\D
.white_space
- A white space. . This is equivalent to\s
.not_white_space
- Not a white space. This is equivalent to\S
.word_character
- A word character. This is equivalent to\w
.not_word_character
- Not a word character. This is equivalent to\W
.beginning_of_line
- A beginning of a line. This is equivalent to^
.end_of_line
- An end of a line. This is equivalent to$
.word_boundary
- A word boundary. This is equivalent to\b
.not_word_boundary
- Not a word boundary. This is equivalent to\B
.beginning_of_input
- A beginning of the input. This is equivalent to\A
.end_of_input
- An end of the input. This is equivalent to\z
.
For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl!{
"Foo",
any_character
"Bar",
};
assert!(regex.is_match("Foo Bar"));
assert!(regex.is_match("Foo-Bar"));
assert!(!regex.is_match("FooBar"));
§Function
That is - func(args)
or func { args }
- a function DSL. The available functions are:
§eq
Expect a single literal string arguments. behave the same as literal string above. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
eq {
"Foo"
}
};
assert!(regex.is_match("Foo"));
assert!(!regex.is_match("Bar"));
§regex
Expect a single literal string argument. Use it as raw regular expression. To be used for things that are not covered by this DSL or when the expression is trivial to understand. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
regex("[0-9]+")
};
assert!(regex.is_match("300"));
assert!(!regex.is_match("Bar"));
Invalid regular expression will fail the compilation. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
regex("[0-9+")
};
§any
Must have at least two dsl arguments. Make sure that at least of of them is valid. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any {
"Foo",
eq("Bar"),
regex("[0-9]+")
}
};
assert!(regex.is_match("Foo"));
assert!(regex.is_match("Bar"));
assert!(regex.is_match("100"));
assert!(!regex.is_match("Bor"));
§concat
Must have at least two dsl arguments. Make sure that all of of them is valid and in the correct order. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
concat {
"Foo",
eq("Bar"),
regex("[0-9]+")
}
};
assert!(regex.is_match("FooBar300"));
assert!(!regex.is_match("Bar300"));
assert!(!regex.is_match("FooBar"));
§any_of
Creates a user class. The arguments can be:
- A string - in that case, the class will include all the characters in the string. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any_of {
"Bar",
}
};
assert!(regex.is_match("B"));
assert!(regex.is_match("a"));
assert!(regex.is_match("r"));
assert!(!regex.is_match("F"));
- A character - in that case, the class will include the character. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any_of {
'1',
'2',
"Bar",
}
};
assert!(regex.is_match("1"));
assert!(regex.is_match("2"));
assert!(regex.is_match("B"));
assert!(regex.is_match("a"));
assert!(regex.is_match("r"));
assert!(!regex.is_match("F"));
assert!(!regex.is_match("3"));
- A predefined unicode class - in that case, the class will include the characters in that class. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any_of {
#digit,
"Bar",
}
};
assert!(regex.is_match("1"));
assert!(regex.is_match("8"));
assert!(regex.is_match("B"));
assert!(regex.is_match("a"));
assert!(regex.is_match("r"));
assert!(!regex.is_match("F"));
- Not a predefined unicode class - in that case, the class will include anything by the characters in that class. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any_of {
~digit,
}
};
assert!(!regex.is_match("1"));
assert!(!regex.is_match("8"));
assert!(regex.is_match("B"));
assert!(regex.is_match("a"));
assert!(regex.is_match("r"));
- A range of characters (from: ‘a’ to: ‘z’) - in that case, the class will include all the characters in that range. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any_of {
'1',
from: '4' to: '6'
}
};
assert!(!regex.is_match("0"));
assert!(regex.is_match("1"));
assert!(!regex.is_match("2"));
assert!(!regex.is_match("3"));
assert!(regex.is_match("4"));
assert!(regex.is_match("5"));
assert!(regex.is_match("6"));
assert!(!regex.is_match("7"));
- A special case (see special cases above). For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any_of {
'a',
digit,
}
};
assert!(regex.is_match("0"));
assert!(regex.is_match("1"));
assert!(regex.is_match("a"));
assert!(!regex.is_match("b"));
intersect(<user_class>)
- An intersection of two user created class. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any_of {
from: '2' to: '5',
intersect {
from: '3' to: '7',
}
}
};
assert!(!regex.is_match("2"));
assert!(regex.is_match("3"));
assert!(regex.is_match("4"));
assert!(regex.is_match("5"));
assert!(!regex.is_match("6"));
assert!(!regex.is_match("7"));
subtract(<user_class>)
- Remove characters from the class. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any_of {
from: '2' to: '7',
subtract {
'3',
'5'
}
}
};
assert!(regex.is_match("2"));
assert!(!regex.is_match("3"));
assert!(regex.is_match("4"));
assert!(!regex.is_match("5"));
assert!(regex.is_match("6"));
assert!(regex.is_match("7"));
xor(<user_class>)
- Symmetric difference between the classes. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
any_of {
from: '2' to: '5',
xor {
from: '3' to: '7',
}
}
};
assert!(regex.is_match("2"));
assert!(!regex.is_match("3"));
assert!(!regex.is_match("4"));
assert!(!regex.is_match("5"));
assert!(regex.is_match("6"));
assert!(regex.is_match("7"));
§not_any_of
Revert a user class. The arguments are the same as the user class above. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
not_any_of {
'1',
from: '4' to: '6'
}
};
assert!(regex.is_match("0"));
assert!(!regex.is_match("1"));
assert!(regex.is_match("2"));
assert!(regex.is_match("3"));
assert!(!regex.is_match("4"));
assert!(!regex.is_match("5"));
assert!(!regex.is_match("6"));
assert!(regex.is_match("7"));
§group
Create a capture group. If the argument is a DSL, the group will be unnamed. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"|",
group {
digit,
},
"|"
};
let caps = regex.captures("|4|").unwrap();
assert_eq!(caps.get(1).unwrap().as_str(), "4");
If there is a name:<name>
argument, the group will be named name
. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"|",
group {
name: a_digit,
digit,
},
"|"
};
let caps = regex.captures("|4|").unwrap();
assert_eq!(&caps["a_digit"], "4");
One can have more than one group in an expression. For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"|",
group {
group {
name: number_1,
regex("[0-9]+"),
},
",",
group {
name: number_2,
regex("[0-9]+"),
},
}
"|"
};
let caps = regex.captures("|100,400|").unwrap();
assert_eq!(&caps["number_1"], "100");
assert_eq!(&caps["number_2"], "400");
assert_eq!(caps.get(1).unwrap().as_str(), "100,400");
§maybe
Represent a regular expression that appears once or not at all (i.e. equivalent to the ?
operator).
For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
maybe {
digit,
},
">"
};
assert!(regex.is_match("<>"));
assert!(regex.is_match("<4>"));
assert!(!regex.is_match("<a>"));
To use a lazy quantifier, use the keyword lazy
, that is, something like:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
maybe {
lazy,
digit,
},
">"
};
assert!(regex.is_match("<>"));
assert!(regex.is_match("<4>"));
assert!(!regex.is_match("<a>"));
§repeat
Represent a regular expression that appears once or more (i.e. equivalent to the +
operator).
For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
repeat {
digit,
},
">"
};
assert!(regex.is_match("<1>"));
assert!(regex.is_match("<123>"));
assert!(!regex.is_match("<>"));
assert!(!regex.is_match("<a>"));
To use a lazy quantifier, use the keyword lazy
, that is, something like:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
repeat {
lazy,
digit,
},
">"
};
assert!(regex.is_match("<1>"));
assert!(regex.is_match("<123>"));
assert!(!regex.is_match("<>"));
assert!(!regex.is_match("<a>"));
§maybe_repeat
Represent a regular expression that can appears a few times or never (i.e. equivalent to the *
operator).
For example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
maybe_repeat {
digit,
},
">"
};
assert!(regex.is_match("<1>"));
assert!(regex.is_match("<123>"));
assert!(regex.is_match("<>"));
assert!(!regex.is_match("<a>"));
To use a lazy quantifier, use the keyword lazy
, that is, something like:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
maybe_repeat {
lazy,
digit,
},
">"
};
assert!(regex.is_match("<1>"));
assert!(regex.is_match("<123>"));
assert!(regex.is_match("<>"));
assert!(!regex.is_match("<a>"));
§times
Represent a regular expression that can appears a few times.
- One can specify exactly how many times, for example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
times {
exactly: 4
digit,
},
">"
};
assert!(regex.is_match("<1234>"));
assert!(!regex.is_match("<1>"));
assert!(!regex.is_match("<123>"));
assert!(!regex.is_match("<>"));
assert!(!regex.is_match("<a>"));
- One can specify lowest limit of the number of times, for example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
times {
at_least: 2,
digit,
},
">"
};
assert!(regex.is_match("<12>"));
assert!(regex.is_match("<123>"));
assert!(regex.is_match("<1234>"));
assert!(regex.is_match("<12345>"));
assert!(!regex.is_match("<>"));
assert!(!regex.is_match("<1>"));
- One can specify a range of the number of times, for example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
times {
at_least: 2,
at_most: 4,
digit,
},
">"
};
assert!(regex.is_match("<1234>"));
assert!(regex.is_match("<123>"));
assert!(regex.is_match("<12>"));
assert!(!regex.is_match("<1>"));
assert!(!regex.is_match("<>"));
assert!(!regex.is_match("<12345>"));
To use a lazy quantifier, use the keyword lazy
, that is, something like:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
"<",
times {
lazy,
exactly: 2,
digit,
},
">"
};
assert!(regex.is_match("<12>"));
assert!(!regex.is_match("<1>"));
assert!(!regex.is_match("<>"));
§apply
Apply regular expression flags. The available flags are:
case_insensitive
- When the flag is set, letters match both upper and lower case - equivalent to thei
flag.multi_line
- When the flag is set,beginning_of_line
and end_of_line match begin/end of line and not input - equivalent to them
flag.allow_dot
- When the flag is set, allowany_character
to match a new line - equivalent to thes
flag.enables_crlf_mode
- Whenmulti_line
flag is set,\r\n
is used - - equivalent to theR
flag.
To set a flag, use: +<flag>
, to unset it, use: -<flag>
.
One can apply flags on a specific DSL, by adding the DSL as an argument to the apply function - for example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
apply {
+case_insensitive,
-multi_line,
"foo"
}
};
assert!(regex.is_match("foo"));
assert!(regex.is_match("Foo"));
One can apply flags on the rest of the DSLs, by leaving just the flags as a arguments to the apply function - for example:
use rust_regex_dsl::regex_dsl;
let regex = regex_dsl! {
apply {
+case_insensitive,
},
eq("foo"),
apply {
-case_insensitive,
},
eq("Bar"),
};
assert!(regex.is_match("FooBar"));
assert!(regex.is_match("fooBar"));
assert!(!regex.is_match("fooBAR"));