From 82e8f68862c25847bd1e1a27e17560758435d74f Mon Sep 17 00:00:00 2001 From: Fries Date: Sun, 2 Jul 2023 19:46:19 -0700 Subject: [PATCH] make printing less complicated and refactor cli i made printing less complicated by making printing both the name and the url with the seperator the default option and using both those flags at the same time should do the same thing as just printing without any flags. i also refactored commands into their own module folder with each command getting their own file module. --- .vscode/launch.json | 61 ++++++++++++++-- cli/Cargo.toml | 3 +- cli/src/arguments.rs | 15 ++-- cli/src/commands.rs | 141 ------------------------------------- cli/src/commands/add.rs | 43 +++++++++++ cli/src/commands/mod.rs | 8 +++ cli/src/commands/print.rs | 88 +++++++++++++++++++++++ cli/src/commands/remove.rs | 23 ++++++ cli/src/commands/utils.rs | 28 ++++++++ cli/src/main.rs | 13 ++-- 10 files changed, 261 insertions(+), 162 deletions(-) delete mode 100644 cli/src/commands.rs create mode 100644 cli/src/commands/add.rs create mode 100644 cli/src/commands/mod.rs create mode 100644 cli/src/commands/print.rs create mode 100644 cli/src/commands/remove.rs create mode 100644 cli/src/commands/utils.rs diff --git a/.vscode/launch.json b/.vscode/launch.json index abb9e2b..6580fad 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,15 +1,62 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ { "type": "lldb", "request": "launch", - "name": "run meowy-cli", + "name": "meowy-cli (Print)", "program": "${workspaceFolder}/target/debug/meowy-cli", - "args": ["print"], + "args": [ + "print" + ], + "cwd": "${workspaceFolder}", + "sourceMap": {}, + "sourceLanguages": [ + "rust" + ], + }, + { + "type": "lldb", + "request": "launch", + "name": "meowy-cli (Print) json", + "program": "${workspaceFolder}/target/debug/meowy-cli", + "args": [ + "print", + "--json" + ], + "cwd": "${workspaceFolder}", + "sourceMap": {}, + "sourceLanguages": [ + "rust" + ], + }, + { + "type": "lldb", + "request": "launch", + "name": "meowy-cli (Print) only url", + "program": "${workspaceFolder}/target/debug/meowy-cli", + "args": [ + "print", + "--url" + ], + "cwd": "${workspaceFolder}", + "sourceMap": {}, + "sourceLanguages": [ + "rust" + ], + }, + { + "type": "lldb", + "request": "launch", + "name": "meowy-cli (Print) only name", + "program": "${workspaceFolder}/target/debug/meowy-cli", + "args": [ + "print", + "--name" + ], "cwd": "${workspaceFolder}", "sourceMap": {}, "sourceLanguages": [ diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 58e580d..33f5761 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -9,7 +9,7 @@ serde_json = "1.0" log = "0.4" [dependencies.clap] -version = "4" +version = "4" features = ["derive"] [dependencies.shared] @@ -18,6 +18,7 @@ path = "../shared" [dependencies.simple_logger] version = "4" default-features = false +features = ["stderr"] [[bin]] name = "meowy-cli" diff --git a/cli/src/arguments.rs b/cli/src/arguments.rs index 5175d19..3c098b5 100644 --- a/cli/src/arguments.rs +++ b/cli/src/arguments.rs @@ -5,6 +5,12 @@ use clap::{arg, command, Args, Parser, Subcommand}; pub(crate) struct Arguments { #[arg(help = "the path to the names.json file", long, short)] pub(crate) path: Option, + #[arg( + long, + short, + help = "a seperator string to seperate the url from the name. defaults to : with a space after that." + )] + pub(crate) seperator: Option, #[command(subcommand)] pub(crate) command: Commands, } @@ -17,20 +23,11 @@ pub(crate) enum Commands { filter: Option, #[command(flatten)] group: PrintGroup, - #[arg( - long, - short, - help = "a seperator character to seperate the url from the name. defaults to ,", - requires = "url", - requires = "name" - )] - seperator: Option, #[arg( long, short, conflicts_with = "url", conflicts_with = "name", - conflicts_with = "seperator", help = "print the data out as a json string" )] json: bool, diff --git a/cli/src/commands.rs b/cli/src/commands.rs deleted file mode 100644 index 24f91c6..0000000 --- a/cli/src/commands.rs +++ /dev/null @@ -1,141 +0,0 @@ -use std::path::Path; - -use shared::errors::ErrorStatus; -use shared::names; -use shared::{errors::Error, names::Site}; - -use crate::arguments::PrintGroup; - -fn group_printing(seperator: &Option, site: &Site, group: &PrintGroup) { - let mut string = String::new(); - let delimiter = seperator.unwrap_or(','); - - if group.url { - string += &site.url; - } - - if group.name { - if !string.is_empty() { - string += &format!( - "{}{}", - delimiter, - site.name.as_ref().unwrap_or(&"None".into()) - ) - } else { - string += &site.name.as_ref().unwrap_or(&"None".into()); - } - } - - log::info!("{}", string); -} - -fn json_printing(site: &Site) -> Result<(), Error> { - match serde_json::to_string(&site) { - Ok(json) => { - log::info!("{}", json); - Ok(()) - } - Err(err) => Err(Error { - status: ErrorStatus::ParsingError, - data: err.to_string(), - }), - } -} - -fn filter_site( - site: &Site, - json: bool, - seperator: &Option, - group: &PrintGroup, -) -> Result<(), Error> { - if json { - json_printing(site)?; - return Ok(()); - } - - if !group.url && !group.name { - log::info!("{:?}", site); - return Ok(()); - } - - return Ok(group_printing(seperator, site, group)); -} - -pub(crate) fn print( - path: &Path, - filter: &Option, - group: &PrintGroup, - seperator: &Option, - json: bool, -) -> Result<(), Error> { - let names_file = names::read_names_file(path)?; - let mut names = names::load_names(names_file)?; - - if let Some(filter) = filter { - names.retain(|f| &f.url == filter); - if names.len() == 0 { - return Err(Error { - status: ErrorStatus::NotFoundError, - data: "this url was not found in names.json".into(), - }); - } - return filter_site(&names[0], json, seperator, group); - } - - for site in names { - if json { - json_printing(&site)?; - continue; - } - - if !group.url && !group.name { - log::info!("{:?}", site); - continue; - } - - group_printing(seperator, &site, group); - } - - Ok(()) -} - -pub(crate) fn add(path: &Path, url: &String, name: &Option) -> Result<(), Error> { - let names_file = names::read_names_file(path)?; - let mut names = names::load_names(names_file)?; - - if names.iter().any(|site| site.url.contains(url)) { - return Err(Error { - status: ErrorStatus::AlreadyExistsError, - data: - "this url already exists in names.json. you can't have more then 1 of the same url." - .into(), - }); - } - - let site = Site { - url: url.to_string(), - name: name.to_owned(), - }; - log::debug!("adding {:?} to {}", site, path.display()); - names.push(site.clone()); - let json = serde_json::to_string(&names).unwrap(); - std::fs::write(path, json).unwrap(); - log::info!("added {:?} to names.json", site); - Ok(()) -} - -pub(crate) fn remove(path: &Path, url: &String) -> Result<(), Error> { - let names_file = names::read_names_file(path)?; - let mut names = names::load_names(names_file)?; - - names.retain(|site| { - if &site.url == url { - log::info!("removing {:?} from names.json", site); - } - &site.url != url - }); - let json = serde_json::to_string(&names).unwrap(); - std::fs::write(path, json).unwrap(); - - Ok(()) -} diff --git a/cli/src/commands/add.rs b/cli/src/commands/add.rs new file mode 100644 index 0000000..042ef8d --- /dev/null +++ b/cli/src/commands/add.rs @@ -0,0 +1,43 @@ +use shared::{ + errors::{Error, ErrorStatus}, + names::{self, Site}, +}; +use std::path::Path; + +use crate::commands::utils::{site_string, PrintOptions}; + +pub(crate) fn add( + path: &Path, + url: &String, + name: &Option, + seperator: &String, +) -> Result<(), Error> { + let names_file = names::read_names_file(path)?; + let mut names = names::load_names(names_file)?; + + if names.iter().any(|site| site.url.contains(url)) { + return Err(Error { + status: ErrorStatus::AlreadyExistsError, + data: + "this url already exists in names.json. you can't have more then 1 of the same url." + .into(), + }); + } + + let site = Site { + url: url.to_string(), + name: name.to_owned(), + }; + + log::debug!("adding {:?} to {}", site, path.display()); + names.push(site.clone()); + + let json = serde_json::to_string(&names).unwrap(); + std::fs::write(path, json).unwrap(); + println!( + "added {} to names.json", + site_string(&site, PrintOptions::All, seperator) + ); + + Ok(()) +} diff --git a/cli/src/commands/mod.rs b/cli/src/commands/mod.rs new file mode 100644 index 0000000..a9779dc --- /dev/null +++ b/cli/src/commands/mod.rs @@ -0,0 +1,8 @@ +mod add; +mod print; +mod remove; +mod utils; + +pub(crate) use add::add; +pub(crate) use print::print; +pub(crate) use remove::remove; diff --git a/cli/src/commands/print.rs b/cli/src/commands/print.rs new file mode 100644 index 0000000..066dce4 --- /dev/null +++ b/cli/src/commands/print.rs @@ -0,0 +1,88 @@ +use crate::{arguments::PrintGroup, commands::utils::site_string}; +use shared::{ + errors::{Error, ErrorStatus}, + names::{self, Site}, +}; +use std::path::Path; + +use super::utils::PrintOptions; + +pub(crate) fn print( + path: &Path, + filter: &Option, + group: &PrintGroup, + seperator: &String, + json: bool, +) -> Result<(), Error> { + let names_file = names::read_names_file(path)?; + let mut names = names::load_names(names_file)?; + + if let Some(filter) = filter { + names.retain(|f| &f.url == filter); + if names.len() == 0 { + return Err(Error { + status: ErrorStatus::NotFoundError, + data: "this url was not found in names.json".into(), + }); + } + return filter_site(&names[0], json, seperator, group); + } + + for site in names { + if json { + json_printing(&site)?; + continue; + } + + printing(seperator, &site, group); + } + + Ok(()) +} + +fn filter_site( + site: &Site, + json: bool, + seperator: &String, + group: &PrintGroup, +) -> Result<(), Error> { + if json { + json_printing(site)?; + return Ok(()); + } + + return Ok(printing(seperator, site, group)); +} + +fn json_printing(site: &Site) -> Result<(), Error> { + match serde_json::to_string(&site) { + Ok(json) => { + println!("{}", json); + Ok(()) + } + Err(err) => Err(Error { + status: ErrorStatus::ParsingError, + data: err.to_string(), + }), + } +} + +fn printing(seperator: &String, site: &Site, group: &PrintGroup) { + let string = site_string(site, print_group_to_options(group), seperator); + + println!("{}", string); +} + +fn print_group_to_options(group: &PrintGroup) -> PrintOptions { + match group { + PrintGroup { + url: true, + name: false, + } => PrintOptions::Url, + PrintGroup { + url: false, + name: true, + } => PrintOptions::Name, + _ => PrintOptions::All, + } +} diff --git a/cli/src/commands/remove.rs b/cli/src/commands/remove.rs new file mode 100644 index 0000000..4e7906c --- /dev/null +++ b/cli/src/commands/remove.rs @@ -0,0 +1,23 @@ +use shared::{errors::Error, names}; +use std::path::Path; + +use crate::commands::utils::{site_string, PrintOptions}; + +pub(crate) fn remove(path: &Path, url: &String, seperator: &String) -> Result<(), Error> { + let names_file = names::read_names_file(path)?; + let mut names = names::load_names(names_file)?; + + names.retain(|site| { + if &site.url == url { + println!( + "removing {} from names.json", + site_string(&site, PrintOptions::All, seperator) + ); + } + &site.url != url + }); + let json = serde_json::to_string(&names).unwrap(); + std::fs::write(path, json).unwrap(); + + Ok(()) +} diff --git a/cli/src/commands/utils.rs b/cli/src/commands/utils.rs new file mode 100644 index 0000000..426975b --- /dev/null +++ b/cli/src/commands/utils.rs @@ -0,0 +1,28 @@ +use shared::names::Site; + +pub(super) enum PrintOptions { + Url, + Name, + All, +} + +pub(super) fn site_string(site: &Site, options: PrintOptions, seperator: &String) -> String { + let mut string = String::new(); + + if matches!(options, PrintOptions::Url) || matches!(options, PrintOptions::All) { + string += &site.url; + } + + if let Some(name) = &site.name { + if matches!(options, PrintOptions::Url) { + return string; + } + if !string.is_empty() { + string += &format!("{}{}", seperator, name) + } else { + string += name; + } + } + + return string; +} diff --git a/cli/src/main.rs b/cli/src/main.rs index 84d4e48..2b070dd 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,8 +1,8 @@ -use std::path::Path; use arguments::{Arguments, Commands}; use clap::Parser; use commands::{add, print, remove}; use shared::{directories, errors::Error}; +use std::path::Path; mod arguments; mod commands; @@ -13,6 +13,7 @@ fn main() -> Result<(), Error> { let default_path = directories::get_names_path()?; let args = Arguments::parse(); + let seperator = args.seperator.unwrap_or(": ".into()); let path = match &args.path { Some(path) => Path::new(path), @@ -20,9 +21,13 @@ fn main() -> Result<(), Error> { }; match &args.command { - Commands::Print { filter, group, seperator, json, } => print(path, filter, group, seperator, *json)?, - Commands::Add { url, name } => add(path, url, name)?, - Commands::Remove { url } => remove(path, url)?, + Commands::Print { + filter, + group, + json, + } => print(path, filter, group, &seperator, *json)?, + Commands::Add { url, name } => add(path, url, name, &seperator)?, + Commands::Remove { url } => remove(path, url, &seperator)?, }; Ok(())