# to-regex-range

[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)

[![Crates.io](https://img.shields.io/crates/v/to-regex-range.svg)](https://crates.io/crates/to-regex-range)
[![Documentation](https://docs.rs/to-regex-range/badge.svg)](https://docs.rs/to-regex-range)
[![CI](https://github.com/trananhtung/to-regex-range/actions/workflows/ci.yml/badge.svg)](https://github.com/trananhtung/to-regex-range/actions/workflows/ci.yml)
[![License](https://img.shields.io/crates/l/to-regex-range.svg)](#license)

**Generate a compact regex that matches an integer range** — `(1, 99)` →
`[1-9]|[1-9][0-9]`. A faithful Rust port of the
[`to-regex-range`](https://www.npmjs.com/package/to-regex-range) npm package (a
micromatch building block). Zero dependencies and `#![no_std]`.

```rust
use to_regex_range::{to_regex_range, to_regex_range_with_options, Options};

assert_eq!(to_regex_range(1, 5), "[1-5]");
assert_eq!(to_regex_range(1, 99), "(?:[1-9]|[1-9][0-9])");
assert_eq!(to_regex_range(0, 255), "(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])");
assert_eq!(to_regex_range(-10, -1), "(?:-[1-9]|-10)");

let opts = Options::default().shorthand(true);
assert_eq!(to_regex_range_with_options(1, 99, &opts), "(?:[1-9]|[1-9]\\d)");
```

## Why to-regex-range?

Matching "a number between 1 and 255" with a regex by hand is tedious and
error-prone. This builds the minimal alternation for you — splitting the range at
power-of-ten boundaries and turning each sub-range into a character class with the
right quantifier. The result is a regex *source* string; wrap it in your engine of
choice (`regex`, `fancy-regex`, …).

```toml
[dependencies]
to-regex-range = "0.1"
```

## API

| Item | Purpose |
| --- | --- |
| `to_regex_range(min, max)` | The regex source for the range, default options |
| `to_regex_range_with_options(min, max, &Options)` | …with options |
| `Options { capture, shorthand, wrap }` | `capture` → `( … )`; `shorthand` → `\d`; `wrap` (default) → `(?: … )` |

## Behavior

- `min`/`max` may be given in either order; equal bounds yield the literal number.
- Negative ranges are handled, sharing a `-?` prefix where positive and negative
  sub-patterns coincide.
- The output is a bare regex source — no anchors or delimiters. Add `^(?:…)$` if you
  need to match a whole string.
- Integer ranges only; zero-padded ranges (e.g. `001..100`) are out of scope.

## Contributors ✨

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome — code, docs, bug reports, ideas, reviews! See the [emoji key](https://allcontributors.org/docs/en/emoji-key) for how each contribution is recognized, and open a PR or issue to get involved.

Thanks goes to these wonderful people:

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tbody>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/trananhtung"><img src="https://avatars.githubusercontent.com/u/30992229?v=4?s=100" width="100px;" alt="Tung Tran"/><br /><sub><b>Tung Tran</b></sub></a><br /><a href="https://github.com/trananhtung/to-regex-range/commits?author=trananhtung" title="Code">💻</a> <a href="#maintenance-trananhtung" title="Maintenance">🚧</a></td>
    </tr>
  </tbody>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

## License

Licensed under either of [Apache-2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT) at
your option.
