loq_cli/
lib.rs

1//! Command-line interface for loq.
2//!
3//! Provides the main entry point and CLI argument handling for the loq tool.
4
5#![forbid(unsafe_code)]
6#![warn(missing_docs)]
7
8mod baseline;
9mod check;
10mod cli;
11mod config_edit;
12mod init;
13mod output;
14mod relax;
15
16use std::ffi::OsString;
17use std::io::{self, Read, Write};
18use std::process::ExitCode;
19
20use clap::Parser;
21use termcolor::{ColorChoice, StandardStream, WriteColor};
22
23use baseline::run_baseline;
24use check::{output_mode, run_check};
25use init::run_init;
26use relax::run_relax;
27
28pub use cli::{Cli, Command};
29
30/// Exit status for the CLI.
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum ExitStatus {
33    /// All checks passed.
34    Success,
35    /// Violations found (errors).
36    Failure,
37    /// Runtime error occurred.
38    Error,
39}
40
41impl From<ExitStatus> for ExitCode {
42    fn from(status: ExitStatus) -> Self {
43        match status {
44            ExitStatus::Success => Self::from(0),
45            ExitStatus::Failure => Self::from(1),
46            ExitStatus::Error => Self::from(2),
47        }
48    }
49}
50
51/// Runs the CLI using environment args and stdio.
52#[must_use]
53pub fn run_env() -> ExitStatus {
54    let args = std::env::args_os();
55    let stdin = io::stdin();
56    let mut stdout = StandardStream::stdout(ColorChoice::Auto);
57    let mut stderr = StandardStream::stderr(ColorChoice::Auto);
58    run_with(args, stdin.lock(), &mut stdout, &mut stderr)
59}
60
61/// Runs the CLI with custom args and streams (for testing).
62pub fn run_with<I, R, W1, W2>(args: I, mut stdin: R, stdout: &mut W1, stderr: &mut W2) -> ExitStatus
63where
64    I: IntoIterator<Item = OsString>,
65    R: Read,
66    W1: WriteColor + Write,
67    W2: WriteColor,
68{
69    let cli = Cli::parse_from(args);
70    let mode = output_mode(&cli);
71
72    let default_check = Command::Check(cli::CheckArgs {
73        paths: vec![],
74        no_cache: false,
75        output_format: cli::OutputFormat::Text,
76    });
77    match cli.command.as_ref().unwrap_or(&default_check) {
78        Command::Check(args) => run_check(args, &mut stdin, stdout, stderr, mode),
79        Command::Init(args) => run_init(args, stdout, stderr),
80        Command::Baseline(args) => run_baseline(args, stdout, stderr),
81        Command::Relax(args) => run_relax(args, stdout, stderr),
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn exit_status_to_exit_code() {
91        assert_eq!(ExitCode::from(ExitStatus::Success), ExitCode::from(0));
92        assert_eq!(ExitCode::from(ExitStatus::Failure), ExitCode::from(1));
93        assert_eq!(ExitCode::from(ExitStatus::Error), ExitCode::from(2));
94    }
95}