Ideally, we can always at least write the file out with as close to a filename as the user wants. Sometimes users are repetitive though and choose the same filenames over and over.
In these cases, we still want to write out a unique name.
We’ll try to use a numeric suffix if we try to use a name that is the same as another file.
for attempt in 0.. {
let mut dest = garden_path.join(if attempt == 0 {
filename.clone()
} else {
format!("{filename}{:03}", -attempt)
});
dest.set_extension("md");
if dest.exists() {
continue;
}
fs::rename(filepath, &dest)?;
break;
}
Infinite Ranges
0..
is the syntax for a Range
that starts at 0, counts up by 1, and never stops.
If we use this infinite range in a for
loop, we have to make sure we break the loop, or it will never end.
This does solve a problem for us though. If we’re at attempt
0, then we’re trying to write the file for the first time. If attempt
is greater than 0, we have to add the number we’re at to our filename.
fill formatters
If we’re at an attempt
greater than 0, then we’ll be using the number on the end of the file. Typically some sorting algorithms have issues with files that have different amounts of numbers, so instead of my-file-9
and my-file-10
, we want my-file-09
and my-file-10
.
Rust supports this in the format!
macro using the syntax {:03}
.
The curly braces are the formatter itself, then :
kicks off our formatting parameters. 0
is the “fill” parameter, and 3
is the amount of characters to fill.
This means that if we have a number that is less than 3 characters long, the left side of that number will be filled by 0
s until it reaches 3 characters.
Warning
file existence
We can then check if the garden path + filename + extension combination exists using dest.exists()
.
If it exists, then we need to continue the loop without executing any of the rest of the code, which we can do with continue
.
If it doesn’t exist, then we can rename our file with fs::rename
and break
out of the loop, stopping it.