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..fd38f91 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 separator string to seperate the url from the name. defaults to : with a space after that." + )] + pub(crate) separator: 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..13be1e4 --- /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, + separator: &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, separator) + ); + + 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..ca60815 --- /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, + separator: &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, separator, group); + } + + for site in names { + if json { + json_printing(&site)?; + continue; + } + + printing(separator, &site, group); + } + + Ok(()) +} + +fn filter_site( + site: &Site, + json: bool, + separator: &String, + group: &PrintGroup, +) -> Result<(), Error> { + if json { + json_printing(site)?; + return Ok(()); + } + + return Ok(printing(separator, 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(separator: &String, site: &Site, group: &PrintGroup) { + let string = site_string(site, print_group_to_options(group), separator); + + 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..603d94f --- /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, separator: &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, separator) + ); + } + &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..61ab040 --- /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, separator: &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!("{}{}", separator, name) + } else { + string += name; + } + } + + return string; +} diff --git a/cli/src/main.rs b/cli/src/main.rs index 84d4e48..39f429b 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 separator = args.separator.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, &separator, *json)?, + Commands::Add { url, name } => add(path, url, name, &separator)?, + Commands::Remove { url } => remove(path, url, &separator)?, }; Ok(())