A fluent interface for building regular expressions
$ dotnet add package RejigsA fluent, intuitive, and thread-safe builder for regular expressions in C#
Rejigs makes creating complex regular expressions simple and readable by providing a fluent API that builds patterns step by step. Built with immutability at its core, Rejigs is inherently thread-safe and follows functional programming principles. No more cryptic regex syntax — write patterns that are easy to understand, maintain, and safely use across multiple threads.
Install Rejigs via NuGet Package Manager:
dotnet add package Rejigs
Or via Package Manager Console:
Install-Package Rejigs
using Rejigs;
// Simple text matching
var regex = Rejigs.Create()
.AtStart()
.Text("hello")
.AtEnd()
.Build();
Console.WriteLine(regex.IsMatch("hello")); // True
Console.WriteLine(regex.IsMatch("hello world")); // False
var emailRegex = Rejigs.Create()
.AtStart()
.OneOrMore(r => r.AnyLetterOrDigit().Or().AnyOf(".-_")) // Local part
.Text("@")
.OneOrMore(r => r.AnyLetterOrDigit().Or().AnyOf(".-")) // Domain
.Text(".")
.AnyInRange('a', 'z') // Top-level domain (2-6 letters)
.Between(2, 6)
.AtEnd()
.IgnoreCase() // Case-insensitive matching
.Build();
Console.WriteLine(emailRegex.IsMatch("user@example.com")); // True
Console.WriteLine(emailRegex.IsMatch("invalid-email")); // False
Rejigs provides built-in validation methods to check input strings against patterns.
var pattern = Rejigs.Create().AtStart().OneOrMore(r => r.AnyDigit()).AtEnd();
pattern.Validate("12345"); // Returns true
pattern.Validate("abc"); // Throws RejigsValidationException
For scenarios where you prefer not to use exceptions for control flow, use TryValidate. It returns a RejigsValidationResult with IsValid and ErrorMessage properties:
var pattern = Rejigs.Create().AtStart().OneOrMore(r => r.AnyDigit()).AtEnd();
var result = pattern.TryValidate("12345");
Console.WriteLine(result.IsValid); // True
Console.WriteLine(result.ErrorMessage); // null
var failed = pattern.TryValidate("abc");
Console.WriteLine(failed.IsValid); // False
Console.WriteLine(failed.ErrorMessage); // "Input 'abc' does not match the required pattern"
Rejigs is built with immutability at its core, making it inherently thread-safe without any performance overhead from locking mechanisms.
Every method call returns a new instance rather than modifying the existing one:
var basePattern = Rejigs.Create().Text("hello");
var pattern1 = basePattern.Text(" world"); // New instance
var pattern2 = basePattern.Text(" there"); // Another new instance
// basePattern remains unchanged: "hello"
// pattern1 contains: "hello world"
// pattern2 contains: "hello there"
You can safely share Rejigs builders across multiple threads:
// Safe to use in multiple threads simultaneously
var sharedBuilder = Rejigs.Create()
.AtStart()
.OneOrMore(r => r.AnyDigit());
// Thread 1
var phonePattern = sharedBuilder.Text("-").Exactly(3, r => r.AnyDigit()).Build();
// Thread 2 (concurrent with Thread 1)
var idPattern = sharedBuilder.AtEnd().Build();
// No race conditions or shared state issues!
var emailRegex = ... instead of var regex = ...AtStart() and AtEnd() — For exact matches, always anchor your patternsBuild() result for repeated useTryValidate over Validate — Use the non-throwing variant when validation failure is expected// Create a base pattern (safe to share)
var baseValidation = Rejigs.Create().AtStart().OneOrMore(r => r.AnyLetterOrDigit());
// Multiple threads can safely extend the pattern
Task.Run(() => {
var emailPattern = baseValidation.Text("@").OneOrMore(r => r.AnyLetterOrDigit()).Build();
// Use emailPattern...
});
Task.Run(() => {
var usernamePattern = baseValidation.AtEnd().Build();
// Use usernamePattern...
});
// No synchronization needed!
For detailed documentation, examples, and API reference, visit the Rejigs Documentation.
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to raise an issue or a PR.