In several of my personal projects I have a need for tilde
expansion, which means taking a filename such as ~/foo
and
expanding the tilde into the current user's home directory. For me,
that would result in /home/liw/foo
. This is ubiquitous in Unix, and
now unknown elsewhere. The usual tilde syntax is a little more complex
than that: one can refer to another user's home directory as well.
input | output |
---|---|
~ |
/home/liw |
~/foo |
/home/liw/foo |
~tomjon |
/home/tomjon |
~tomjon/foo |
/home/tomjon/foo |
I want to support tilde expansion in places such as configuration files. In such places can't rely on the shell to do the expansion for me, like I can for command line arguments. Thus, I would like a Rust crate to do this for me.
I have some requirements:
- The crate MUST support any valid filename on the system. It's NOT OK
to require the input filename to be UTF8 encoded. In practice this
probably means the input should be a
&Path
, orAsRef<Path>
. However, having variants that take a Rust string as input is OK. - The result MUST be a
Path
orPathBuf
. I'm NOT OK with getting a string, or even an array of bytes. It's not ergonomic to make the caller convert the result to a standard filename representation. I'm not even willing to write a wrapper to do the conversion: I want to be lazy. - The crate MUST report errors, especially for an input that refers to a non-existent user. I want my programs to be able to produce excellent error messages, and to not fail in ways the confuse the user.
- The crate MUST have a license that's compatible with my code. I tend to favor strong copyleft licenses, such as the GPL.
I found a bunch of crates to evaluate. Here are results.
- untildify
- deals with UTF8 strings only only, making this unacceptable to me
- uses the WTFPL license, which is also unacceptable to me
- tilde-expand
- deals with byte strings, not
Path
orPathBuf
- does not handle errors in a useful way
- gets unknown user wrong on my system (/var/lib/nfs)
- deals with byte strings, not
- shellexpand
- currently unmaintained
- also does shell variable expansion but has function for just tilde expansion so that's OK
- input and output are both UTF8 strings
- doesn't handled
~liw
as input, returning~liw
- does not give good error for unknown user, returns the input string in that case
- home-dir
- lacks README on crates.io
- defines a trait that adds an
expand_home
to types that implement the trait - implements the trait for
Path
and&Path
, so that's acceptable - handles errors, though the error message for a non-existent user could be improved
- documentation could be better: for example, it lacks an example on front page
- expanduser
- lacks README on crates.io
- takes a UTF8 string as input, which is not good enough for me
- return a result, using
std::io::ErrorKind::Other
to indicate a non-existent user, which I could live with, but could be improved
Of these, I'm leaning towards using the home-dir
crate. I'll offer
changes to improve its documentation and other aspects of it I wish
were better.