To rename the temporary file, we need a file name to move it to inside of our garden directory.
use edit::{edit_file, Builder};
use std::{fs, io::Write, path::PathBuf};
pub fn write(
garden_path: PathBuf,
title: Option<String>,
) -> Result<(), std::io::Error> {
let (mut file, filepath) = Builder::new()
.suffix(".md")
.rand_bytes(5)
.tempfile_in(&garden_path)?
.keep()?;
dbg!(&filepath);
let template =
format!("# {}", title.as_deref().unwrap_or(""));
file.write_all(template.as_bytes())?;
edit_file(&filepath)?;
let contents = fs::read_to_string(&filepath)?;
let document_title = title.or_else(|| {
contents.lines().find(|v| v.starts_with("# ")).map(
|line| {
line.trim_start_matches("# ").to_string()
},
)
});
let filename = match document_title {
Some(raw_title) => slug::slugify(raw_title),
None => {
todo!("ask for filename");
}
};
let mut dest = garden_path.join(filename);
dest.set_extension("md");
fs::rename(filepath, &dest)?;
dbg!(dest);
Ok(())
}
We’ll start out by matching on the document_title
, which could be Some
or None
.
If its Some
, then we’ll use the slug
crate to slugify
the title into something without spaces.
If its None
, we’ll use a todo!()
, macro to panic if we hit that branch. The todo!
macro is nice because it short-circuits type inference, meaning that we don’t need to return random values to get our program to compile.
We get to say “We’ll do this later”.
let filename = match document_title {
Some(raw_title) => slug::slugify(raw_title),
None => {
todo!("ask for filename");
}
};
❯ cargo add slug
Updating crates.io index
Adding slug v0.1.4 to dependencies.
Updating crates.io index
If there ends up being no title, then we’ll see our program panic
thread 'main' panicked at 'not yet implemented: ask for filename', src/lib.rs:31:13
Renaming files
After getting the appropriate title, renaming the file from the temporary location to the designed final location is straightforward.
Take the garden_path
which is a PathBuf
, and join
it with the filename.
Then set the extension for the file to .md
.
and use std::fs::rename
to rename the original temporary file path to the new destination.
let mut dest = garden_path.join(filename);
dest.set_extension("md");
fs::rename(filepath, &dest)?;
dbg!(dest);
fs::rename
is another function that returns an io::Error
for its error, so we get to use ?
again.
Running
and now when we run
❯ cargo run -- write
Compiling garden v0.1.0 (/rust-adventure/digital-garden)
Finished dev [unoptimized + debuginfo] target(s) in 0.57s
Running `target/debug/garden write`
[src/lib.rs:13] &filepath = "/Users/chris/garden/.tmpWNu0x.md"
[src/lib.rs:38] dest = "/Users/chris/garden/some-file.md"
and the file contents are in that file
❯ cat /Users/chris/garden/some-file.md
# some file