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