envfmt v1.0.0
A while ago, I wrote about
releasing the first version of
envfmt
. It was a tiny library I built to solve a problem in another project,
and it turned into a great lesson on using Rust’s traits for testing.
Today, I’m excited to release envfmt
as v1.0.0.
This isn’t a release packed with new features. In fact, it’s the opposite. The goal of this release was to simplify, stabilize, and polish what was already there. It’s about making the crate a small, dependable tool that you can forget about once you add it to your project.
There are three main updates I want to talk about.
New Documentation Site
The auto-generated docs from cargo doc
are amazing, but I wanted a place to
show more practical examples and explain the library’s purpose more clearly.
So I built a documentation site with Astro. It covers
why you might want to use envfmt
and how to use its API, with copy-pasteable
examples. Writing good documentation is a skill I’m trying to improve, and this
was a fun little exercise.
Zero Dependencies
In my last post, I talked about how much I enjoyed using thiserror
to handle
errors. It was clean and made defining custom error types very easy.
But envfmt
is a tiny library. Its whole purpose is to do one small thing with
minimal fuss. As I thought about it more, even a single, small dependency felt
like it went against that spirit. I wanted it to be completely self-contained.
So, I removed thiserror
.
This meant I had to implement the standard library’s std::error::Error
and
std::fmt::Display
traits myself. Here’s what the Error
enum looks like now:
/// Represents errors that can occur during formatting.
#[derive(Debug, PartialEq)]
pub enum Error {
/// A required variable was not found in the context.
VariableNotFound(String),
/// A variable name was invalid, e.g `${}`.
InvalidVariableName(String),
/// The input string have an unclosed brace.
UnclosedBrace,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::VariableNotFound(var) => {
write!(f, "variable not found: '{}'", var)
}
Error::InvalidVariableName(var) => {
write!(f, "invalid variable name: '{}'", var)
}
Error::UnclosedBrace => {
write!(f, "unexpected end of input: missing closing brace '}}'")
}
}
}
}
impl std::error::Error for Error {}
It’s a little more code than the thiserror
version, for sure. But it’s not
complicated. And in return, envfmt
now has zero dependencies. It’s just my
code and the Rust standard library. For a utility this small, that trade-off
feels right. It was a good reminder that helper crates are great, but sometimes
just using the standard library directly is the simplest solution.
A Stable API
The final reason for the 1.0.0 release is to make a promise. The API is now stable.
The core functions, format
and format_with
, and the Context
trait are
solid. I don’t see them changing. By releasing a v1.0.0
, I’m saying that you
can depend on envfmt
and not worry about a cargo update
breaking your build.
For a low-level tool, that kind of stability is the most important feature.
And that’s it. envfmt
is a complete, tiny, and now stable tool. It does one
thing, and I hope it does it well. It was a fantastic learning project for me,
and I’m happy to finally call it “done”.
You can find the crate on crates.io, the code on GitHub, and the new docs at pyk.sh/envfmt.
Tags | rust , release , envfmt |
---|