1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::error::{Error, Result};
use std::str::FromStr;

#[derive(Debug, Clone, Copy)]
/// The results output options.
pub enum OutputOption {
    /// Only output links.
    Links,
    /// Output answer details, which contains code and plain text.
    All,
    /// Only output code in answer.
    OnlyCode,
}

#[derive(Debug, Clone, Copy)]
/// supported search engine definition.
pub enum SearchEngine {
    /// Microsoft bing search engine.
    Bing,
    /// Google search engine.
    Google,
    /// DuckDuckGo search engine.
    DuckDuckGo,
    /// Stackoverflow internal search.
    StackOverflow,
}

#[derive(Debug, Clone, Copy)]
/// The user config information is integrated here.
pub struct Config {
    /// Terminal output options.
    option: OutputOption,
    /// The number of answers to be output.
    numbers: u8,
    /// Indicate that the output code shoule be colorized or not.
    colorize: bool,
}

impl Config {
    pub fn new(output_option: OutputOption, numbers: u8, colorize: bool) -> Config {
        Config {
            option: output_option,
            numbers,
            colorize,
        }
    }

    pub fn option(&self) -> &OutputOption {
        &self.option
    }

    pub fn numbers(&self) -> u8 {
        self.numbers
    }

    pub fn colorize(&self) -> bool {
        self.colorize
    }
}

impl FromStr for SearchEngine {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        match s {
            "bing" => Ok(SearchEngine::Bing),
            "google" => Ok(SearchEngine::Google),
            "duckduckgo" => Ok(SearchEngine::DuckDuckGo),
            "stackoverflow" => Ok(SearchEngine::StackOverflow),
            _ => Err(Error::from_parse("Not supported search engine")),
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub enum PagingOption {
    Auto,
    Never,
}

impl FromStr for PagingOption {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        match s {
            "auto" => Ok(PagingOption::Auto),
            "never" => Ok(PagingOption::Never),
            _ => Err(Error::from_parse("Not supported paging option")),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_search_engine_from_str() {
        let search_engine = SearchEngine::from_str("bing");
        assert_eq!(search_engine.is_ok(), true);
        let search_engine = SearchEngine::from_str("google");
        assert_eq!(search_engine.is_ok(), true);
    }

    #[test]
    fn test_search_engine_from_invalid_str() {
        let search_engine = SearchEngine::from_str("what's this?");
        assert_eq!(search_engine.is_err(), true);
    }

    #[test]
    fn test_paging_option_from_str() {
        let paging_option = PagingOption::from_str("auto");
        assert_eq!(paging_option.is_ok(), true);
        let paging_option = PagingOption::from_str("never");
        assert_eq!(paging_option.is_ok(), true);
    }

    #[test]
    fn test_invalid_paging_option() {
        let paging_option = PagingOption::from_str("invalid");
        assert_eq!(paging_option.is_err(), true);
    }
}