summaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: cad09a774b5e85e39cddffd8b5c7245b668c8631 (plain)
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
mod cli;
mod config;
mod error;
mod macros;
mod stackexchange;

use crossterm::style::Color;
use error::{Error, ErrorKind};
use lazy_static::lazy_static;
use minimad::mad_inline;
use stackexchange::{LocalStorage, StackExchange};
use termimad::{CompoundStyle, MadSkin};

fn main() {
    (|| {
        let opts = cli::get_opts()?;
        let config = opts.config;
        let site = &config.site;
        let mut ls = LocalStorage::new()?;
        // TODO style configuration
        let mut skin = MadSkin::default();
        skin.inline_code = CompoundStyle::with_fg(Color::Cyan);
        skin.code_block.set_fgbg(Color::Cyan, termimad::gray(20));

        if opts.update_sites {
            ls.update_sites()?;
        }

        if opts.list_sites {
            let sites = ls.sites()?;
            let mut md = String::new();
            md.push_str("|:-:|:-:|\n");
            md.push_str("|Site Code|Site URL|\n");
            md.push_str("|-:|:-|\n");
            for s in sites.iter() {
                md.push_str(&format!("|{}|{}\n", s.api_site_parameter, s.site_url));
            }
            md.push_str("|-\n");
            termimad::print_text(&md);
            return Ok(());
        }

        match ls.validate_site(site) {
            Ok(true) => (),
            Ok(false) => {
                print_error!(skin, "$0 is not a valid StackExchange site.\n\n", site)?;
                // TODO what about using text wrapping feature?
                print_notice!(
                    skin,
                    "If you think this is incorrect, try running\n\
                    ```\n\
                    so --update-sites\n\
                    ```\n\
                    to update the cached site listing. You can also run `so --list-sites` \
                    to list all available sites.",
                )?;
                return Ok(());
            }
            Err(Error {
                kind: ErrorKind::EmptySites,
                ..
            }) => {
                // TODO use text wrapping feature
                print_error!(
                    skin,
                    "The cached site list is empty. This can likely be fixed by\n\n\
                    ```\n\
                    so --update-sites\n\
                    ```"
                )?;
                return Ok(());
            }
            Err(e) => return Err(e),
        }

        if let Some(q) = opts.query {
            let se = StackExchange::new(config);
            let que = se.search(&q)?;
            let ans = que
                .first()
                .ok_or_else(Error::no_results)?
                .answers
                .first()
                .ok_or_else(|| {
                    Error::from(
                        "StackExchange returned a question with no answers; \
                        this shouldn't be possible!",
                    )
                })?;
            // TODO eventually do this in the right place, e.g. abstract out md parser & do within threads
            let md = ans.body.replace("<kbd>", "**[").replace("</kbd>", "]**");
            skin.print_text(&md);
        }

        Ok(())
    })()
    .or_else(|e| print_error!(MadSkin::default(), "{}", &e.error))
    .unwrap_or_else(|e| {
        println!("{}", e.error);
    });
}

#[cfg(test)]
mod tests {

    #[test]
    fn test_main() {
        //TODO
    }
}