From d57ed908e29b86a7e8a0c699986a35325dce7d77 Mon Sep 17 00:00:00 2001 From: Adrian Wannenmacher Date: Sat, 30 Sep 2023 03:26:52 +0200 Subject: [PATCH] list listing and list info --- src/cli/list.rs | 16 +++++++++++++--- src/main.rs | 27 +++++++++++++++++++-------- src/store.rs | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/src/cli/list.rs b/src/cli/list.rs index 9d59bc3..f6cf516 100644 --- a/src/cli/list.rs +++ b/src/cli/list.rs @@ -3,7 +3,7 @@ use clap::Subcommand; #[derive(Debug, Subcommand)] pub enum ListCommand { /// Create a new download list. - #[clap(visible_alias = "new", visible_alias = "c")] + #[clap(visible_alias = "c", visible_alias = "new")] Create { /// A unique name, which will be used to refer to the list. name: String, @@ -12,12 +12,22 @@ pub enum ListCommand { description: String, }, /// Delete a download list. - #[clap(visible_alias = "rm", visible_alias = "d")] + #[clap(visible_alias = "d", visible_alias = "rm")] Delete { /// The name of the list to remove. name: String, }, - /// Update an existing list. + /// Print a download lists properties. + /// + #[clap(visible_alias = "i", visible_alias = "show")] + Info { + /// The name of the list to inspect. + name: String, + }, + /// List all known download lists. + #[clap(visible_alias = "l", visible_alias = "ls")] + List, + /// Update an existing download list. /// /// Only values specified for this command are changed. #[clap(visible_alias = "u")] diff --git a/src/main.rs b/src/main.rs index fed175c..59b3176 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,25 @@ fn main() -> anyhow::Result<()> { match cli.command { cli::Command::List { command } => match command { + cli::ListCommand::Create { name, description } => { + let mut list = DownloadListStore::new(name, &data)?; + + list.set_description(description); + + list.save() + } + cli::ListCommand::Delete { name } => DownloadListStore::delete(&name, &data), + cli::ListCommand::Info { name } => { + let list = DownloadListStore::load(&name, &data)?; + + println!("name: {}", list.name()); + println!("description: {}", list.description()); + + Ok(()) + } + cli::ListCommand::List => Ok(DownloadListStore::list(&data)? + .into_iter() + .for_each(|n| println!("{n}"))), cli::ListCommand::Update { name, description } => { let mut list = DownloadListStore::load(&name, &data)?; @@ -29,14 +48,6 @@ fn main() -> anyhow::Result<()> { list.save() } - cli::ListCommand::Create { name, description } => { - let mut list = DownloadListStore::new(name, &data)?; - - list.set_description(description); - - list.save() - } - cli::ListCommand::Delete { name } => DownloadListStore::delete(&name, &data), }, } } diff --git a/src/store.rs b/src/store.rs index bb7ea9a..fd2197c 100644 --- a/src/store.rs +++ b/src/store.rs @@ -1,11 +1,12 @@ use std::{ + collections::HashSet, fs::{self, File, OpenOptions}, io::{BufReader, BufWriter, Seek}, ops::{Deref, DerefMut}, path::Path, }; -use anyhow::{ensure, Context}; +use anyhow::{anyhow, ensure, Context}; use fs4::FileExt; use crate::data::DownloadList; @@ -83,6 +84,40 @@ impl DownloadListStore { .context("failed to remove list file") } + /// Get a all list names inside `directory`. + pub fn list(directory: &Path) -> anyhow::Result> { + let ls = fs::read_dir(directory).context("failed to read list file directory")?; + + // 6 steps process: + // + // 1. turn the entry into a file name + ls.map(|pe| { + pe.map(|e| { + e.file_name() + // 2. turn file name into string + .to_str() + .map(ToString::to_string) + .ok_or(anyhow!("os string not string")) + // 3. try to remove the `.json` suffix from the file name + .map(|n| n.strip_suffix(".json").map(ToString::to_string)) + }) + }) + // 4. remove all files that had no `.json` suffix + .filter(|e| match e { + Ok(Ok(None)) => false, + _ => true, + }) + // 5. flatten read error and os string error + .map(|e| match e { + Ok(Ok(x)) => Ok(x.expect("none filtered out before")), + Ok(Err(e)) => Err(e), + Err(e) => Err(e).context("failed to read list file directory entry"), + }) + // 6. handle errors & collect return + .collect::>() + .context("failed to list lists") + } + fn path_in_directory(directory: &Path, name: &str) -> std::path::PathBuf { directory.join(name).with_extension("json") }