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