summaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: e6e36d966ffbbde53f3dc02f4e1fb949ccd81d05 (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
111
112
113
114
115
116
117
118
#![warn(clippy::all)]

//mod doxygen;
mod cli;
mod config;
mod entities;
mod generator;
mod pandoc;
mod parsing;

#[macro_use]
extern crate log;

use cli::{Command, ConfigCommand};
use generator::generate;
use parsing::parse_file;

use anyhow::{Context, Result};
use codemap::CodeMap;
use codemap_diagnostic::{Diagnostic, Emitter, Level};
use structopt::StructOpt;

fn into_diagnostic(err: &anyhow::Error) -> Diagnostic {
    if let Some(err) = err.downcast_ref::<config::ConfigLoadError>() {
        err.into()
    } else {
        Diagnostic {
            level: Level::Error,
            message: err.to_string(),
            code: None,
            spans: vec![],
        }
    }
}

fn main() {
    let mut codemap = CodeMap::new();

    match start(&mut codemap) {
        Ok(()) => {}
        Err(err) => {
            let mut emitter =
                Emitter::stderr(codemap_diagnostic::ColorConfig::Auto, Some(&codemap));

            let mut diagnostics = Vec::new();
            diagnostics.push(into_diagnostic(&err));

            if let Some(mut source) = err.source() {
                diagnostics.push(Diagnostic {
                    level: Level::Note,
                    message: format!("Caused by: {}", source),
                    code: None,
                    spans: vec![],
                });
                while let Some(source2) = source.source() {
                    source = source2;
                    diagnostics.push(Diagnostic {
                        level: Level::Note,
                        message: format!("Caused by: {}", source),
                        code: None,
                        spans: vec![],
                    });
                }
            }
            emitter.emit(&diagnostics);
        }
    }
}

fn start(codemap: &mut CodeMap) -> Result<()> {
    let cli = cli::Cli::from_args();
    pretty_env_logger::formatted_builder()
        .filter(
            None,
            match cli.verbosity {
                // Warnings and errors for internal warnings / errors
                0 => log::LevelFilter::Warn,
                1 => log::LevelFilter::Info,
                2 => log::LevelFilter::Debug,
                _ => log::LevelFilter::Trace,
            },
        )
        .try_init()?;

    std::env::set_current_dir(&cli.directory)
        .with_context(|| format!("Cannot change current directory to: {:?}", cli.directory))?;

    match &cli.command {
        Command::Generate { file } => {
            let file = file.clone();
            let config = load_effective_config(cli, codemap)?;

            let manager = parse_file(file, &config.extra_clang_args);

            let base_output_dir = std::path::Path::new("doc");
            generate(&base_output_dir, manager, &config)?;
        }
        Command::Config {
            command: ConfigCommand::Default,
        } => {
            print!("{}", toml::to_string_pretty(&config::Config::default())?);
        }
        Command::Config {
            command: ConfigCommand::Show,
        } => {
            print!(
                "{}",
                toml::to_string_pretty(&config::load_config(".", codemap)?)?
            );
        }
    }

    Ok(())
}

fn load_effective_config(cli: cli::Cli, codemap: &mut CodeMap) -> Result<config::Config> {
    Ok(config::load_config(".", codemap)?.merge_cli(cli))
}