texc_config/
error.rs

1use crate::Config;
2use thiserror::Error;
3/// The TexCreate Errors that can occur
4/// - Beamer Error: When Beamer template is chosen, but doc_class isn't beamer
5/// - Invalid Template: Template doesn't exist
6/// - Invalid Document Class: Document Class doesn't exist
7/// - Empty Fields: A field in `config.toml` is left empty
8/// - IO Error: Error caused by `std::io::Error`
9/// - Invalid: Any other error
10#[derive(Error, Debug)]
11pub enum TexCreateError {
12    #[error(
13        "'{0}' document_class is illegal for Beamer Template!!!\nPlease set document_class to 'beamer'",
14    )]
15    BeamerError(String),
16    #[error("'{0}' is an invalid Template, use texcreate list for list of available templates")]
17    InvalidTemplate(String),
18    #[error("'{0}' is an invalid Document Class!")]
19    InvalidDocClass(String),
20    #[error("The '{0}' field has an empty value!")]
21    EmptyFields(String),
22    #[error("{0}")]
23    IOError(#[from] std::io::Error),
24    #[error("Invalid '{0}'")]
25    Invalid(String),
26    #[error("Cannot have both custom_template and template fields, please remove one of them!")]
27    BothTemplate,
28    #[error("Cannot find custom template directory, make sure to have files under '{0}'.")]
29    CannotFindCustom(String),
30    #[error("Cannot build project if no template field is present")]
31    MissingTemplate
32}
33
34fn valid_templates() -> Vec<&'static str> {
35    vec![
36        "Basic", "Book", "Math", "Theatre", "Code", "Novel", "Beamer", "Lachaise", "Lachaise-Mod", "Dictionary", "News"
37    ]
38}
39fn valid_classes() -> Vec<&'static str> {
40    vec![
41        "article", "IEEEtran", "proc", "minimal", "report", "book", "slides", "memoir", "letter",
42    ]
43}
44
45/// Result type for TexCreate
46pub type TexCreateResult<T> = std::result::Result<T, TexCreateError>;
47
48/// Checks if config has a beamer error, if so returns `TexCreateError::BeamerError`
49pub fn check_beamer_error(config: &Config) -> TexCreateResult<()> {
50    if config.template.is_none(){
51        return Ok(());
52    }
53    /*
54    Beamer error occurs when the Document class is
55    not set as beamer when the Beamer Template is chosen
56     */
57    if config.template.as_ref().unwrap() == "Beamer" && config.document_class != "beamer" {
58        Err(TexCreateError::BeamerError(config.document_class.clone()))
59    } else {
60        Ok(())
61    }
62}
63/// Explicit Missing Template Check
64/// This occurs when both `Config.template == None && Config.custom_template == None`
65pub fn check_missing_template(config: &Config) -> TexCreateResult<()>{
66    if config.template.is_none() && config.custom_template.is_none() {
67        return Err(TexCreateError::MissingTemplate);
68    }
69    Ok(())
70}
71
72/// Checks if config has an invalid template, if so returns `TexCreateError::InvalidTemplate`
73pub fn check_invalid_template(config: &Config) -> TexCreateResult<()> {
74    /*
75    Invalid template error occurs when a user enters a template that
76    does not exist, to do this we look at a vec and see if it matches
77     */
78    let template = match &config.template{
79        Some(a) => a.to_string(),
80        None => {
81            return if config.custom_template == None {
82                Err(TexCreateError::MissingTemplate)
83            } else {
84                Ok(())
85            }
86        }
87    };
88    if !valid_templates().contains(&template.as_str()) {
89        Err(TexCreateError::InvalidTemplate(template))
90    } else {
91        Ok(())
92    }
93}
94/// Checks if the config has an invalid document class, if so returns `TexCreateError::InvalidDocClass`
95pub fn check_invalid_class(config: &Config) -> TexCreateResult<()> {
96    /*
97    Invalid class error occurs when a user enters a document
98    class that does not exist, we look at a vec and see if it matches
99     */
100    if !valid_classes().contains(&config.document_class.as_str()) {
101        Err(TexCreateError::InvalidDocClass(
102            config.document_class.clone(),
103        ))
104    } else {
105        Ok(())
106    }
107}
108/// Checks if the config has any empty fields, if so returns `TexCreateError::EmptyFields`
109pub fn check_empty_field(config: &Config) -> TexCreateResult<()> {
110    check_missing_template(config)?;
111    /*
112    Checks each field if empty, ignores fields that are optional
113     */
114    if config.author.is_empty() {
115        Err(TexCreateError::EmptyFields("Author".to_string()))
116    } else if config.title.is_empty() {
117        Err(TexCreateError::EmptyFields("Title".to_string()))
118    } else if config.date.is_empty() {
119        Err(TexCreateError::EmptyFields("Date".to_string()))
120    } else if config.project_name.is_empty() {
121        Err(TexCreateError::EmptyFields("Project Name".to_string()))
122    } else if config.document_class.is_empty() {
123        Err(TexCreateError::EmptyFields("Document Class".to_string()))
124    } else if config.paper_size.is_empty() {
125        Err(TexCreateError::EmptyFields("Paper Size".to_string()))
126    } else if config.font_size.to_string().is_empty() {
127        Err(TexCreateError::EmptyFields("Font Size".to_string()))
128    } else {
129        Ok(())
130    }
131}
132/// Contains all checks helper functions into one function
133pub fn check_errors(config: &Config) -> Result<(), String> {
134    /*
135    Checks all errors in one function
136     */
137    if check_beamer_error(config).is_err(){
138        return match check_beamer_error(config){
139            Err(e) => Err(e.to_string()),
140            _ => Err("".to_string())
141        }
142    }
143    if check_invalid_class(config).is_err(){
144        return match check_invalid_class(config){
145            Err(e) => Err(e.to_string()),
146            _ => Err("".to_string())
147        }
148    }
149    if check_missing_template(config).is_err(){
150        return match check_missing_template(config){
151            Err(e) => Err(e.to_string()),
152            _ => Err("".to_string())
153        }
154    }
155    if check_invalid_template(config).is_err(){
156        return match check_invalid_template(config){
157            Err(e) => Err(e.to_string()),
158            _ => Err("".to_string())
159        }
160    }
161    if check_empty_field(config).is_err(){
162        return match check_empty_field(config){
163            Err(e) => Err(e.to_string()),
164            _ => Err("".to_string())
165        }
166    }
167    Ok(())
168}