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
#![warn(clippy::all)]

#[macro_use]
extern crate strum;

use std::io::{self, Write};

use serde::Serialize;
use structopt::StructOpt;
use strum::VariantNames;

use acick_atcoder as atcoder;
use acick_config as config;
use acick_util::{abs_path, console, model, service};

mod cmd;
mod judge;

use crate::cmd::{Cmd, Outcome};
use crate::config::Config;
use crate::console::{Console, ConsoleConfig};

pub type Error = anyhow::Error;
pub type Result<T> = anyhow::Result<T>;

#[derive(
    Serialize, EnumString, EnumVariantNames, IntoStaticStr, Debug, Copy, Clone, PartialEq, Eq, Hash,
)]
#[serde(rename_all = "kebab-case")]
#[strum(serialize_all = "kebab-case")]
pub enum OutputFormat {
    Default,
    Debug,
    Json,
    Yaml,
}

impl Default for OutputFormat {
    fn default() -> Self {
        Self::Default
    }
}

#[derive(StructOpt, Debug, Clone, PartialEq, Eq, Hash)]
pub struct Opt {
    /// Format of output
    #[structopt(
        long,
        global = true,
        default_value = OutputFormat::default().into(),
        possible_values = &OutputFormat::VARIANTS
    )]
    output: OutputFormat,
    /// Hides any messages except the final outcome of commands
    #[structopt(long, short, global = true)]
    quiet: bool,
    /// Assumes "yes" as answer to all prompts and run non-interactively
    #[structopt(long, short = "y", global = true)]
    assume_yes: bool,
    #[structopt(subcommand)]
    cmd: Cmd,
}

impl Opt {
    pub fn run(&self) -> Result<()> {
        let assume_yes = self.assume_yes;
        let cnsl_conf = ConsoleConfig { assume_yes };
        let mut cnsl = if self.quiet {
            Console::sink(cnsl_conf)
        } else {
            Console::term(cnsl_conf)
        };

        self.cmd.run(&mut cnsl, |outcome, cnsl| {
            self.finish(outcome, &mut io::stdout(), cnsl)
        })
    }

    fn finish(
        &self,
        outcome: &dyn Outcome,
        stdout: &mut dyn Write,
        cnsl: &mut Console,
    ) -> Result<()> {
        cnsl.flush()?;
        writeln!(stdout)?;

        outcome.print(stdout, self.output)?;

        if outcome.is_error() {
            Err(Error::msg("Command exited with error"))
        } else {
            Ok(())
        }
    }
}