use clap::Subcommand; use eyre::{Result, WrapErr}; use tracing_subscriber::filter::EnvFilter; use crate::atuin_client::settings::Settings; mod config; mod daemon; mod default_config; mod history; mod info; mod stats; // mod store; mod sync; mod wrapped; #[derive(Subcommand, Debug)] #[command(infer_subcommands = true)] pub(crate) enum Cmd { /// Manipulate shell history #[command(subcommand)] History(history::Cmd), /// Interact with the daemon #[command(subcommand)] Daemon(daemon::Cmd), #[command(subcommand)] /// Request a sync or view sync status Sync(sync::Cmd), // /// Manage the atuin data store // #[command(subcommand)] // Store(store::Cmd), /// Information about dotfiles locations and ENV vars #[command()] Info, /// Calculate statistics for your history Stats(stats::Cmd), #[command()] /// Display a recap of your last year's history Wrapped { year: Option }, /// Print the default atuin configuration (config.toml) #[command()] DefaultConfig, #[command(subcommand)] /// Manage your configuration Config(config::Cmd), } impl Cmd { pub(crate) fn run(self) -> Result<()> { let mut runtime = tokio::runtime::Builder::new_current_thread(); let runtime = runtime.enable_all().build().unwrap(); let res = { let settings = Settings::new().wrap_err("could not load client settings")?; runtime.block_on(self.run_inner(settings)) }; runtime.shutdown_timeout(std::time::Duration::from_millis(50)); res } async fn run_inner(self, settings: Settings) -> Result<()> { // ATUIN_LOG env var overrides config file level settings let env_log_set = std::env::var("ATUIN_LOG").is_ok(); // Base filter from env var (or empty if not set) let base_filter = EnvFilter::from_env("ATUIN_LOG").add_directive("sqlx_sqlite::regexp=off".parse()?); tracing::trace!(command = ?self, "client command"); // Skip initializing any databases for history // This is a pretty hot path, as it runs before and after every single command the user // runs match self { Self::History(history) => return history.run(&settings).await, Self::Config(config) => return config.run(&settings).await, _ => {} } match self { Self::Daemon(cmd) => cmd.run(&settings).await, Self::Sync(sync) => sync.run(settings).await, Self::Stats(stats) => stats.run(&settings).await, Self::Wrapped { year } => wrapped::run(year, &settings).await, // Self::Store(store) => store.run(&settings, &db, sqlite_store).await, Self::Info => info::run(&settings).await, Self::DefaultConfig => { default_config::run(); Ok(()) } Self::History(_) | Self::Config(_) => { unreachable!() } } } }