diff --git a/src/cmd/check.rs b/src/cmd/check.rs index 21fa425..3f2193e 100644 --- a/src/cmd/check.rs +++ b/src/cmd/check.rs @@ -25,6 +25,7 @@ pub enum OsedaCheckError { DirectoryNameMismatch(String), CouldNotPingLocalPresentation(String), MissingDescription(String), + MissingTags(String), } impl std::error::Error for OsedaCheckError {} @@ -33,17 +34,20 @@ impl std::error::Error for OsedaCheckError {} impl std::fmt::Display for OsedaCheckError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::MissingConfig(msg) => write!(f, "Missing config file {}", msg), - Self::BadConfig(msg) => write!(f, "Bad config file {}", msg), - Self::BadGitCredentials(msg) => write!(f, "Missing git credentials {}", msg), + Self::MissingConfig(msg) => write!(f, "Missing config file: {}", msg), + Self::BadConfig(msg) => write!(f, "Bad config file: {}", msg), + Self::BadGitCredentials(msg) => write!(f, "Missing git credentials: {}", msg), Self::DirectoryNameMismatch(msg) => { - write!(f, "Project name does not match directory {}", msg) + write!(f, "Project name does not match directory: {}", msg) } Self::CouldNotPingLocalPresentation(msg) => { - write!(f, "Could not ping localhost after project was ran {}", msg) + write!(f, "Could not ping localhost after project was ran: {}", msg) } Self::MissingDescription(msg) => { - write!(f, "Config file is missing description {}", msg) + write!(f, "Config file is missing description: {}", msg) + } + Self::MissingTags(msg) => { + write!(f, "No tags detected: {}", msg) } } } diff --git a/src/cmd/export.rs b/src/cmd/export.rs index 65f81a9..7ce0dec 100644 --- a/src/cmd/export.rs +++ b/src/cmd/export.rs @@ -20,13 +20,18 @@ use crate::{ #[derive(Args, Debug, Clone)] pub struct ExportOptions { /// String name of the output PDF file - #[arg(long, default_value_t = get_default_output())] - pub output: String, + pub output: Option, /// Port the project runs on #[arg(long, default_value_t = 3000)] pub port: u16, } +impl ExportOptions { + pub fn output_or_default(&self) -> String { + self.output.clone().unwrap_or_else(get_default_output) + } +} + fn get_default_output() -> String { let default = String::from("slides.pdf"); @@ -79,7 +84,13 @@ pub fn export(opts: ExportOptions) -> Result<(), Box> { // run decktape, assuming the server has spun up by now let export_output = Command::new("npm") - .args(["exec", "decktape", "reveal", &addr, &opts.output]) + .args([ + "exec", + "decktape", + "reveal", + &addr, + &opts.output_or_default(), + ]) .output()?; // send shutdown flag, should signal to run_with_shutdown to kill the process diff --git a/src/config.rs b/src/config.rs index 6d978f3..301a275 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,7 +13,7 @@ use crate::cmd::check::OsedaCheckError; use crate::cmd::init::InitOptions; use crate::color::Color; use crate::github; -use crate::tags::Tag; +use crate::tags::DefinedTag; pub fn read_config_file>( path: P, @@ -101,6 +101,12 @@ pub fn validate_config( )); } + if conf.tags.is_empty() { + return Err(OsedaCheckError::MissingTags( + "Please add tags to oseda-config.json".to_owned(), + )); + } + Ok(()) } @@ -109,7 +115,7 @@ pub fn validate_config( pub struct OsedaConfig { pub title: String, pub author: String, - pub tags: Vec, + pub tags: Vec, // effectively mutable. Will get updated on each deployment pub last_updated: DateTime, pub color: String, @@ -143,12 +149,12 @@ pub fn create_conf(options: InitOptions) -> Result> None => prompt_for_title()?.replace(" ", "-"), }; - let tags = match options.tags { + let defined_tags = match options.tags { Some(arg_tags) => { arg_tags .iter() - .map(|arg_tag| Tag::from_str(arg_tag)) - .collect::, _>>() + .map(|arg_tag| DefinedTag::from_str(arg_tag)) + .collect::, _>>() .map_err(|_| "Invalid tag. Custom Tags may be added to the oseda-config.json after initialization".to_string())? }, None => prompt_for_tags()? @@ -166,7 +172,10 @@ pub fn create_conf(options: InitOptions) -> Result> Ok(OsedaConfig { title: title.trim().to_owned(), author: user_name, - tags, + tags: defined_tags + .into_iter() + .map(|t: DefinedTag| DefinedTag::to_string(&t)) + .collect(), last_updated: get_time(), color: color.into_hex(), // start them with empty description @@ -179,8 +188,8 @@ pub fn create_conf(options: InitOptions) -> Result> /// # Returns /// * `Ok(Vec)` with selected categories /// * `Err` if the prompting went wrong somewhere -fn prompt_for_tags() -> Result, Box> { - let options: Vec = Tag::iter().collect(); +fn prompt_for_tags() -> Result, Box> { + let options: Vec = DefinedTag::iter().collect(); let selected_tags = inquire::MultiSelect::new("Select categories (type to search):", options.clone()) @@ -252,6 +261,7 @@ pub fn write_config(path: &str, conf: &OsedaConfig) -> Result<(), Box #[cfg(test)] mod test { + use crate::tags::DefinedTag; use std::path::Path; use tempfile::tempdir; @@ -285,7 +295,7 @@ mod test { let conf = OsedaConfig { title: "my-project".to_string(), author: "JaneDoe".to_string(), - tags: vec![Tag::ComputerScience], + tags: vec![DefinedTag::ComputerScience.to_string()], last_updated: chrono::Utc::now(), color: Color::Black.into_hex(), description: String::from("Test Description"), @@ -303,7 +313,7 @@ mod test { let conf = OsedaConfig { title: "my-project".to_string(), author: "JaneDoe".to_string(), - tags: vec![Tag::ComputerScience], + tags: vec![DefinedTag::ComputerScience.to_string()], last_updated: chrono::Utc::now(), color: Color::Black.into_hex(), description: String::from("Test Description"), @@ -321,7 +331,7 @@ mod test { let conf = OsedaConfig { title: "correct-name".to_string(), author: "JaneDoe".to_string(), - tags: vec![Tag::ComputerScience], + tags: vec![DefinedTag::ComputerScience.to_string()], last_updated: chrono::Utc::now(), color: Color::Black.into_hex(), description: String::new(), @@ -341,7 +351,7 @@ mod test { let conf = OsedaConfig { title: "oseda".to_string(), author: "JaneDoe".to_string(), - tags: vec![Tag::ComputerScience], + tags: vec![DefinedTag::ComputerScience.to_string()], last_updated: chrono::Utc::now(), color: Color::Black.into_hex(), description: String::from("Test Description"), diff --git a/src/tags.rs b/src/tags.rs index e95f061..003ddf0 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -4,7 +4,7 @@ use strum_macros::{Display, EnumIter, EnumString}; #[derive(Serialize, Deserialize, Debug, Clone, Copy, Display, EnumIter, EnumString)] #[strum(ascii_case_insensitive)] -pub enum Tag { +pub enum DefinedTag { Aerospace, Business, ComputerScience, @@ -20,13 +20,16 @@ pub enum Tag { Politics, Psychology, Science, - // Custom(String), } -// TODO document me -// Custom tags must be added by hand to the oseda-config.json -impl Tag { - pub fn to_vec() -> Vec { - Tag::iter().collect() +impl From for String { + fn from(tag: DefinedTag) -> Self { + tag.to_string() + } +} + +impl DefinedTag { + pub fn to_vec() -> Vec { + DefinedTag::iter().collect() } }