Skip to main content

crabtalk_command/
lib.rs

1pub use anyhow;
2pub use crabtalk_command_codegen::command;
3pub use wcore;
4
5pub mod service;
6pub use service::{Service, install, render_service_template, uninstall, verbose_flag, view_logs};
7
8#[cfg(feature = "mcp")]
9pub use axum;
10#[cfg(feature = "mcp")]
11pub use service::{McpService, run_mcp};
12
13/// Shared entry point: init tracing from `-v` count (falling back to `RUST_LOG`),
14/// build a tokio runtime, run the given async closure, and exit on error.
15pub fn run<F, Fut>(verbose: u8, f: F)
16where
17    F: FnOnce() -> Fut,
18    Fut: std::future::Future<Output = anyhow::Result<()>>,
19{
20    let level = if verbose > 0 {
21        Some(match verbose {
22            1 => tracing::Level::INFO,
23            2 => tracing::Level::DEBUG,
24            _ => tracing::Level::TRACE,
25        })
26    } else {
27        std::env::var("RUST_LOG").ok().map(|v| {
28            match v.rsplit('=').next().unwrap_or(&v).to_lowercase().as_str() {
29                "trace" => tracing::Level::TRACE,
30                "debug" => tracing::Level::DEBUG,
31                "info" => tracing::Level::INFO,
32                "error" => tracing::Level::ERROR,
33                _ => tracing::Level::WARN,
34            }
35        })
36    };
37    if let Some(level) = level {
38        tracing_subscriber::fmt()
39            .with_writer(std::io::stderr)
40            .with_max_level(level)
41            .init();
42    }
43
44    let rt = match tokio::runtime::Runtime::new() {
45        Ok(rt) => rt,
46        Err(e) => {
47            eprintln!("Error: failed to create tokio runtime: {e}");
48            std::process::exit(1);
49        }
50    };
51    if let Err(e) = rt.block_on(f()) {
52        eprintln!("Error: {e}");
53        std::process::exit(1);
54    }
55}