use clap::Parser;
use std::str;
mod colorize;
mod config;
mod context;
mod init;
mod settings;
mod shell;
use colorize::Colorize;
use config::*;
use context::*;
use settings::*;
use shell::*;
#[derive(Parser)]
#[command(
bin_name = "use",
version,
about = "Command-line utility to setup environment"
)]
struct Args {
name: Option<String>,
#[clap(subcommand)]
command: Option<Command>,
}
#[derive(Parser)]
enum Command {
Init {
shell: Shell,
#[clap(long)]
print_full_init: bool,
},
Config {
#[clap(long)]
create: bool,
},
List,
Set {
#[clap(requires = "value")]
key: Option<SettingsKey>,
value: Option<String>,
},
Print {
name: String,
},
}
fn main() {
let context = Context::new();
if context.os == OperatingSystem::Unknown {
eprintln!("{}: Unsupported operating system", "error:".error());
std::process::exit(1);
}
let mut args = Args::parse();
if args.name.is_none() && args.command.is_none() {
args.command = Some(Command::List);
}
if let Some(command) = args.command {
match command {
Command::Init {
shell,
print_full_init,
} => handle_init(shell, print_full_init),
Command::Config { create } => handle_config(&context, create),
Command::List => handle_list(&context),
Command::Set { key, value } => handle_set(key, value),
Command::Print { name } => handle_use(&context, name, true),
}
} else if let Some(name) = args.name {
handle_use(&context, name, false);
}
}
fn check_config(context: &Context) {
if context.check_old_config() {
eprintln!(
"{}: Old configuration file detected at ~/.config/use/useconfig.yaml. Please migrate to the new configuration file location {}.",
"error:".error(),
"~/.config/use.yaml".info()
);
std::process::exit(1);
}
}
fn handle_init(shell: Shell, print_full_init: bool) {
let result = if print_full_init {
init::init_main(shell)
} else {
init::init_stub(shell)
};
result.unwrap_or_else(|e| {
eprintln!("{}: {}", "error:".error(), e);
std::process::exit(1);
});
}
fn handle_config(context: &Context, create: bool) {
check_config(context);
let result = if create {
context.create_config_file().map(|_| {
println!(
"{} creating the default configuration file at {}",
" Finished".success(),
context.config_path.display()
);
})
} else {
context.edit_config_file()
};
result.unwrap_or_else(|e| {
eprintln!("{}: {}", "error:".error(), e);
std::process::exit(1);
});
}
fn handle_list(context: &Context) {
check_config(context);
let config = Config::new(context).unwrap_or_else(|e| {
eprintln!("{}: {}", "error:".error(), e);
std::process::exit(1);
});
config.list().iter().for_each(|env| {
println!("{}", env);
});
}
fn handle_set(key: Option<SettingsKey>, value: Option<String>) {
if let (Some(key), Some(value)) = (key, value) {
Settings::set(key, &value);
} else {
Settings::print();
}
}
fn handle_use(context: &Context, name: String, printing: bool) {
check_config(context);
if !printing && context.shell == Shell::Unknown {
eprintln!(
"{} Unknown shell, make sure to initialize use first (see documentation)",
"error:".error()
);
std::process::exit(1);
}
let shell_printer = if printing {
Box::new(DebugPrinter {}) as Box<dyn ShellPrinter>
} else {
create_shell_printer(context)
};
let config = Config::new(context).unwrap_or_else(|e| {
let error = format!("{} {}", "error:".error(), e);
shell_printer.echo(&error);
std::process::exit(1);
});
let settings = Settings::new();
config
.print_env(&name, &settings, shell_printer.as_ref())
.unwrap_or_else(|e| {
let warning = format!("{} {}", "warning:".warning(), e);
shell_printer.echo(&warning);
std::process::exit(1);
});
}
fn create_shell_printer(context: &Context) -> Box<dyn ShellPrinter> {
match context.shell {
Shell::Powershell => Box::new(PowershellPrinter {}),
Shell::Cmd => Box::new(CmdPrinter {}),
Shell::Unknown => panic!("Unsupported shell"),
}
}