2022-02-25 04:31:01 +00:00
|
|
|
#![warn(clippy::disallowed_methods)]
|
2021-07-16 19:20:59 +00:00
|
|
|
|
2021-01-22 19:14:51 +00:00
|
|
|
use clap::crate_authors;
|
2020-06-03 15:25:51 +00:00
|
|
|
use std::io;
|
2022-02-27 18:37:43 +00:00
|
|
|
use std::thread::available_parallelism;
|
2019-12-19 22:38:06 +00:00
|
|
|
use std::time::SystemTime;
|
|
|
|
|
2022-02-19 21:24:11 +00:00
|
|
|
use clap::{IntoApp, Parser, Subcommand};
|
2022-01-04 09:49:42 +00:00
|
|
|
use clap_complete::{generate, Shell as CompletionShell};
|
2020-09-28 20:38:50 +00:00
|
|
|
use rand::distributions::Alphanumeric;
|
|
|
|
use rand::Rng;
|
2022-01-04 09:49:42 +00:00
|
|
|
use starship::context::{Properties, Target};
|
2020-10-17 09:09:27 +00:00
|
|
|
use starship::module::ALL_MODULES;
|
|
|
|
use starship::*;
|
2019-04-02 04:45:49 +00:00
|
|
|
|
2022-01-04 09:49:42 +00:00
|
|
|
fn long_version() -> &'static str {
|
2022-02-26 16:34:48 +00:00
|
|
|
let ver = Box::new(crate::shadow::clap_long_version());
|
2022-01-04 09:49:42 +00:00
|
|
|
Box::leak(ver).as_str()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Parser, Debug)]
|
|
|
|
#[clap(
|
|
|
|
author=crate_authors!(),
|
|
|
|
version=shadow::PKG_VERSION,
|
|
|
|
long_version=long_version(),
|
2022-02-19 21:24:11 +00:00
|
|
|
about="The cross-shell prompt for astronauts. ☄🌌️",
|
|
|
|
subcommand_required=true,
|
|
|
|
arg_required_else_help=true,
|
2022-01-04 09:49:42 +00:00
|
|
|
)]
|
|
|
|
struct Cli {
|
|
|
|
#[clap(subcommand)]
|
|
|
|
command: Commands,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Subcommand, Debug)]
|
|
|
|
enum Commands {
|
|
|
|
/// Create a pre-populated GitHub issue with information about your configuration
|
|
|
|
BugReport,
|
|
|
|
/// Generate starship shell completions for your shell to stdout
|
|
|
|
Completions {
|
|
|
|
#[clap(arg_enum)]
|
|
|
|
shell: CompletionShell,
|
|
|
|
},
|
|
|
|
/// Edit the starship configuration
|
|
|
|
Config {
|
|
|
|
/// Configuration key to edit
|
|
|
|
#[clap(requires = "value")]
|
|
|
|
name: Option<String>,
|
|
|
|
/// Value to place into that key
|
|
|
|
value: Option<String>,
|
|
|
|
},
|
|
|
|
/// Explains the currently showing modules
|
|
|
|
Explain(Properties),
|
|
|
|
/// Prints the shell function used to execute starship
|
|
|
|
Init {
|
|
|
|
shell: String,
|
|
|
|
#[clap(long)]
|
|
|
|
print_full_init: bool,
|
|
|
|
},
|
|
|
|
/// Prints a specific prompt module
|
|
|
|
Module {
|
|
|
|
/// The name of the module to be printed
|
|
|
|
#[clap(required = true, required_unless_present = "list")]
|
|
|
|
name: Option<String>,
|
|
|
|
/// List out all supported modules
|
|
|
|
#[clap(short, long)]
|
|
|
|
list: bool,
|
|
|
|
#[clap(flatten)]
|
|
|
|
properties: Properties,
|
|
|
|
},
|
|
|
|
/// Prints the computed starship configuration
|
|
|
|
PrintConfig {
|
|
|
|
/// Print the default instead of the computed config
|
|
|
|
#[clap(short, long)]
|
|
|
|
default: bool,
|
|
|
|
/// Configuration keys to print
|
|
|
|
name: Vec<String>,
|
|
|
|
},
|
|
|
|
/// Prints the full starship prompt
|
|
|
|
Prompt {
|
|
|
|
/// Print the right prompt (instead of the standard left prompt)
|
|
|
|
#[clap(long)]
|
|
|
|
right: bool,
|
|
|
|
/// Print the continuation prompt (instead of the standard left prompt)
|
|
|
|
#[clap(long, conflicts_with = "right")]
|
|
|
|
continuation: bool,
|
|
|
|
#[clap(flatten)]
|
|
|
|
properties: Properties,
|
|
|
|
},
|
|
|
|
/// Generate random session key
|
|
|
|
Session,
|
|
|
|
/// Prints time in milliseconds
|
2022-02-19 21:24:11 +00:00
|
|
|
#[clap(hide = true)]
|
2022-01-04 09:49:42 +00:00
|
|
|
Time,
|
|
|
|
/// Prints timings of all active modules
|
|
|
|
Timings(Properties),
|
|
|
|
/// Toggle a given starship module
|
|
|
|
Toggle {
|
|
|
|
/// The name of the module to be toggled
|
|
|
|
name: String,
|
|
|
|
/// The key of the config to be toggled
|
|
|
|
#[clap(default_value = "disabled")]
|
|
|
|
value: String,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-04-02 03:23:03 +00:00
|
|
|
fn main() {
|
2020-11-11 19:24:43 +00:00
|
|
|
// Configure the current terminal on windows to support ANSI escape sequences.
|
|
|
|
#[cfg(windows)]
|
|
|
|
let _ = ansi_term::enable_ansi_support();
|
2020-09-28 20:38:50 +00:00
|
|
|
logger::init();
|
2022-02-27 18:37:43 +00:00
|
|
|
init_global_threadpool();
|
2019-05-14 04:43:11 +00:00
|
|
|
|
2022-02-06 22:04:28 +00:00
|
|
|
let args = match Cli::try_parse() {
|
|
|
|
Ok(args) => args,
|
|
|
|
Err(e) => {
|
|
|
|
// if the error is not printed to stderr, this means it was not really
|
|
|
|
// an error but rather some information is going to be listed, therefore
|
|
|
|
// we won't print the arguments passed
|
|
|
|
let is_info_only = !e.use_stderr();
|
|
|
|
// print the error and void panicking in case of stdout/stderr closing unexpectedly
|
|
|
|
let _ = e.print();
|
|
|
|
// if there was no mistake by the user and we're only going to display information,
|
|
|
|
// we won't put arguments or exit with non-zero code
|
|
|
|
let exit_code = if is_info_only {
|
|
|
|
0
|
|
|
|
} else {
|
|
|
|
// print the arguments
|
|
|
|
// avoid panicking in case of stderr closing
|
|
|
|
let mut stderr = io::stderr();
|
|
|
|
use io::Write;
|
|
|
|
let _ = writeln!(
|
|
|
|
stderr,
|
|
|
|
"\nNOTE:\n passed arguments: {:?}",
|
|
|
|
// collect into a vec to format args as a slice
|
|
|
|
std::env::args().skip(1).collect::<Vec<_>>()
|
|
|
|
);
|
|
|
|
// clap exits with status 2 on error:
|
|
|
|
// https://docs.rs/clap/latest/clap/struct.Error.html#method.exit
|
|
|
|
2
|
|
|
|
};
|
|
|
|
|
|
|
|
std::process::exit(exit_code);
|
|
|
|
}
|
|
|
|
};
|
2022-01-04 09:49:42 +00:00
|
|
|
log::trace!("Parsed arguments: {:#?}", args);
|
2019-08-17 19:33:19 +00:00
|
|
|
|
2022-01-04 09:49:42 +00:00
|
|
|
match args.command {
|
|
|
|
Commands::Init {
|
|
|
|
shell,
|
|
|
|
print_full_init,
|
|
|
|
} => {
|
|
|
|
if print_full_init {
|
|
|
|
init::init_main(&shell).expect("can't init_main");
|
2019-08-20 01:44:53 +00:00
|
|
|
} else {
|
2022-01-04 09:49:42 +00:00
|
|
|
init::init_stub(&shell).expect("can't init_stub");
|
2019-08-20 01:44:53 +00:00
|
|
|
}
|
2019-07-03 12:03:02 +00:00
|
|
|
}
|
2022-01-04 09:49:42 +00:00
|
|
|
Commands::Prompt {
|
|
|
|
properties,
|
|
|
|
right,
|
|
|
|
continuation,
|
|
|
|
} => {
|
|
|
|
let target = match (right, continuation) {
|
|
|
|
(true, _) => Target::Right,
|
|
|
|
(_, true) => Target::Continuation,
|
|
|
|
(_, _) => Target::Main,
|
|
|
|
};
|
|
|
|
print::prompt(properties, target)
|
|
|
|
}
|
|
|
|
Commands::Module {
|
|
|
|
name,
|
|
|
|
list,
|
|
|
|
properties,
|
|
|
|
} => {
|
|
|
|
if list {
|
2019-08-20 04:42:25 +00:00
|
|
|
println!("Supported modules list");
|
|
|
|
println!("----------------------");
|
|
|
|
for modules in ALL_MODULES {
|
|
|
|
println!("{}", modules);
|
|
|
|
}
|
|
|
|
}
|
2022-01-04 09:49:42 +00:00
|
|
|
if let Some(module_name) = name {
|
|
|
|
print::module(&module_name, properties);
|
2019-08-20 04:42:25 +00:00
|
|
|
}
|
2019-06-06 12:18:00 +00:00
|
|
|
}
|
2022-01-04 09:49:42 +00:00
|
|
|
Commands::Config { name, value } => {
|
|
|
|
if let Some(name) = name {
|
|
|
|
if let Some(value) = value {
|
|
|
|
configure::update_configuration(&name, &value)
|
2020-04-26 13:58:39 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
configure::edit_configuration()
|
|
|
|
}
|
|
|
|
}
|
2022-01-04 09:49:42 +00:00
|
|
|
Commands::PrintConfig { default, name } => configure::print_configuration(default, &name),
|
|
|
|
Commands::Toggle { name, value } => configure::toggle_configuration(&name, &value),
|
|
|
|
Commands::BugReport => bug_report::create(),
|
|
|
|
Commands::Time => {
|
2019-12-19 22:38:06 +00:00
|
|
|
match SystemTime::now()
|
|
|
|
.duration_since(SystemTime::UNIX_EPOCH)
|
|
|
|
.ok()
|
|
|
|
{
|
|
|
|
Some(time) => println!("{}", time.as_millis()),
|
|
|
|
None => println!("{}", -1),
|
|
|
|
}
|
|
|
|
}
|
2022-01-04 09:49:42 +00:00
|
|
|
Commands::Explain(props) => print::explain(props),
|
|
|
|
Commands::Timings(props) => print::timings(props),
|
|
|
|
Commands::Completions { shell } => generate(
|
|
|
|
shell,
|
2022-02-19 21:24:11 +00:00
|
|
|
&mut Cli::command(),
|
2022-01-04 09:49:42 +00:00
|
|
|
"starship",
|
|
|
|
&mut io::stdout().lock(),
|
|
|
|
),
|
|
|
|
Commands::Session => println!(
|
2020-09-28 20:38:50 +00:00
|
|
|
"{}",
|
|
|
|
rand::thread_rng()
|
|
|
|
.sample_iter(&Alphanumeric)
|
|
|
|
.take(16)
|
2020-12-25 18:08:07 +00:00
|
|
|
.map(char::from)
|
2020-09-28 20:38:50 +00:00
|
|
|
.collect::<String>()
|
|
|
|
),
|
2019-06-06 12:18:00 +00:00
|
|
|
}
|
2019-04-02 03:23:03 +00:00
|
|
|
}
|
2022-02-27 18:37:43 +00:00
|
|
|
|
|
|
|
/// Intialize global `rayon` thread pool
|
|
|
|
fn init_global_threadpool() {
|
|
|
|
// Allow overriding the number of threads
|
|
|
|
let num_threads = std::env::var("STARSHIP_NUM_THREADS")
|
|
|
|
.ok()
|
|
|
|
.and_then(|s| s.parse().ok())
|
|
|
|
// Default to the number of logical cores,
|
|
|
|
// but restrict the number of threads to 8
|
|
|
|
.unwrap_or_else(|| available_parallelism().map(usize::from).unwrap_or(1).min(8));
|
|
|
|
|
|
|
|
rayon::ThreadPoolBuilder::new()
|
|
|
|
.num_threads(num_threads)
|
|
|
|
.build_global()
|
|
|
|
.expect("Failed to initialize worker thread pool");
|
|
|
|
}
|