use std::io::Write;
use clap::{CommandFactory, Parser};
use ytcli::cli::{Cli, Command, GlobalArgs, Session, render_context};
use ytcli::config::{Config, paths};
use ytcli::exit::ExitCode;
#[tokio::main(flavor = "current_thread")]
async fn main() -> std::process::ExitCode {
let cli = Cli::parse();
init_tracing(cli.global.verbose);
run(cli).await.into()
}
async fn run(cli: Cli) -> ExitCode {
if let Command::Completions { shell } = cli.command {
let mut command = Cli::command();
let name = command.get_name().to_owned();
clap_complete::generate(shell, &mut command, name, &mut std::io::stdout());
return ExitCode::Success;
}
if let Command::Cheatsheet(ref args) = cli.command {
return ytcli::cli::cheatsheet::run(args);
}
let session = match build_session(&cli.global) {
Ok(session) => session,
Err(code) => return code,
};
match cli.command {
Command::Auth(ref command) => ytcli::cli::auth::run(command, &session).await,
Command::Issue(ref command) => ytcli::cli::issue::run(command, &session).await,
Command::Queue(ref command) => ytcli::cli::queue::run(command, &session).await,
Command::User(ref command) => ytcli::cli::user::run(command, &session).await,
Command::Worklog(ref command) => ytcli::cli::worklog::run(command, &session).await,
Command::Dict(ref command) => ytcli::cli::dict::run(command, &session).await,
Command::Field(ref command) => ytcli::cli::field::run(command, &session).await,
Command::Template(ref command) => ytcli::cli::field::run_templates(command, &session).await,
Command::Project(ref command) => ytcli::cli::project::run(command, &session).await,
Command::Board(ref command) => ytcli::cli::board::run(command, &session).await,
Command::Sprint(ref command) => ytcli::cli::sprint::run(command, &session).await,
Command::Component(ref command) => ytcli::cli::component::run(command, &session).await,
Command::Link(ref command) => ytcli::cli::link::run(command, &session).await,
Command::Bulk(ref command) => ytcli::cli::bulk::run(command, &session).await,
Command::Portfolio(ref command) => ytcli::cli::portfolio::run(command, &session).await,
Command::Goal(ref command) => ytcli::cli::goal::run(command, &session).await,
Command::Attachment(ref command) => ytcli::cli::attachment::run(command, &session).await,
Command::Cheatsheet(_) | Command::Completions { .. } => ExitCode::Success,
}
}
fn build_session(global: &GlobalArgs) -> Result<Session, ExitCode> {
let mut err = anstream::stderr();
let config_file = match global.config.clone() {
Some(path) => path,
None => match paths::config_file() {
Ok(path) => path,
Err(error) => {
let _ = writeln!(err, "error: {error}");
return Err(ExitCode::Failure);
}
},
};
let config = match Config::load(&config_file) {
Ok(config) => config,
Err(error) => {
let _ = writeln!(err, "error: {error}");
return Err(ExitCode::Failure);
}
};
let cwd = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("."));
let env_profile = std::env::var("YTCLI_PROFILE").ok();
let resolved = match config.resolve(global.profile.as_deref(), env_profile.as_deref(), &cwd) {
Ok(resolved) => Some(resolved),
Err(error) => {
tracing::debug!(%error, "no profile resolved");
None
}
};
Ok(Session {
render: render_context(global, resolved.as_ref()),
resolved,
config,
config_file,
global: global.clone(),
})
}
fn init_tracing(verbose: u8) {
let level = match verbose {
0 => "warn",
1 => "info",
2 => "debug",
_ => "trace",
};
let filter = tracing_subscriber::EnvFilter::try_from_env("YTCLI_LOG")
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(level));
let _ = tracing_subscriber::fmt()
.with_env_filter(filter)
.with_writer(std::io::stderr)
.without_time()
.try_init();
}