refactor: update clap to v3 (#3370)
This commit is contained in:
parent
35eae3fb4a
commit
20cf200c3a
|
@ -218,17 +218,42 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.34.0"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||
checksum = "d17bf219fcd37199b9a29e00ba65dfb8cd5b2688b7297ec14ff829c40ac50ca9"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim 0.8.0",
|
||||
"clap_derive",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"os_str_bytes",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60d123fbea4c5d9799cffd44051e2125c880efd23b3b7c529baf3ea5508c8736"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1b9752c030a14235a0bd5ef3ad60a1dcac8468c30921327fc8af36b20c790b9"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1191,6 +1216,15 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.0.0"
|
||||
|
@ -1344,6 +1378,30 @@ dependencies = [
|
|||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
|
@ -1719,6 +1777,7 @@ dependencies = [
|
|||
"byte-unit",
|
||||
"chrono",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"directories-next",
|
||||
"gethostname",
|
||||
"git2",
|
||||
|
@ -1748,7 +1807,7 @@ dependencies = [
|
|||
"shell-words",
|
||||
"starship-battery",
|
||||
"starship_module_config_derive",
|
||||
"strsim 0.10.0",
|
||||
"strsim",
|
||||
"sys-info",
|
||||
"tempfile",
|
||||
"terminal_size",
|
||||
|
@ -1795,12 +1854,6 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
|
@ -1863,6 +1916,15 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.17"
|
||||
|
@ -1875,9 +1937,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
@ -1968,6 +2030,15 @@ version = "0.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.6"
|
||||
|
@ -2041,12 +2112,6 @@ version = "0.2.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
|
@ -2129,6 +2194,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
|
|
@ -30,7 +30,8 @@ battery = ["starship-battery"]
|
|||
tls-vendored = ["native-tls/vendored"]
|
||||
|
||||
[dependencies]
|
||||
clap = "2.34.0"
|
||||
clap = { version = "3.0.0", features = ["derive", "cargo", "unicode"] }
|
||||
clap_complete = "3.0.0"
|
||||
ansi_term = "0.12.1"
|
||||
directories-next = "2.0.0"
|
||||
git2 = { version = "0.13.25", default-features = false }
|
||||
|
|
|
@ -73,7 +73,7 @@ fn handle_update_configuration(doc: &mut Document, name: &str, value: &str) -> R
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_configuration(use_default: bool, paths: &[&str]) {
|
||||
pub fn print_configuration(use_default: bool, paths: &[String]) {
|
||||
let config = if use_default {
|
||||
// Get default config
|
||||
let default_config = crate::configs::FullConfig::default();
|
||||
|
@ -94,7 +94,7 @@ pub fn print_configuration(use_default: bool, paths: &[&str]) {
|
|||
if paths.is_empty()
|
||||
|| paths
|
||||
.iter()
|
||||
.any(|&path| path == "format" || path == "right_format")
|
||||
.any(|path| path == "format" || path == "right_format")
|
||||
{
|
||||
println!(
|
||||
"# $all is shorthand for {}",
|
||||
|
@ -128,7 +128,7 @@ pub fn print_configuration(use_default: bool, paths: &[&str]) {
|
|||
println!("{}", string_config);
|
||||
}
|
||||
|
||||
fn extract_toml_paths(mut config: toml::Value, paths: &[&str]) -> toml::Value {
|
||||
fn extract_toml_paths(mut config: toml::Value, paths: &[String]) -> toml::Value {
|
||||
// Extract all the requested sections into a new configuration.
|
||||
let mut subset = toml::value::Table::new();
|
||||
let config = if let Some(config) = config.as_table_mut() {
|
||||
|
@ -138,7 +138,7 @@ fn extract_toml_paths(mut config: toml::Value, paths: &[&str]) -> toml::Value {
|
|||
return toml::Value::Table(subset);
|
||||
};
|
||||
|
||||
'paths: for &path in paths {
|
||||
'paths: for path in paths {
|
||||
let path_segments: Vec<_> = path.split('.').collect();
|
||||
let (&end, parents) = path_segments.split_last().unwrap_or((&"", &[]));
|
||||
|
||||
|
@ -414,9 +414,9 @@ mod tests {
|
|||
let actual_config = extract_toml_paths(
|
||||
config,
|
||||
&[
|
||||
"extract_root",
|
||||
"extract_section",
|
||||
"extract_subsection.extracted",
|
||||
"extract_root".to_owned(),
|
||||
"extract_section".to_owned(),
|
||||
"extract_subsection.extracted".to_owned(),
|
||||
],
|
||||
);
|
||||
|
||||
|
|
142
src/context.rs
142
src/context.rs
|
@ -5,14 +5,17 @@ use crate::utils::{create_command, exec_timeout, CommandOutput};
|
|||
|
||||
use crate::modules;
|
||||
use crate::utils::{self, home_dir};
|
||||
use clap::ArgMatches;
|
||||
use clap::Parser;
|
||||
use git2::{ErrorCode::UnbornBranch, Repository, RepositoryState};
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
#[cfg(test)]
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fmt::Debug;
|
||||
use std::fs;
|
||||
use std::num::ParseIntError;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::string::String;
|
||||
use std::time::{Duration, Instant};
|
||||
|
@ -37,7 +40,7 @@ pub struct Context<'a> {
|
|||
dir_contents: OnceCell<DirContents>,
|
||||
|
||||
/// Properties to provide to modules.
|
||||
pub properties: HashMap<&'a str, String>,
|
||||
pub properties: Properties,
|
||||
|
||||
/// Pipestatus of processes in pipe
|
||||
pub pipestatus: Option<Vec<String>>,
|
||||
|
@ -48,11 +51,8 @@ pub struct Context<'a> {
|
|||
/// The shell the user is assumed to be running
|
||||
pub shell: Shell,
|
||||
|
||||
/// Construct the right prompt instead of the left prompt
|
||||
pub right: bool,
|
||||
|
||||
/// Construct the continuation prompt instead of the normal prompt
|
||||
pub continuation: bool,
|
||||
/// Which prompt to print (main, right, ...)
|
||||
pub target: Target,
|
||||
|
||||
/// Width of terminal, or zero if width cannot be detected.
|
||||
pub width: usize,
|
||||
|
@ -76,53 +76,46 @@ impl<'a> Context<'a> {
|
|||
/// Identify the current working directory and create an instance of Context
|
||||
/// for it. "logical-path" is used when a shell allows the "current working directory"
|
||||
/// to be something other than a file system path (like powershell provider specific paths).
|
||||
pub fn new(arguments: ArgMatches) -> Context {
|
||||
pub fn new(arguments: Properties, target: Target) -> Context<'a> {
|
||||
let shell = Context::get_shell();
|
||||
|
||||
// Retrieve the "current directory".
|
||||
// If the path argument is not set fall back to the OS current directory.
|
||||
let path = arguments
|
||||
.value_of("path")
|
||||
.map(PathBuf::from)
|
||||
.path
|
||||
.clone()
|
||||
.or_else(|| env::current_dir().ok())
|
||||
.or_else(|| env::var("PWD").map(PathBuf::from).ok())
|
||||
.or_else(|| arguments.value_of("logical_path").map(PathBuf::from))
|
||||
.or_else(|| arguments.logical_path.clone())
|
||||
.unwrap_or_default();
|
||||
|
||||
// Retrieve the "logical directory".
|
||||
// If the path argument is not set fall back to the PWD env variable set by many shells
|
||||
// or to the other path.
|
||||
let logical_path = arguments
|
||||
.value_of("logical_path")
|
||||
.map(PathBuf::from)
|
||||
.logical_path
|
||||
.clone()
|
||||
.or_else(|| env::var("PWD").map(PathBuf::from).ok())
|
||||
.unwrap_or_else(|| path.clone());
|
||||
|
||||
Context::new_with_shell_and_path(arguments, shell, path, logical_path)
|
||||
Context::new_with_shell_and_path(arguments, shell, target, path, logical_path)
|
||||
}
|
||||
|
||||
/// Create a new instance of Context for the provided directory
|
||||
pub fn new_with_shell_and_path(
|
||||
arguments: ArgMatches,
|
||||
properties: Properties,
|
||||
shell: Shell,
|
||||
target: Target,
|
||||
path: PathBuf,
|
||||
logical_path: PathBuf,
|
||||
) -> Context {
|
||||
) -> Context<'a> {
|
||||
let config = StarshipConfig::initialize();
|
||||
|
||||
// Unwrap the clap arguments into a simple hashtable
|
||||
let properties: HashMap<&str, std::string::String> = arguments
|
||||
.args
|
||||
.iter()
|
||||
.filter(|(_, v)| !v.vals.is_empty())
|
||||
.map(|(a, b)| (*a, b.vals.first().cloned().unwrap().into_string().unwrap()))
|
||||
.collect();
|
||||
|
||||
let pipestatus = arguments
|
||||
.values_of("pipestatus")
|
||||
let pipestatus = properties
|
||||
.pipestatus
|
||||
.as_deref()
|
||||
.map(Context::get_and_flatten_pipestatus)
|
||||
.flatten();
|
||||
|
||||
log::trace!("Received completed pipestatus of {:?}", pipestatus);
|
||||
|
||||
// Canonicalize the current path to resolve symlinks, etc.
|
||||
|
@ -136,14 +129,7 @@ impl<'a> Context<'a> {
|
|||
.as_ref()
|
||||
.map_or_else(StarshipRootConfig::default, StarshipRootConfig::load);
|
||||
|
||||
let right = arguments.is_present("right");
|
||||
let continuation = arguments.is_present("continuation");
|
||||
|
||||
let width = arguments
|
||||
.value_of("terminal_width")
|
||||
.and_then(|w| w.parse().ok())
|
||||
.or_else(|| terminal_size().map(|(w, _)| w.0 as usize))
|
||||
.unwrap_or(80);
|
||||
let width = properties.terminal_width;
|
||||
|
||||
Context {
|
||||
config,
|
||||
|
@ -154,8 +140,7 @@ impl<'a> Context<'a> {
|
|||
dir_contents: OnceCell::new(),
|
||||
repo: OnceCell::new(),
|
||||
shell,
|
||||
right,
|
||||
continuation,
|
||||
target,
|
||||
width,
|
||||
#[cfg(test)]
|
||||
env: HashMap::new(),
|
||||
|
@ -212,12 +197,13 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
|
||||
/// Reads and appropriately flattens multiple args for pipestatus
|
||||
pub fn get_and_flatten_pipestatus(args: clap::Values) -> Option<Vec<String>> {
|
||||
// TODO: Replace with value_delimiter = ' ' clap option?
|
||||
pub fn get_and_flatten_pipestatus(args: &[String]) -> Option<Vec<String>> {
|
||||
// Due to shell differences, we can potentially receive individual or space
|
||||
// separated inputs, e.g. "0","1","2","0" is the same as "0 1 2 0" and
|
||||
// "0 1", "2 0". We need to accept all these formats and return a Vec<String>
|
||||
let parsed_vals = args
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(|x| x.split_ascii_whitespace())
|
||||
.flatten()
|
||||
.map(|x| x.to_string())
|
||||
|
@ -310,8 +296,12 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: This should be used directly by clap parse
|
||||
pub fn get_cmd_duration(&self) -> Option<u128> {
|
||||
self.properties.get("cmd_duration")?.parse::<u128>().ok()
|
||||
self.properties
|
||||
.cmd_duration
|
||||
.as_deref()
|
||||
.and_then(|cd| cd.parse::<u128>().ok())
|
||||
}
|
||||
|
||||
/// Execute a command and return the output on stdout and stderr if successful
|
||||
|
@ -574,6 +564,67 @@ pub enum Shell {
|
|||
Unknown,
|
||||
}
|
||||
|
||||
fn default_width() -> usize {
|
||||
terminal_size().map_or(80, |(w, _)| w.0 as usize)
|
||||
}
|
||||
|
||||
/// Which kind of prompt target to print (main prompt, rprompt, ...)
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Target {
|
||||
Main,
|
||||
Right,
|
||||
Continuation,
|
||||
}
|
||||
|
||||
/// Properties as passed on from the shell as arguments
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Properties {
|
||||
/// The status code of the previously run command
|
||||
#[clap(short = 's', long = "status")]
|
||||
pub status_code: Option<i32>,
|
||||
/// Bash and Zsh support returning codes for each process in a pipeline.
|
||||
#[clap(long)]
|
||||
pipestatus: Option<Vec<String>>,
|
||||
/// The width of the current interactive terminal.
|
||||
#[clap(short = 'w', long, default_value_t=default_width())]
|
||||
terminal_width: usize,
|
||||
/// The path that the prompt should render for.
|
||||
#[clap(short, long)]
|
||||
path: Option<PathBuf>,
|
||||
/// The logical path that the prompt should render for.
|
||||
/// This path should be a virtual/logical representation of the PATH argument.
|
||||
#[clap(short = 'P', long)]
|
||||
logical_path: Option<PathBuf>,
|
||||
/// The execution duration of the last command, in milliseconds
|
||||
#[clap(short = 'd', long)]
|
||||
pub cmd_duration: Option<String>,
|
||||
/// The keymap of fish/zsh
|
||||
#[clap(short = 'k', long, default_value = "viins")]
|
||||
pub keymap: String,
|
||||
/// The number of currently running jobs
|
||||
#[clap(short, long, default_value_t, parse(try_from_str=parse_jobs))]
|
||||
pub jobs: i64,
|
||||
}
|
||||
|
||||
impl Default for Properties {
|
||||
fn default() -> Self {
|
||||
Properties {
|
||||
status_code: None,
|
||||
pipestatus: None,
|
||||
terminal_width: default_width(),
|
||||
path: None,
|
||||
logical_path: None,
|
||||
cmd_duration: None,
|
||||
keymap: "viins".to_string(),
|
||||
jobs: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_jobs(jobs: &str) -> Result<i64, ParseIntError> {
|
||||
jobs.trim().parse::<i64>()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -660,8 +711,9 @@ mod tests {
|
|||
// Mock navigation into the symlink path
|
||||
let test_path = path_symlink.join("yyy");
|
||||
let context = Context::new_with_shell_and_path(
|
||||
ArgMatches::default(),
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
test_path.clone(),
|
||||
test_path.clone(),
|
||||
);
|
||||
|
@ -685,8 +737,9 @@ mod tests {
|
|||
// Mock navigation to a directory which does not exist on disk
|
||||
let test_path = Path::new("/path_which_does_not_exist").to_path_buf();
|
||||
let context = Context::new_with_shell_and_path(
|
||||
ArgMatches::default(),
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
test_path.clone(),
|
||||
test_path.clone(),
|
||||
);
|
||||
|
@ -705,8 +758,9 @@ mod tests {
|
|||
// Mock navigation to a directory which does not exist on disk
|
||||
let test_path = Path::new("~/path_which_does_not_exist").to_path_buf();
|
||||
let context = Context::new_with_shell_and_path(
|
||||
ArgMatches::default(),
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
test_path.clone(),
|
||||
test_path.clone(),
|
||||
);
|
||||
|
|
416
src/main.rs
416
src/main.rs
|
@ -4,297 +4,165 @@ use clap::crate_authors;
|
|||
use std::io;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use clap::{App, AppSettings, Arg, Shell, SubCommand};
|
||||
use clap::{AppSettings, IntoApp, Parser, Subcommand};
|
||||
use clap_complete::{generate, Shell as CompletionShell};
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::Rng;
|
||||
use starship::context::{Properties, Target};
|
||||
use starship::module::ALL_MODULES;
|
||||
use starship::*;
|
||||
|
||||
fn long_version() -> &'static str {
|
||||
let ver = Box::new(crate::shadow::clap_version());
|
||||
Box::leak(ver).as_str()
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(
|
||||
author=crate_authors!(),
|
||||
version=shadow::PKG_VERSION,
|
||||
long_version=long_version(),
|
||||
about="The cross-shell prompt for astronauts. ☄🌌️"
|
||||
)]
|
||||
#[clap(setting(AppSettings::SubcommandRequiredElseHelp))]
|
||||
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
|
||||
#[clap(setting=AppSettings::Hidden)]
|
||||
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,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Configure the current terminal on windows to support ANSI escape sequences.
|
||||
#[cfg(windows)]
|
||||
let _ = ansi_term::enable_ansi_support();
|
||||
logger::init();
|
||||
|
||||
let status_code_arg = Arg::with_name("status_code")
|
||||
.short("s")
|
||||
.long("status")
|
||||
.value_name("STATUS_CODE")
|
||||
.help("The status code of the previously run command")
|
||||
.takes_value(true);
|
||||
let args = Cli::parse();
|
||||
log::trace!("Parsed arguments: {:#?}", args);
|
||||
|
||||
let pipestatus_arg = Arg::with_name("pipestatus")
|
||||
.long("pipestatus")
|
||||
.value_name("PIPESTATUS")
|
||||
.help("Status codes from a command pipeline")
|
||||
.long_help("Bash and Zsh supports returning codes for each process in a pipeline.")
|
||||
.multiple(true);
|
||||
|
||||
let terminal_width_arg = Arg::with_name("terminal_width")
|
||||
.short("w")
|
||||
.long("terminal-width")
|
||||
.value_name("TERMINAL_WIDTH")
|
||||
.help("The width of the current interactive terminal.")
|
||||
.takes_value(true);
|
||||
|
||||
let path_arg = Arg::with_name("path")
|
||||
.short("p")
|
||||
.long("path")
|
||||
.value_name("PATH")
|
||||
.help("The path that the prompt should render for.")
|
||||
.takes_value(true);
|
||||
|
||||
let logical_path_arg = Arg::with_name("logical_path")
|
||||
.short("P")
|
||||
.long("logical-path")
|
||||
.value_name("LOGICAL_PATH")
|
||||
.help(concat!(
|
||||
"The logical path that the prompt should render for. ",
|
||||
"This path should be a virtual/logical representation of the PATH argument."
|
||||
))
|
||||
.takes_value(true);
|
||||
|
||||
let shell_arg = Arg::with_name("shell")
|
||||
.value_name("SHELL")
|
||||
.help(
|
||||
"The name of the currently running shell\nCurrently supported options: bash, zsh, fish, powershell, ion, elvish, tcsh, nu, xonsh",
|
||||
)
|
||||
.required(true);
|
||||
|
||||
let cmd_duration_arg = Arg::with_name("cmd_duration")
|
||||
.short("d")
|
||||
.long("cmd-duration")
|
||||
.value_name("CMD_DURATION")
|
||||
.help("The execution duration of the last command, in milliseconds")
|
||||
.takes_value(true);
|
||||
|
||||
let keymap_arg = Arg::with_name("keymap")
|
||||
.short("k")
|
||||
.long("keymap")
|
||||
.value_name("KEYMAP")
|
||||
// fish/zsh only
|
||||
.help("The keymap of fish/zsh")
|
||||
.takes_value(true);
|
||||
|
||||
let jobs_arg = Arg::with_name("jobs")
|
||||
.short("j")
|
||||
.long("jobs")
|
||||
.value_name("JOBS")
|
||||
.help("The number of currently running jobs")
|
||||
.takes_value(true);
|
||||
|
||||
let init_scripts_arg = Arg::with_name("print_full_init")
|
||||
.long("print-full-init")
|
||||
.help("Print the main initialization script (as opposed to the init stub)");
|
||||
|
||||
let long_version = crate::shadow::clap_version();
|
||||
let mut app = App::new("starship")
|
||||
.about("The cross-shell prompt for astronauts. ☄🌌️")
|
||||
// pull the version number from Cargo.toml
|
||||
.version(shadow::PKG_VERSION)
|
||||
.long_version(long_version.as_str())
|
||||
// pull the authors from Cargo.toml
|
||||
.author(crate_authors!())
|
||||
.after_help("https://github.com/starship/starship")
|
||||
.setting(AppSettings::SubcommandRequiredElseHelp)
|
||||
.subcommand(
|
||||
SubCommand::with_name("init")
|
||||
.about("Prints the shell function used to execute starship")
|
||||
.arg(&shell_arg)
|
||||
.arg(&init_scripts_arg),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("prompt")
|
||||
.about("Prints the full starship prompt")
|
||||
.arg(
|
||||
Arg::with_name("right")
|
||||
.long("right")
|
||||
.help("Print the right prompt (instead of the standard left prompt)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("continuation")
|
||||
.long("continuation")
|
||||
.help("Print the continuation prompt (instead of the standard left prompt)")
|
||||
.conflicts_with("right"),
|
||||
)
|
||||
.arg(&status_code_arg)
|
||||
.arg(&pipestatus_arg)
|
||||
.arg(&terminal_width_arg)
|
||||
.arg(&path_arg)
|
||||
.arg(&logical_path_arg)
|
||||
.arg(&cmd_duration_arg)
|
||||
.arg(&keymap_arg)
|
||||
.arg(&jobs_arg),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("module")
|
||||
.about("Prints a specific prompt module")
|
||||
.arg(
|
||||
Arg::with_name("name")
|
||||
.help("The name of the module to be printed")
|
||||
.required(true)
|
||||
.required_unless("list"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("list")
|
||||
.short("l")
|
||||
.long("list")
|
||||
.help("List out all supported modules"),
|
||||
)
|
||||
.arg(&status_code_arg)
|
||||
.arg(&pipestatus_arg)
|
||||
.arg(&terminal_width_arg)
|
||||
.arg(&path_arg)
|
||||
.arg(&logical_path_arg)
|
||||
.arg(&cmd_duration_arg)
|
||||
.arg(&keymap_arg)
|
||||
.arg(&jobs_arg),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("config")
|
||||
.alias("configure")
|
||||
.about("Edit the starship configuration")
|
||||
.arg(
|
||||
Arg::with_name("name")
|
||||
.help("Configuration key to edit")
|
||||
.required(false)
|
||||
.requires("value"),
|
||||
)
|
||||
.arg(Arg::with_name("value").help("Value to place into that key")),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("print-config")
|
||||
.about("Prints the computed starship configuration")
|
||||
.arg(
|
||||
Arg::with_name("default")
|
||||
.short("d")
|
||||
.long("default")
|
||||
.help("Print the default instead of the computed config")
|
||||
.takes_value(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("name")
|
||||
.help("Configuration keys to print")
|
||||
.multiple(true)
|
||||
.required(false),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("toggle")
|
||||
.about("Toggle a given starship module")
|
||||
.arg(
|
||||
Arg::with_name("name")
|
||||
.help("The name of the module to be toggled")
|
||||
.required(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("key")
|
||||
.help("The key of the config to be toggled")
|
||||
.required(false)
|
||||
.required_unless("name"),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("bug-report").about(
|
||||
"Create a pre-populated GitHub issue with information about your configuration",
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("time")
|
||||
.about("Prints time in milliseconds")
|
||||
.settings(&[AppSettings::Hidden]),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("explain")
|
||||
.about("Explains the currently showing modules")
|
||||
.arg(&status_code_arg)
|
||||
.arg(&pipestatus_arg)
|
||||
.arg(&terminal_width_arg)
|
||||
.arg(&path_arg)
|
||||
.arg(&logical_path_arg)
|
||||
.arg(&cmd_duration_arg)
|
||||
.arg(&keymap_arg)
|
||||
.arg(&jobs_arg),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("timings")
|
||||
.about("Prints timings of all active modules")
|
||||
.arg(&status_code_arg)
|
||||
.arg(&pipestatus_arg)
|
||||
.arg(&terminal_width_arg)
|
||||
.arg(&path_arg)
|
||||
.arg(&logical_path_arg)
|
||||
.arg(&cmd_duration_arg)
|
||||
.arg(&keymap_arg)
|
||||
.arg(&jobs_arg),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("completions")
|
||||
.about("Generate starship shell completions for your shell to stdout")
|
||||
.arg(
|
||||
Arg::with_name("shell")
|
||||
.takes_value(true)
|
||||
.possible_values(&Shell::variants())
|
||||
.help("the shell to generate completions for")
|
||||
.value_name("SHELL")
|
||||
.required(true)
|
||||
.env("STARSHIP_SHELL"),
|
||||
),
|
||||
)
|
||||
.subcommand(SubCommand::with_name("session").about("Generate random session key"));
|
||||
|
||||
let matches = app.clone().get_matches();
|
||||
|
||||
match matches.subcommand() {
|
||||
("init", Some(sub_m)) => {
|
||||
let shell_name = sub_m.value_of("shell").expect("Shell name missing.");
|
||||
if sub_m.is_present("print_full_init") {
|
||||
init::init_main(shell_name).expect("can't init_main");
|
||||
match args.command {
|
||||
Commands::Init {
|
||||
shell,
|
||||
print_full_init,
|
||||
} => {
|
||||
if print_full_init {
|
||||
init::init_main(&shell).expect("can't init_main");
|
||||
} else {
|
||||
init::init_stub(shell_name).expect("can't init_stub");
|
||||
init::init_stub(&shell).expect("can't init_stub");
|
||||
}
|
||||
}
|
||||
("prompt", Some(sub_m)) => print::prompt(sub_m.clone()),
|
||||
("module", Some(sub_m)) => {
|
||||
if sub_m.is_present("list") {
|
||||
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 {
|
||||
println!("Supported modules list");
|
||||
println!("----------------------");
|
||||
for modules in ALL_MODULES {
|
||||
println!("{}", modules);
|
||||
}
|
||||
}
|
||||
if let Some(module_name) = sub_m.value_of("name") {
|
||||
print::module(module_name, sub_m.clone());
|
||||
if let Some(module_name) = name {
|
||||
print::module(&module_name, properties);
|
||||
}
|
||||
}
|
||||
("config", Some(sub_m)) => {
|
||||
if let Some(name) = sub_m.value_of("name") {
|
||||
if let Some(value) = sub_m.value_of("value") {
|
||||
configure::update_configuration(name, value)
|
||||
Commands::Config { name, value } => {
|
||||
if let Some(name) = name {
|
||||
if let Some(value) = value {
|
||||
configure::update_configuration(&name, &value)
|
||||
}
|
||||
} else {
|
||||
configure::edit_configuration()
|
||||
}
|
||||
}
|
||||
("print-config", Some(sub_m)) => {
|
||||
let print_default = sub_m.is_present("default");
|
||||
let paths = sub_m
|
||||
.values_of("name")
|
||||
.map(|paths| paths.collect::<Vec<&str>>())
|
||||
.unwrap_or_default();
|
||||
configure::print_configuration(print_default, &paths)
|
||||
}
|
||||
("toggle", Some(sub_m)) => {
|
||||
if let Some(name) = sub_m.value_of("name") {
|
||||
if let Some(value) = sub_m.value_of("key") {
|
||||
configure::toggle_configuration(name, value)
|
||||
} else {
|
||||
configure::toggle_configuration(name, "disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
("bug-report", Some(_)) => bug_report::create(),
|
||||
("time", _) => {
|
||||
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 => {
|
||||
match SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.ok()
|
||||
|
@ -303,18 +171,15 @@ fn main() {
|
|||
None => println!("{}", -1),
|
||||
}
|
||||
}
|
||||
("explain", Some(sub_m)) => print::explain(sub_m.clone()),
|
||||
("timings", Some(sub_m)) => print::timings(sub_m.clone()),
|
||||
("completions", Some(sub_m)) => {
|
||||
let shell: Shell = sub_m
|
||||
.value_of("shell")
|
||||
.expect("Shell name missing.")
|
||||
.parse()
|
||||
.expect("Invalid shell");
|
||||
|
||||
app.gen_completions_to("starship", shell, &mut io::stdout().lock());
|
||||
}
|
||||
("session", _) => println!(
|
||||
Commands::Explain(props) => print::explain(props),
|
||||
Commands::Timings(props) => print::timings(props),
|
||||
Commands::Completions { shell } => generate(
|
||||
shell,
|
||||
&mut Cli::into_app(),
|
||||
"starship",
|
||||
&mut io::stdout().lock(),
|
||||
),
|
||||
Commands::Session => println!(
|
||||
"{}",
|
||||
rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
|
@ -322,6 +187,5 @@ fn main() {
|
|||
.map(char::from)
|
||||
.collect::<String>()
|
||||
),
|
||||
(command, _) => unreachable!("Invalid subcommand: {}", command),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
let config: CharacterConfig = CharacterConfig::try_load(module.config);
|
||||
|
||||
let props = &context.properties;
|
||||
let exit_code = props.get("status_code").map_or("0", String::as_str);
|
||||
let keymap = props.get("keymap").map_or("viins", String::as_str);
|
||||
let exit_success = exit_code == "0";
|
||||
let exit_code = props.status_code;
|
||||
let keymap = props.keymap.as_str();
|
||||
let exit_success = exit_code.unwrap_or_default() == 0;
|
||||
|
||||
// Match shell "keymap" names to normalized vi modes
|
||||
// NOTE: in vi mode, fish reports normal mode as "default".
|
||||
|
|
|
@ -33,12 +33,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
}
|
||||
|
||||
let props = &context.properties;
|
||||
let num_of_jobs = props
|
||||
.get("jobs")
|
||||
.map_or("0", String::as_str)
|
||||
.trim()
|
||||
.parse::<i64>()
|
||||
.ok()?;
|
||||
let num_of_jobs = props.jobs;
|
||||
|
||||
if num_of_jobs == 0
|
||||
&& config.threshold > 0
|
||||
|
|
|
@ -168,9 +168,9 @@ mod tests {
|
|||
use std::io;
|
||||
|
||||
use super::*;
|
||||
use crate::context::Target;
|
||||
use crate::test::ModuleRenderer;
|
||||
use ansi_term::Color;
|
||||
use clap::ArgMatches;
|
||||
|
||||
#[test]
|
||||
fn pulumi_version_release() {
|
||||
|
@ -192,7 +192,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn get_home_dir() {
|
||||
let mut context = Context::new(ArgMatches::default());
|
||||
let mut context = Context::new(Default::default(), Target::Main);
|
||||
context.env.insert("HOME", "/home/sweet/home".to_string());
|
||||
assert_eq!(
|
||||
pulumi_home_dir(&context),
|
||||
|
@ -204,7 +204,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_get_pulumi_workspace() {
|
||||
let mut context = Context::new(ArgMatches::default());
|
||||
let mut context = Context::new(Default::default(), Target::Main);
|
||||
context.env.insert("HOME", "/home/sweet/home".to_string());
|
||||
let name = "foobar";
|
||||
let project_file = PathBuf::from("/hello/Pulumi.yaml");
|
||||
|
|
|
@ -268,7 +268,7 @@ enum RustupRunRustcVersionOutcome {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::context::Shell;
|
||||
use crate::context::{Shell, Target};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::io;
|
||||
use std::process::{ExitStatus, Output};
|
||||
|
@ -424,6 +424,7 @@ mod tests {
|
|||
let context = Context::new_with_shell_and_path(
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
dir.path().into(),
|
||||
dir.path().into(),
|
||||
);
|
||||
|
@ -444,6 +445,7 @@ mod tests {
|
|||
let context = Context::new_with_shell_and_path(
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
dir.path().into(),
|
||||
dir.path().into(),
|
||||
);
|
||||
|
@ -464,6 +466,7 @@ mod tests {
|
|||
let context = Context::new_with_shell_and_path(
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
dir.path().into(),
|
||||
dir.path().into(),
|
||||
);
|
||||
|
@ -486,6 +489,7 @@ mod tests {
|
|||
let context = Context::new_with_shell_and_path(
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
child_dir_path.clone(),
|
||||
child_dir_path,
|
||||
);
|
||||
|
@ -505,6 +509,7 @@ mod tests {
|
|||
let context = Context::new_with_shell_and_path(
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
dir.path().into(),
|
||||
dir.path().into(),
|
||||
);
|
||||
|
@ -522,6 +527,7 @@ mod tests {
|
|||
let context = Context::new_with_shell_and_path(
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
dir.path().into(),
|
||||
dir.path().into(),
|
||||
);
|
||||
|
@ -542,6 +548,7 @@ mod tests {
|
|||
let context = Context::new_with_shell_and_path(
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
dir.path().into(),
|
||||
dir.path().into(),
|
||||
);
|
||||
|
@ -564,6 +571,7 @@ mod tests {
|
|||
let context = Context::new_with_shell_and_path(
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
child_dir_path.clone(),
|
||||
child_dir_path,
|
||||
);
|
||||
|
|
|
@ -11,7 +11,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let shell = context.shell;
|
||||
let shell = &context.shell;
|
||||
|
||||
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
|
||||
formatter
|
||||
|
|
|
@ -28,10 +28,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
return None;
|
||||
};
|
||||
|
||||
let exit_code = context
|
||||
.properties
|
||||
.get("status_code")
|
||||
.map_or("0", String::as_str);
|
||||
let exit_code = context.properties.status_code.unwrap_or_default();
|
||||
|
||||
let pipestatus_status = match &context.pipestatus {
|
||||
None => PipeStatusStatus::Disabled,
|
||||
|
@ -47,7 +44,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
};
|
||||
|
||||
// Exit code is zero and pipestatus is all zero or disabled/missing
|
||||
if exit_code == "0"
|
||||
if exit_code == 0
|
||||
&& (match pipestatus_status {
|
||||
PipeStatusStatus::Pipe(ps) => ps.iter().all(|s| s == "0"),
|
||||
_ => true,
|
||||
|
@ -79,7 +76,13 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||
PipeStatusStatus::Pipe(_) => config.pipestatus_format,
|
||||
_ => config.format,
|
||||
};
|
||||
let parsed = format_exit_code(exit_code, main_format, Some(&pipestatus), &config, context);
|
||||
let parsed = format_exit_code(
|
||||
&exit_code.to_string(),
|
||||
main_format,
|
||||
Some(&pipestatus),
|
||||
&config,
|
||||
context,
|
||||
);
|
||||
|
||||
module.set_segments(match parsed {
|
||||
Ok(segments) => segments,
|
||||
|
|
39
src/print.rs
39
src/print.rs
|
@ -1,5 +1,4 @@
|
|||
use ansi_term::ANSIStrings;
|
||||
use clap::ArgMatches;
|
||||
use rayon::prelude::*;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt::{self, Debug, Write as FmtWrite};
|
||||
|
@ -10,7 +9,7 @@ use unicode_segmentation::UnicodeSegmentation;
|
|||
use unicode_width::UnicodeWidthChar;
|
||||
|
||||
use crate::configs::PROMPT_ORDER;
|
||||
use crate::context::{Context, Shell};
|
||||
use crate::context::{Context, Properties, Shell, Target};
|
||||
use crate::formatter::{StringFormatter, VariableHolder};
|
||||
use crate::module::Module;
|
||||
use crate::module::ALL_MODULES;
|
||||
|
@ -54,8 +53,8 @@ fn test_grapheme_aware_width() {
|
|||
assert_eq!(11, "normal text".width_graphemes());
|
||||
}
|
||||
|
||||
pub fn prompt(args: ArgMatches) {
|
||||
let context = Context::new(args);
|
||||
pub fn prompt(args: Properties, target: Target) {
|
||||
let context = Context::new(args, target);
|
||||
let stdout = io::stdout();
|
||||
let mut handle = stdout.lock();
|
||||
write!(handle, "{}", get_prompt(context)).unwrap();
|
||||
|
@ -114,13 +113,13 @@ pub fn get_prompt(context: Context) -> String {
|
|||
);
|
||||
|
||||
let module_strings = root_module.ansi_strings_for_shell(context.shell, Some(context.width));
|
||||
if config.add_newline && !context.continuation {
|
||||
if config.add_newline && context.target != Target::Continuation {
|
||||
// continuation prompts normally do not include newlines, but they can
|
||||
writeln!(buf).unwrap();
|
||||
}
|
||||
write!(buf, "{}", ANSIStrings(&module_strings)).unwrap();
|
||||
|
||||
if context.right {
|
||||
if context.target == Target::Right {
|
||||
// right prompts generally do not allow newlines
|
||||
buf = buf.replace('\n', "");
|
||||
}
|
||||
|
@ -135,8 +134,8 @@ pub fn get_prompt(context: Context) -> String {
|
|||
buf
|
||||
}
|
||||
|
||||
pub fn module(module_name: &str, args: ArgMatches) {
|
||||
let context = Context::new(args);
|
||||
pub fn module(module_name: &str, args: Properties) {
|
||||
let context = Context::new(args, Target::Main);
|
||||
let module = get_module(module_name, context).unwrap_or_default();
|
||||
print!("{}", module);
|
||||
}
|
||||
|
@ -145,8 +144,8 @@ pub fn get_module(module_name: &str, context: Context) -> Option<String> {
|
|||
modules::handle(module_name, &context).map(|m| m.to_string())
|
||||
}
|
||||
|
||||
pub fn timings(args: ArgMatches) {
|
||||
let context = Context::new(args);
|
||||
pub fn timings(args: Properties) {
|
||||
let context = Context::new(args, Target::Main);
|
||||
|
||||
struct ModuleTiming {
|
||||
name: String,
|
||||
|
@ -191,8 +190,8 @@ pub fn timings(args: ArgMatches) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn explain(args: ArgMatches) {
|
||||
let context = Context::new(args);
|
||||
pub fn explain(args: Properties) {
|
||||
let context = Context::new(args, Target::Main);
|
||||
|
||||
struct ModuleInfo {
|
||||
value: String,
|
||||
|
@ -431,16 +430,14 @@ fn load_formatter_and_modules<'a>(context: &'a Context) -> (StringFormatter<'a>,
|
|||
match (lformatter, rformatter, cformatter) {
|
||||
(Ok(lf), Ok(rf), Ok(cf)) => {
|
||||
let mut modules: BTreeSet<String> = BTreeSet::new();
|
||||
if !context.continuation {
|
||||
if context.target != Target::Continuation {
|
||||
modules.extend(lf.get_variables());
|
||||
modules.extend(rf.get_variables());
|
||||
}
|
||||
if context.continuation {
|
||||
(cf, modules)
|
||||
} else if context.right {
|
||||
(rf, modules)
|
||||
} else {
|
||||
(lf, modules)
|
||||
match context.target {
|
||||
Target::Main => (lf, modules),
|
||||
Target::Right => (rf, modules),
|
||||
Target::Continuation => (cf, modules),
|
||||
}
|
||||
}
|
||||
_ => (StringFormatter::raw(">"), BTreeSet::new()),
|
||||
|
@ -464,7 +461,7 @@ mod test {
|
|||
}),
|
||||
};
|
||||
context.root_config.right_format = "$character".to_string();
|
||||
context.right = true;
|
||||
context.target = Target::Right;
|
||||
|
||||
let expected = String::from(">>"); // should strip new lines
|
||||
let actual = get_prompt(context);
|
||||
|
@ -480,7 +477,7 @@ mod test {
|
|||
}),
|
||||
};
|
||||
context.root_config.continuation_prompt = "><>".to_string();
|
||||
context.continuation = true;
|
||||
context.target = Target::Continuation;
|
||||
|
||||
let expected = String::from("><>");
|
||||
let actual = get_prompt(context);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::context::{Context, Shell};
|
||||
use crate::context::{Context, Shell, Target};
|
||||
use crate::logger::StarshipLogger;
|
||||
use crate::{
|
||||
config::{RootModuleConfig, StarshipConfig},
|
||||
|
@ -34,8 +34,9 @@ static LOGGER: Lazy<()> = Lazy::new(|| {
|
|||
|
||||
pub fn default_context() -> Context<'static> {
|
||||
let mut context = Context::new_with_shell_and_path(
|
||||
clap::ArgMatches::default(),
|
||||
Default::default(),
|
||||
Shell::Unknown,
|
||||
Target::Main,
|
||||
PathBuf::new(),
|
||||
PathBuf::new(),
|
||||
);
|
||||
|
@ -103,15 +104,13 @@ impl<'a> ModuleRenderer<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn jobs(mut self, jobs: u64) -> Self {
|
||||
self.context.properties.insert("jobs", jobs.to_string());
|
||||
pub fn jobs(mut self, jobs: i64) -> Self {
|
||||
self.context.properties.jobs = jobs;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn cmd_duration(mut self, duration: u64) -> Self {
|
||||
self.context
|
||||
.properties
|
||||
.insert("cmd_duration", duration.to_string());
|
||||
self.context.properties.cmd_duration = Some(duration.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -119,14 +118,12 @@ impl<'a> ModuleRenderer<'a> {
|
|||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
self.context.properties.insert("keymap", keymap.into());
|
||||
self.context.properties.keymap = keymap.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn status(mut self, status: i32) -> Self {
|
||||
self.context
|
||||
.properties
|
||||
.insert("status_code", status.to_string());
|
||||
self.context.properties.status_code = Some(status);
|
||||
self
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue