switch from color-eyre to miette for error reporting
change uqytulyswwyzkqlnsxsmwpvzpqnrvlyx
commit a234c68564e5c31abdb87055e11bc533a8ce6f1b
author Alpha Chen <alpha@kejadlen.dev>
date
parent vqtymmsv
diff --git a/Cargo.lock b/Cargo.lock
index 3207865..c049e97 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -191,6 +191,15 @@ dependencies = [
  "windows-link",
 ]
 
+[[package]]
+name = "backtrace-ext"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
+dependencies = [
+ "backtrace",
+]
+
 [[package]]
 name = "base64"
 version = "0.22.1"
@@ -312,33 +321,6 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
 
-[[package]]
-name = "color-eyre"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d"
-dependencies = [
- "backtrace",
- "color-spantrace",
- "eyre",
- "indenter",
- "once_cell",
- "owo-colors",
- "tracing-error",
-]
-
-[[package]]
-name = "color-spantrace"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427"
-dependencies = [
- "once_cell",
- "owo-colors",
- "tracing-core",
- "tracing-error",
-]
-
 [[package]]
 name = "colorchoice"
 version = "1.0.4"
@@ -502,16 +484,6 @@ dependencies = [
  "pin-project-lite",
 ]
 
-[[package]]
-name = "eyre"
-version = "0.6.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
-dependencies = [
- "indenter",
- "once_cell",
-]
-
 [[package]]
 name = "fastrand"
 version = "2.3.0"
@@ -924,12 +896,6 @@ dependencies = [
  "icu_properties",
 ]
 
-[[package]]
-name = "indenter"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5"
-
 [[package]]
 name = "indexmap"
 version = "2.13.0"
@@ -942,6 +908,12 @@ dependencies = [
  "serde_core",
 ]
 
+[[package]]
+name = "is_ci"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
+
 [[package]]
 name = "is_executable"
 version = "1.0.5"
@@ -1136,6 +1108,36 @@ version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
 
+[[package]]
+name = "miette"
+version = "7.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7"
+dependencies = [
+ "backtrace",
+ "backtrace-ext",
+ "cfg-if",
+ "miette-derive",
+ "owo-colors",
+ "supports-color",
+ "supports-hyperlinks",
+ "supports-unicode",
+ "terminal_size",
+ "textwrap",
+ "unicode-width 0.1.14",
+]
+
+[[package]]
+name = "miette-derive"
+version = "7.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "mime"
 version = "0.3.17"
@@ -1486,9 +1488,9 @@ dependencies = [
  "axum",
  "clap",
  "clap_complete",
- "color-eyre",
  "jiff",
  "maud",
+ "miette",
  "predicates",
  "rand",
  "serde",
@@ -1989,6 +1991,27 @@ version = "2.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
 
+[[package]]
+name = "supports-color"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
+dependencies = [
+ "is_ci",
+]
+
+[[package]]
+name = "supports-hyperlinks"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91"
+
+[[package]]
+name = "supports-unicode"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
+
 [[package]]
 name = "syn"
 version = "2.0.117"
@@ -2030,12 +2053,32 @@ dependencies = [
  "windows-sys 0.61.2",
 ]
 
+[[package]]
+name = "terminal_size"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"
+dependencies = [
+ "rustix",
+ "windows-sys 0.60.2",
+]
+
 [[package]]
 name = "termtree"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
 
+[[package]]
+name = "textwrap"
+version = "0.16.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
+dependencies = [
+ "unicode-linebreak",
+ "unicode-width 0.2.2",
+]
+
 [[package]]
 name = "thiserror"
 version = "2.0.18"
@@ -2190,16 +2233,6 @@ dependencies = [
  "valuable",
 ]
 
-[[package]]
-name = "tracing-error"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db"
-dependencies = [
- "tracing",
- "tracing-subscriber",
-]
-
 [[package]]
 name = "tracing-log"
 version = "0.2.0"
@@ -2247,6 +2280,12 @@ version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
 
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
+
 [[package]]
 name = "unicode-normalization"
 version = "0.1.25"
@@ -2262,6 +2301,18 @@ version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"
 
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "unicode-width"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
+
 [[package]]
 name = "unicode-xid"
 version = "0.2.6"
diff --git a/Cargo.toml b/Cargo.toml
index 0936b4d..7d764f5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,7 +9,7 @@ path = "src/bin/ranger/main.rs"
 
 [dependencies]
 axum = "*"
-color-eyre = "*"
+miette = { version = "*", features = ["fancy"] }
 tracing-subscriber = { version = "*", features = ["env-filter"] }
 jiff = { version = "*", features = ["serde"] }
 clap = { version = "*", features = ["derive", "env", "unstable-ext"] }
diff --git a/src/bin/ranger/commands/backlog.rs b/src/bin/ranger/commands/backlog.rs
index 2842ee5..eadf3cc 100644
--- a/src/bin/ranger/commands/backlog.rs
+++ b/src/bin/ranger/commands/backlog.rs
@@ -1,7 +1,7 @@
 use clap::Subcommand;
 use clap_complete::engine::ArgValueCompleter;
-use color_eyre::eyre::Result;
 use ranger::db::SqlitePool;
+use ranger::error::RangerError;
 use ranger::key;
 use ranger::models::{Backlog, State};
 use ranger::ops;
@@ -47,7 +47,11 @@ pub enum BacklogCommands {
     },
 }
 
-pub async fn run(pool: &SqlitePool, command: BacklogCommands, json: bool) -> Result<()> {
+pub async fn run(
+    pool: &SqlitePool,
+    command: BacklogCommands,
+    json: bool,
+) -> Result<(), RangerError> {
     let mut conn = pool.acquire().await?;
 
     match command {
diff --git a/src/bin/ranger/commands/comment.rs b/src/bin/ranger/commands/comment.rs
index 4955c68..01cdbcc 100644
--- a/src/bin/ranger/commands/comment.rs
+++ b/src/bin/ranger/commands/comment.rs
@@ -1,7 +1,7 @@
 use clap::Subcommand;
 use clap_complete::engine::ArgValueCompleter;
-use color_eyre::eyre::Result;
 use ranger::db::SqlitePool;
+use ranger::error::RangerError;
 use ranger::ops;
 
 use crate::completions;
@@ -27,7 +27,11 @@ pub enum CommentCommands {
     },
 }
 
-pub async fn run(pool: &SqlitePool, command: CommentCommands, json: bool) -> Result<()> {
+pub async fn run(
+    pool: &SqlitePool,
+    command: CommentCommands,
+    json: bool,
+) -> Result<(), RangerError> {
     let backlog_scope = super::task::default_backlog_id(pool).await;
     let mut conn = pool.acquire().await?;
 
diff --git a/src/bin/ranger/commands/serve.rs b/src/bin/ranger/commands/serve.rs
index 8320255..44d4c12 100644
--- a/src/bin/ranger/commands/serve.rs
+++ b/src/bin/ranger/commands/serve.rs
@@ -24,7 +24,7 @@ pub async fn run(
     pool: &SqlitePool,
     port: u16,
     default_backlog: Option<String>,
-) -> color_eyre::Result<()> {
+) -> Result<(), ranger::error::RangerError> {
     let state = AppState {
         pool: pool.clone(),
         default_backlog,
@@ -92,7 +92,10 @@ struct TaskView {
     tags: Vec<String>,
 }
 
-async fn render_board(state: &AppState, backlog_name: &str) -> color_eyre::Result<Markup> {
+async fn render_board(
+    state: &AppState,
+    backlog_name: &str,
+) -> Result<Markup, ranger::error::RangerError> {
     let mut conn = state.pool.acquire().await?;
 
     // Fetch all backlogs for the selector
@@ -326,7 +329,7 @@ async fn to_task_views(
     tasks: &[Task],
     prefixes: &std::collections::HashMap<String, usize>,
     conn: &mut sqlx::pool::PoolConnection<sqlx::Sqlite>,
-) -> color_eyre::Result<Vec<TaskView>> {
+) -> Result<Vec<TaskView>, ranger::error::RangerError> {
     let mut views = Vec::with_capacity(tasks.len());
     for task in tasks {
         let prefix_len = prefixes.get(&task.key).copied().unwrap_or(8);
diff --git a/src/bin/ranger/commands/tag.rs b/src/bin/ranger/commands/tag.rs
index c1ceb06..401e260 100644
--- a/src/bin/ranger/commands/tag.rs
+++ b/src/bin/ranger/commands/tag.rs
@@ -1,6 +1,6 @@
 use clap::Subcommand;
-use color_eyre::eyre::Result;
 use ranger::db::SqlitePool;
+use ranger::error::RangerError;
 use ranger::ops;
 
 use super::task::default_backlog_id;
@@ -28,7 +28,7 @@ pub enum TagCommands {
     List,
 }
 
-pub async fn run(pool: &SqlitePool, command: TagCommands, json: bool) -> Result<()> {
+pub async fn run(pool: &SqlitePool, command: TagCommands, json: bool) -> Result<(), RangerError> {
     let backlog_scope = default_backlog_id(pool).await;
     let mut conn = pool.acquire().await?;
 
diff --git a/src/bin/ranger/commands/task.rs b/src/bin/ranger/commands/task.rs
index 9d23e63..8bdaf64 100644
--- a/src/bin/ranger/commands/task.rs
+++ b/src/bin/ranger/commands/task.rs
@@ -2,8 +2,8 @@ use std::collections::HashMap;
 
 use clap::{Args, Subcommand};
 use clap_complete::engine::ArgValueCompleter;
-use color_eyre::eyre::{Result, bail};
 use ranger::db::{SqliteConnection, SqlitePool};
+use ranger::error::RangerError as Error;
 use ranger::key;
 use ranger::models::{State, Task};
 use ranger::ops;
@@ -28,7 +28,7 @@ impl PositionArgs {
         self,
         conn: &mut SqliteConnection,
         backlog_id: Option<i64>,
-    ) -> Result<Option<PositionAnchors>> {
+    ) -> Result<Option<PositionAnchors>, Error> {
         match (self.before, self.after) {
             (None, None) => Ok(None),
             (Some(b), None) => {
@@ -168,7 +168,7 @@ pub async fn default_backlog_id(pool: &SqlitePool) -> Option<i64> {
         .map(|b| b.id)
 }
 
-pub async fn run(pool: &SqlitePool, command: TaskCommands, json: bool) -> Result<()> {
+pub async fn run(pool: &SqlitePool, command: TaskCommands, json: bool) -> Result<(), Error> {
     let backlog_scope = default_backlog_id(pool).await;
 
     match command {
@@ -319,7 +319,9 @@ pub async fn run(pool: &SqlitePool, command: TaskCommands, json: bool) -> Result
                         task.title
                     );
                 }
-                None => bail!("--before or --after is required"),
+                None => {
+                    return Err(Error::Usage("--before or --after is required".into()));
+                }
             }
         }
         TaskCommands::Delete { key } => {
diff --git a/src/bin/ranger/main.rs b/src/bin/ranger/main.rs
index 71c9664..53b3f10 100644
--- a/src/bin/ranger/main.rs
+++ b/src/bin/ranger/main.rs
@@ -4,6 +4,7 @@ mod output;
 
 use clap::{CommandFactory, Parser, Subcommand};
 use clap_complete::engine::ArgValueCompleter;
+use miette::IntoDiagnostic;
 use std::path::PathBuf;
 use tracing_subscriber::{EnvFilter, fmt, prelude::*};
 
@@ -71,8 +72,7 @@ fn resolve_db_path(cli_path: Option<PathBuf>) -> PathBuf {
         .expect("failed to create data directory")
 }
 
-fn main() -> color_eyre::Result<()> {
-    color_eyre::install()?;
+fn main() -> miette::Result<()> {
     tracing_subscriber::registry()
         .with(fmt::layer())
         .with(EnvFilter::from_default_env())
@@ -85,11 +85,12 @@ fn main() -> color_eyre::Result<()> {
 
     tokio::runtime::Builder::new_multi_thread()
         .enable_all()
-        .build()?
+        .build()
+        .into_diagnostic()?
         .block_on(async_main())
 }
 
-async fn async_main() -> color_eyre::Result<()> {
+async fn async_main() -> miette::Result<()> {
     let cli = Cli::parse();
     let db_path = resolve_db_path(cli.db);
     let pool = ranger::db::connect(&db_path).await?;
diff --git a/src/error.rs b/src/error.rs
index e361f0e..851a10e 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,4 +1,4 @@
-#[derive(Debug, thiserror::Error)]
+#[derive(Debug, thiserror::Error, miette::Diagnostic)]
 pub enum RangerError {
     #[error("no key matching prefix '{0}'")]
     KeyNotFound(String),
@@ -11,10 +11,14 @@ pub enum RangerError {
     },
     #[error("backlog not found: '{0}'")]
     BacklogNotFound(String),
+    #[error(transparent)]
+    InvalidState(#[from] crate::models::InvalidStateError),
     #[error("database error: {0}")]
     Db(#[from] sqlx::Error),
     #[error("migration error: {0}")]
     Migrate(#[from] sqlx::migrate::MigrateError),
+    #[error("{0}")]
+    Usage(String),
     #[error("io error: {0}")]
     Io(#[from] std::io::Error),
 }