Now that regex.help is functional and deployed (check it out if you’re writing regular expressions) I want to share how I built it. In the text post will cover deployment and CI/CD setup. In case you want to look at the code, head over to the GitHub repo.
First: what is regex.help? It’s a web interface for
grex, which basically writes regex for you. Given a couple of example strings you want to match, grex will generate a regular expression matching all of them. That’s pretty much it, although quoting the README: “often, the resulting expression is still longer or more complex than it needs to be” so you might want to adjust it by hand. You can do that interactively on regex.help while getting real-time feedback for each of the examples you specified.
This is the second side-project I’ve built using Elixir, Phoenix and LiveView (the first one was Secretwords). The stack is pretty much the same, including Tailwind for CSS. I was hoping I’ll have a use case for Alpine.js to close the loop and use the entire PETAL stack, alas, there was no need for any custom JS this time either.
The main difference this time was that
grex is a Rust library - so I had to figure out a way to bundle it with an Elixir app. Luckily, a bunch of people already spent a bunch of time on this and the resulting library,
rustler works pretty well. It’s not entirely mature and there were a couple of sharp egdes (here’s how to deal with them), but the API is pretty nice and overall it works like you’d expect.
This is pretty exciting! I feel like this stack is powerful: LiveView gives you so much power by itself and then it’s also pretty easy to combine with Rust in case you need to do anything computationally inensive.
Overall mapping how I wanted the app to work to code was straightforward, even if it took a while to get right. There components are:
- An event for modifying the input, that is the example strings we want to write a regex for. Every time we modify the input, we check whether it’s within some maximum allowed length (I found that giving
grexmore than 1000 characters OOM’s on the current infrastructure) and then ask
grexto generate a regex for us and output it.
- There are various binary flags
grexaccepts and we expose a subset of them. Every time a flag is toggled, we recompute the regex using the new settings.
- There’s also the option to edit the generated regex and check whether it still matches all the examples given. In this case, on every edit, we send both the updated regex and the examples to the rust library and get back a boolean vector specifying which lines matched.
- There’s a thin wrapper around the Rust library, which also defines the allowed flags.
- And the Rust library itself, which just build the arguments and passes them to the
- The only remaining part is the HTML template, which LiveView uses to render the page. It also took me a little while to get all the events working correctly, but there’s nothing inherently complicated there.
Overall this project was a joy: learning cool, new tech while creating something potentially useful. Also it was pretty quick to get working! I spent much more time setting up the infrastructure for deploys and the CI/CD pipeline for it, which I’ll cover in the next post.
Please let me know if you found this helpful, interesting, or have any feedback.