sqry_cli/error.rs
1//! CLI error types with custom exit codes
2//!
3//! This module defines error types that map to specific exit codes:
4//! - 0: Success
5//! - 1: Runtime error (default)
6//! - 2: Validation error (index corruption)
7//! - N: Pager exit code (when pager exits with non-zero)
8
9use std::fmt;
10
11/// CLI-specific error type with custom exit codes
12#[derive(Debug)]
13pub enum CliError {
14 /// Runtime error (exit code 1)
15 RuntimeError(anyhow::Error),
16
17 /// Pager exited with non-zero status (exit code from pager)
18 ///
19 /// This is used to propagate pager exit codes to the CLI exit code.
20 /// For example, if the user kills the pager with Ctrl-C (SIGINT),
21 /// this would propagate exit code 130 (128 + 2).
22 PagerExit(i32),
23}
24
25impl CliError {
26 /// Returns the appropriate exit code for this error
27 #[must_use]
28 pub fn exit_code(&self) -> i32 {
29 match self {
30 CliError::RuntimeError(_) => 1,
31 CliError::PagerExit(code) => *code,
32 }
33 }
34
35 /// Create a runtime error
36 #[allow(dead_code)]
37 #[must_use]
38 pub fn runtime(err: impl Into<anyhow::Error>) -> Self {
39 CliError::RuntimeError(err.into())
40 }
41
42 /// Create a pager exit error
43 ///
44 /// Use this when the pager exits with a non-zero status and you want
45 /// to propagate that exit code to the CLI.
46 #[must_use]
47 pub fn pager_exit(code: i32) -> Self {
48 CliError::PagerExit(code)
49 }
50}
51
52impl fmt::Display for CliError {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 match self {
55 CliError::RuntimeError(err) => write!(f, "{err}"),
56 CliError::PagerExit(code) => write!(f, "pager exited with code {code}"),
57 }
58 }
59}
60
61impl std::error::Error for CliError {
62 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
63 match self {
64 CliError::RuntimeError(err) => err.source(),
65 CliError::PagerExit(_) => None,
66 }
67 }
68}
69
70// Allow converting anyhow::Error to CliError (defaults to RuntimeError)
71impl From<anyhow::Error> for CliError {
72 fn from(err: anyhow::Error) -> Self {
73 CliError::RuntimeError(err)
74 }
75}