style: pedantic refactoring (#6771)

---------

Co-authored-by: daniel.eades <daniel.eades@seebyte.com>
This commit is contained in:
danieleades
2025-08-17 15:51:04 +01:00
committed by GitHub
parent 6d717b20ae
commit 3760f29560
59 changed files with 391 additions and 421 deletions
+2 -2
View File
@@ -42,7 +42,7 @@ fn gen_presets_hook(mut file: &File) -> SdResult<()> {
writeln!(
file,
r#"
r"
use crate::print;
pub fn get_preset_list<'a>() -> &'a [print::Preset] {{
@@ -57,7 +57,7 @@ pub fn get_preset_content(name: &str) -> &[u8] {{
_ => unreachable!(),
}}
}}
"#
"
)?;
Ok(())
}
+13 -17
View File
@@ -11,7 +11,7 @@ use serde::{
use std::borrow::Cow;
use std::clone::Clone;
use std::collections::HashMap;
use std::ffi::OsString;
use std::ffi::OsStr;
use std::io::ErrorKind;
use toml::Value;
@@ -38,7 +38,7 @@ where
}
}
/// Helper function that will call `ModuleConfig::from_config(config) if config is Some,
/// Helper function that will call `ModuleConfig::from_config(config)` if config is Some,
/// or `ModuleConfig::default()` if config is None.
fn try_load<V: Into<ValueRef<'a>>>(config: Option<V>) -> Self {
config.map(Into::into).map(Self::load).unwrap_or_default()
@@ -124,7 +124,7 @@ pub struct StarshipConfig {
impl StarshipConfig {
/// Initialize the Config struct
pub fn initialize(config_file_path: &Option<OsString>) -> Self {
pub fn initialize(config_file_path: Option<&OsStr>) -> Self {
Self::config_from_file(config_file_path)
.map(|config| Self {
config: Some(config),
@@ -133,7 +133,7 @@ impl StarshipConfig {
}
/// Create a config from a starship configuration file
fn config_from_file(config_file_path: &Option<OsString>) -> Option<toml::Table> {
fn config_from_file(config_file_path: Option<&OsStr>) -> Option<toml::Table> {
let toml_content = Self::read_config_content_as_str(config_file_path)?;
match toml::from_str(&toml_content) {
@@ -148,7 +148,7 @@ impl StarshipConfig {
}
}
pub fn read_config_content_as_str(config_file_path: &Option<OsString>) -> Option<String> {
pub fn read_config_content_as_str(config_file_path: Option<&OsStr>) -> Option<String> {
if config_file_path.is_none() {
log::debug!(
"Unable to determine `config_file_path`. Perhaps `utils::home_dir` is not defined on your platform?"
@@ -201,12 +201,10 @@ impl StarshipConfig {
// Assumes all keys except the last in path has a table
for option in table_options {
match prev_table.get(*option) {
Some(value) => match value.as_table() {
Some(value) => {
if let Some(value) = prev_table.get(*option) {
if let Some(value) = value.as_table() {
prev_table = value;
}
None => {
} else {
log::trace!(
"No config found for \"{}\": \"{}\" is not a table",
path.join("."),
@@ -214,17 +212,15 @@ impl StarshipConfig {
);
return None;
}
},
None => {
} else if prev_table.contains_key(*option) {
log::trace!(
"No config found for \"{}\": Option \"{}\" not found",
"No config found for \"{}\": \"{}\" is not a table",
path.join("."),
&option
);
return None;
}
}
}
let last_option = path.last().unwrap();
let value = prev_table.get(*last_option);
@@ -234,7 +230,7 @@ impl StarshipConfig {
path.join("."),
&last_option
);
};
}
value
}
@@ -1021,7 +1017,7 @@ mod tests {
assert_eq!(
parse_color_string("green", Some(&palette)),
Some(Color::Green)
)
);
}
#[test]
@@ -1064,7 +1060,7 @@ mod tests {
fn read_config_no_config_file_path_provided() {
assert_eq!(
None,
StarshipConfig::read_config_content_as_str(&None),
StarshipConfig::read_config_content_as_str(None),
"if the platform doesn't have utils::home_dir(), it should return None"
);
}
+2 -2
View File
@@ -17,8 +17,8 @@ pub struct OSConfig<'a> {
}
impl<'a> OSConfig<'a> {
pub fn get_symbol(&self, key: &Type) -> Option<&'a str> {
self.symbols.get(key).copied()
pub fn get_symbol(&self, key: Type) -> Option<&'a str> {
self.symbols.get(&key).copied()
}
}
+13 -12
View File
@@ -224,14 +224,14 @@ fn handle_toggle_configuration(doc: &mut DocumentMut, name: &str, key: &str) ->
}
pub fn get_configuration(context: &Context) -> toml::Table {
let starship_config = StarshipConfig::initialize(&context.get_config_path_os());
let starship_config = StarshipConfig::initialize(context.get_config_path_os().as_deref());
starship_config.config.unwrap_or_default()
}
pub fn get_configuration_edit(context: &Context) -> DocumentMut {
let config_file_path = context.get_config_path_os();
let toml_content = StarshipConfig::read_config_content_as_str(&config_file_path);
let toml_content = StarshipConfig::read_config_content_as_str(config_file_path.as_deref());
toml_content
.unwrap_or_default()
@@ -313,13 +313,13 @@ fn get_editor_internal(visual: Option<String>, editor: Option<String>) -> String
#[cfg(test)]
mod tests {
use std::{fs::create_dir, io};
use std::{fs::create_dir, io, path::PathBuf};
use tempfile::TempDir;
use toml_edit::Item;
use crate::{
context::{Shell, Target},
context::{Properties, Shell, Target},
context_env::Env,
};
@@ -376,13 +376,13 @@ mod tests {
#[test]
fn no_panic_when_editor_unparsable() {
let outcome = edit_configuration(&Default::default(), Some("\"vim"));
let outcome = edit_configuration(&Context::default(), Some("\"vim"));
assert!(outcome.is_err());
}
#[test]
fn no_panic_when_editor_not_found() {
let outcome = edit_configuration(&Default::default(), Some("this_editor_does_not_exist"));
let outcome = edit_configuration(&Context::default(), Some("this_editor_does_not_exist"));
assert!(outcome.is_err());
}
@@ -464,7 +464,7 @@ mod tests {
"\n"
);
assert_eq!(doc.to_string(), new_config)
assert_eq!(doc.to_string(), new_config);
}
#[test]
@@ -529,7 +529,7 @@ mod tests {
"\n"
);
assert_eq!(doc.to_string(), new_config)
assert_eq!(doc.to_string(), new_config);
}
#[test]
@@ -578,7 +578,7 @@ mod tests {
doc["a"]["b"]["c"]["d"]["e"]["f"]["g"]["h"]
.as_bool()
.unwrap()
)
);
}
#[test]
@@ -629,6 +629,7 @@ mod tests {
Ok(())
}
#[derive(Clone, Copy)]
enum StarshipConfigEnvScenario {
NotSpecified,
NonExistingFile,
@@ -683,11 +684,11 @@ mod tests {
);
Ok(Context::new_with_shell_and_path(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
Default::default(),
Default::default(),
PathBuf::default(),
PathBuf::default(),
env,
))
}
+8 -8
View File
@@ -128,7 +128,7 @@ impl<'a> Context<'a> {
logical_path: PathBuf,
env: Env<'a>,
) -> Self {
let config = StarshipConfig::initialize(&get_config_path_os(&env));
let config = StarshipConfig::initialize(get_config_path_os(&env).as_deref());
// If the vector is zero-length, we should pretend that we didn't get a
// pipestatus at all (since this is the input `--pipestatus=""`)
@@ -433,7 +433,7 @@ impl<'a> Context<'a> {
}
/// Attempt to execute several commands with `exec_cmd`, return the results of the first that works
pub fn exec_cmds_return_first(&self, commands: Vec<Vec<&str>>) -> Option<CommandOutput> {
pub fn exec_cmds_return_first(&self, commands: &[Vec<&str>]) -> Option<CommandOutput> {
commands
.iter()
.find_map(|attempt| self.exec_cmd(attempt[0], &attempt[1..]))
@@ -1153,12 +1153,12 @@ mod tests {
// Mock navigation into the symlink path
let test_path = path_symlink.join("yyy");
let context = Context::new_with_shell_and_path(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
test_path.clone(),
test_path.clone(),
Default::default(),
Env::default(),
);
assert_ne!(context.current_dir, context.logical_dir);
@@ -1178,12 +1178,12 @@ 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(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
test_path.clone(),
test_path.clone(),
Default::default(),
Env::default(),
);
let expected_current_dir = &test_path;
@@ -1200,12 +1200,12 @@ 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(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
test_path.clone(),
test_path.clone(),
Default::default(),
Env::default(),
);
let expected_current_dir = home_dir()
+6 -6
View File
@@ -158,25 +158,25 @@ pub fn init_stub(shell_name: &str) -> io::Result<()> {
"zsh" => print_script(ZSH_INIT, &starship.sprint_posix()?),
"fish" => print!(
// Fish does process substitution with pipes and psub instead of bash syntax
r#"source ({} init fish --print-full-init | psub)"#,
r"source ({} init fish --print-full-init | psub)",
starship.sprint_posix()?
),
"powershell" => print!(
r#"Invoke-Expression (& {} init powershell --print-full-init | Out-String)"#,
r"Invoke-Expression (& {} init powershell --print-full-init | Out-String)",
starship.sprint_pwsh()?
),
"ion" => print!("eval $({} init ion --print-full-init)", starship.sprint()?),
"elvish" => print!(
r#"eval ({} init elvish --print-full-init | slurp)"#,
r"eval ({} init elvish --print-full-init | slurp)",
starship.sprint()?
),
"tcsh" => print!(
r#"eval `({} init tcsh --print-full-init)`"#,
r"eval `({} init tcsh --print-full-init)`",
starship.sprint_posix()?
),
"nu" => print_script(NU_INIT, &StarshipPath::init()?.sprint()?),
"xonsh" => print!(
r#"execx($({} init xonsh --print-full-init))"#,
r"execx($({} init xonsh --print-full-init))",
starship.sprint_posix()?
),
"cmd" => print_script(CMDEXE_INIT, &StarshipPath::init()?.sprint_cmdexe()?),
@@ -198,7 +198,7 @@ pub fn init_stub(shell_name: &str) -> io::Result<()> {
Please open an issue in the starship repo if you would like to \
see support for {shell_basename}:\n\
https://github.com/starship/starship/issues/new\n"
)
);
}
};
Ok(())
+1 -1
View File
@@ -86,7 +86,7 @@ impl Default for StarshipLogger {
let log_dir = get_log_dir();
if let Err(err) = fs::create_dir_all(&log_dir) {
eprintln!("Unable to create log dir {log_dir:?}: {err:?}!")
eprintln!("Unable to create log dir {log_dir:?}: {err:?}!");
};
let session_log_file = log_dir.join(format!(
"session_{}.log",
+5 -4
View File
@@ -10,7 +10,7 @@ use clap_complete::generate;
use rand::Rng;
use starship::context::{Context, Properties, Target};
use starship::module::ALL_MODULES;
use starship::*;
use starship::{bug_report, configure, init, logger, num_rayon_threads, print, shadow};
#[derive(Parser, Debug)]
#[clap(
@@ -26,7 +26,7 @@ struct Cli {
command: Commands,
}
#[derive(clap::Parser, ValueEnum, Debug, Clone, PartialEq, Eq)]
#[derive(clap::Parser, ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
enum CompletionShell {
Bash,
Elvish,
@@ -42,7 +42,7 @@ fn generate_shell(shell: impl clap_complete::Generator) {
&mut Cli::command(),
"starship",
&mut io::stdout().lock(),
)
);
}
fn generate_completions(shell: CompletionShell) {
@@ -173,10 +173,11 @@ fn main() {
let exit_code = if is_info_only {
0
} else {
use io::Write;
// 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: {:?}",
+9 -9
View File
@@ -159,7 +159,7 @@ fn get_credentials_duration(
let cache_key = crate::utils::encode_to_hex(&Sha1::digest(start_url.as_bytes()));
// https://github.com/aws/aws-cli/blob/b3421dcdd443db95999364e94266c0337b45cc43/awscli/customizations/sso/utils.py#L89
let mut sso_cred_path = context.get_home()?;
sso_cred_path.push(format!(".aws/sso/cache/{}.json", cache_key));
sso_cred_path.push(format!(".aws/sso/cache/{cache_key}.json"));
let sso_cred_json: json::Value =
json::from_str(&crate::utils::read_file(&sso_cred_path).ok()?).ok()?;
let expires_at = sso_cred_json.get("expiresAt")?.as_str();
@@ -719,7 +719,7 @@ credential_process = /opt/bin/awscreds-retriever
use chrono::{DateTime, SecondsFormat, Utc};
let expiration_env_vars = ["AWS_SESSION_EXPIRATION", "AWS_CREDENTIAL_EXPIRATION"];
expiration_env_vars.iter().for_each(|env_var| {
for env_var in expiration_env_vars {
let now_plus_half_hour: DateTime<Utc> =
DateTime::from_timestamp(chrono::Local::now().timestamp() + 1800, 0).unwrap();
@@ -747,24 +747,24 @@ credential_process = /opt/bin/awscreds-retriever
possible_values.contains(&actual),
"time is not in range: {actual:?}"
);
});
}
}
#[test]
fn expiration_date_set_from_file() -> io::Result<()> {
use chrono::{DateTime, Utc};
let dir = tempfile::tempdir()?;
let credentials_path = dir.path().join("credentials");
let mut file = File::create(&credentials_path)?;
use chrono::{DateTime, Utc};
let now_plus_half_hour: DateTime<Utc> =
DateTime::from_timestamp(chrono::Local::now().timestamp() + 1800, 0).unwrap();
let expiration_date = now_plus_half_hour.to_rfc3339_opts(chrono::SecondsFormat::Secs, true);
let expiration_keys = ["expiration", "x_security_token_expires"];
expiration_keys.iter().for_each(|key| {
for key in expiration_keys {
file.write_all(
format!(
"[astronauts]
@@ -778,7 +778,7 @@ aws_secret_access_key=dummy
.unwrap();
let credentials_env_vars = ["AWS_SHARED_CREDENTIALS_FILE", "AWS_CREDENTIALS_FILE"];
credentials_env_vars.iter().for_each(|env_var| {
for env_var in credentials_env_vars {
let actual = ModuleRenderer::new("aws")
.env("AWS_PROFILE", "astronauts")
.env("AWS_REGION", "ap-northeast-2")
@@ -802,8 +802,8 @@ aws_secret_access_key=dummy
possible_values.contains(&actual),
"time is not in range: {actual:?}"
);
});
});
}
}
dir.close()
}
+5 -6
View File
@@ -34,7 +34,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
if config.disabled {
return None;
};
}
let subscription: Option<Subscription> = get_azure_profile_info(context);
@@ -126,7 +126,7 @@ mod tests {
fn generate_test_config(dir: &TempDir, azure_profile_contents: &str) -> io::Result<()> {
save_string_to_file(
dir,
azure_profile_contents.to_string(),
azure_profile_contents,
String::from("azureProfile.json"),
)?;
@@ -737,7 +737,7 @@ mod tests {
bom_str.push_str(json_str);
let dir_path_no_bom = save_string_to_file(&dir, bom_str, String::from("bom.json"))?;
let dir_path_no_bom = save_string_to_file(&dir, &bom_str, String::from("bom.json"))?;
let sanitized_json = load_azure_profile(&dir_path_no_bom).unwrap();
assert_eq!(
@@ -755,8 +755,7 @@ mod tests {
let json_str =
r#"{"installationId": "3deacd2a-b9db-77e1-aa42-23e2f8dfffc3", "subscriptions": []}"#;
let dir_path_no_bom =
save_string_to_file(&dir, json_str.to_string(), String::from("bom.json"))?;
let dir_path_no_bom = save_string_to_file(&dir, json_str, String::from("bom.json"))?;
let sanitized_json = load_azure_profile(&dir_path_no_bom).unwrap();
assert_eq!(
@@ -783,7 +782,7 @@ mod tests {
fn save_string_to_file(
dir: &TempDir,
contents: String,
contents: &str,
file_name: String,
) -> Result<PathBuf, io::Error> {
let bom_file_path = dir.path().join(file_name);
+3 -3
View File
@@ -70,15 +70,15 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
fn get_battery_status(context: &Context) -> Option<BatteryStatus> {
let battery_info = context.battery_info_provider.get_battery_info()?;
if battery_info.energy_full != 0.0 {
if battery_info.energy_full == 0.0 {
None
} else {
let battery = BatteryStatus {
percentage: battery_info.energy / battery_info.energy_full * 100.0,
state: battery_info.state,
};
log::debug!("Battery status: {battery:?}");
Some(battery)
} else {
None
}
}
+2 -2
View File
@@ -61,10 +61,10 @@ fn get_bun_version(context: &Context) -> Option<String> {
context
.exec_cmd("bun", &["--version"])
.map(get_command_string_output)
.map(parse_bun_version)
.map(|s| parse_bun_version(&s))
}
fn parse_bun_version(bun_version: String) -> String {
fn parse_bun_version(bun_version: &str) -> String {
bun_version.trim_end().to_string()
}
+2 -1
View File
@@ -13,6 +13,7 @@ use std::borrow::Cow;
use std::ops::Deref;
use std::sync::LazyLock;
#[derive(Clone, Copy)]
pub enum Lang {
C,
Cpp,
@@ -36,7 +37,7 @@ fn parse_module<T>(
compilers: [(&str, &str); 2],
) -> Result<Vec<Segment>, crate::formatter::string_formatter::StringFormatterError> {
StringFormatter::new(config.format).and_then(|formatter| {
let cc_compiler_info = LazyLock::new(|| context.exec_cmds_return_first(config.commands));
let cc_compiler_info = LazyLock::new(|| context.exec_cmds_return_first(&config.commands));
formatter
.map_meta(|var, _| match var {
+4 -4
View File
@@ -168,10 +168,10 @@ mod tests {
// The value that should be rendered by the module.
let expected = Some(format!(
"{} ",
Color::Red
.bold()
.dimmed()
.paint(format!("⬢ [{}]", name.unwrap_or(image.unwrap_or("podman"))))
Color::Red.bold().dimmed().paint(format!(
"⬢ [{}]",
name.unwrap_or_else(|| image.unwrap_or("podman"))
))
));
Ok((actual, expected))
+3 -4
View File
@@ -45,16 +45,15 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
.into_iter()
.find_map(|env| context.get_env(env));
let ctx = match docker_context_env {
Some(data) => data,
_ => {
let ctx = if let Some(data) = docker_context_env {
data
} else {
if !docker_config.exists() {
return None;
}
let json = utils::read_file(docker_config).ok()?;
let parsed_json: serde_json::Value = serde_json::from_str(&json).ok()?;
parsed_json.get("currentContext")?.as_str()?.to_owned()
}
};
let default_contexts = ["default", "desktop-linux"];
+3 -6
View File
@@ -282,7 +282,7 @@ fn get_dotnet_file_type(path: &Path) -> Option<FileType> {
Some("csproj" | "fsproj" | "xproj") => return Some(FileType::ProjectFile),
Some("props" | "targets") => return Some(FileType::MsBuildFile),
_ => (),
};
}
None
}
@@ -297,8 +297,7 @@ fn get_version_from_cli(context: &Context) -> Option<String> {
}
fn get_latest_sdk_from_cli(context: &Context) -> Option<String> {
match context.exec_cmd("dotnet", &["--list-sdks"]) {
Some(sdks_output) => {
if let Some(sdks_output) = context.exec_cmd("dotnet", &["--list-sdks"]) {
fn parse_failed<T>() -> Option<T> {
log::warn!("Unable to parse the output from `dotnet --list-sdks`.");
None
@@ -319,8 +318,7 @@ fn get_latest_sdk_from_cli(context: &Context) -> Option<String> {
} else {
parse_failed()
}
}
None => {
} else {
// Older versions of the dotnet cli do not support the --list-sdks command
// So, if the status code indicates failure, fall back to `dotnet --version`
log::debug!(
@@ -329,7 +327,6 @@ fn get_latest_sdk_from_cli(context: &Context) -> Option<String> {
);
get_version_from_cli(context)
}
}
}
struct DotNetFile {
+1 -1
View File
@@ -35,7 +35,7 @@ pub fn module<'a>(name: Option<&str>, context: &'a Context) -> Option<Module<'a>
let mut module = Module::new(mod_name, config.description, None);
if config.disabled {
return None;
};
}
let variable_name = config.variable.or(name)?;
+2 -2
View File
@@ -15,7 +15,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// before it was only checking against whatever is in the config starship.toml
if config.disabled {
return None;
};
}
let checkout_db = if cfg!(windows) {
"_FOSSIL_"
@@ -205,7 +205,7 @@ mod tests {
}
Expect::Symbol(symbol) => expect_symbol = symbol,
Expect::TruncationSymbol(truncation_symbol) => {
expect_truncation_symbol = truncation_symbol
expect_truncation_symbol = truncation_symbol;
}
Expect::NoTruncation => expect_truncation_symbol = "",
Expect::BranchName(branch_name) => expect_branch_name = branch_name,
+1 -1
View File
@@ -15,7 +15,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// before it was only checking against whatever is in the config starship.toml
if config.disabled {
return None;
};
}
let checkout_db = if cfg!(windows) {
"_FOSSIL_"
+6 -5
View File
@@ -23,7 +23,7 @@ impl<'a> GcloudContext {
Self {
config_name: config_name.to_string(),
config_path: PathBuf::from(config_path),
config: Default::default(),
config: OnceLock::default(),
}
}
@@ -73,10 +73,11 @@ fn get_config_dir(context: &Context) -> Option<PathBuf> {
fn get_active_config(context: &Context, config_dir: &Path) -> Option<String> {
context.get_env("CLOUDSDK_ACTIVE_CONFIG_NAME").or_else(|| {
let path = config_dir.join("active_config");
match utils::read_file(path) {
Ok(data) => data.lines().next().map(String::from),
Err(_) => None,
}
utils::read_file(path)
.ok()?
.lines()
.next()
.map(String::from)
})
}
+4 -4
View File
@@ -45,11 +45,11 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut remote_name_graphemes: Vec<&str> = Vec::new();
if let Some(remote) = repo.remote.as_ref() {
if let Some(branch) = &remote.branch {
remote_branch_graphemes = branch.graphemes(true).collect()
};
remote_branch_graphemes = branch.graphemes(true).collect();
}
if let Some(name) = &remote.name {
remote_name_graphemes = name.graphemes(true).collect()
};
remote_name_graphemes = name.graphemes(true).collect();
}
}
// Truncate fields if need be
+1 -1
View File
@@ -19,7 +19,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let is_detached = git_head.is_detached();
if config.only_detached && !is_detached {
return None;
};
}
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter
+12 -8
View File
@@ -21,7 +21,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// before it was only checking against whatever is in the config starship.toml
if config.disabled {
return None;
};
}
let repo = context.get_repo().ok()?;
let gix_repo = repo.open();
@@ -58,7 +58,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
gix_repo.write_blob([]).ok()?; /* create empty blob */
let tree_index_cache = prevent_external_diff(
gix_repo
.diff_resource_cache(gix::diff::blob::pipeline::Mode::ToGit, Default::default())
.diff_resource_cache(
gix::diff::blob::pipeline::Mode::ToGit,
WorktreeRoots::default(),
)
.ok()?,
);
let index_worktree_cache = prevent_external_diff(
@@ -194,7 +197,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
entry,
status:
EntryStatus::Change(Change::Modification {
content_change: Some(_),
content_change: Some(()),
..
}),
..
@@ -231,7 +234,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
_ => {}
}
}
};
}
diff
},
)
@@ -382,12 +385,13 @@ impl GitDiff {
only_nonzero_diffs: bool,
changed: &str,
) -> Option<Result<&str, StringFormatterError>> {
match only_nonzero_diffs {
true => match changed {
if only_nonzero_diffs {
match changed {
"0" => None,
_ => Some(Ok(changed)),
},
false => Some(Ok(changed)),
}
} else {
Some(Ok(changed))
}
}
}
+5 -14
View File
@@ -60,22 +60,12 @@ fn get_state_description<'a>(
current: None,
total: None,
}),
InProgress::Revert => Some(StateDescription {
InProgress::Revert | InProgress::RevertSequence => Some(StateDescription {
label: config.revert,
current: None,
total: None,
}),
InProgress::RevertSequence => Some(StateDescription {
label: config.revert,
current: None,
total: None,
}),
InProgress::CherryPick => Some(StateDescription {
label: config.cherry_pick,
current: None,
total: None,
}),
InProgress::CherryPickSequence => Some(StateDescription {
InProgress::CherryPick | InProgress::CherryPickSequence => Some(StateDescription {
label: config.cherry_pick,
current: None,
total: None,
@@ -95,8 +85,9 @@ fn get_state_description<'a>(
current: None,
total: None,
}),
InProgress::Rebase => Some(describe_rebase(repo, config.rebase)),
InProgress::RebaseInteractive => Some(describe_rebase(repo, config.rebase)),
InProgress::Rebase | InProgress::RebaseInteractive => {
Some(describe_rebase(repo, config.rebase))
}
}
}
+11 -21
View File
@@ -118,9 +118,8 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
Ok(segments) => {
if segments.is_empty() {
return None;
} else {
segments
}
segments
}
Err(error) => {
log::warn!("Error in module `git_status`:\n{error}");
@@ -160,27 +159,21 @@ impl<'a> GitStatusInfo<'a> {
pub fn get_repo_status(&self) -> Option<&RepoStatus> {
self.repo_status
.get_or_init(
|| match get_static_repo_status(self.context, self.repo, &self.config) {
Some(repo_status) => Some(repo_status),
None => {
.get_or_init(|| {
get_static_repo_status(self.context, self.repo, &self.config).or_else(|| {
log::debug!("get_repo_status: git status execution failed");
None
}
},
)
.as_ref()
.map(|repo_status| repo_status.as_ref())
})
})
.as_deref()
}
pub fn get_stashed(&self) -> &Option<usize> {
self.stashed_count
.get_or_init(|| match get_stashed_count(self.repo) {
Some(stashed_count) => Some(stashed_count),
None => {
self.stashed_count.get_or_init(|| {
get_stashed_count(self.repo).or_else(|| {
log::debug!("get_stashed_count: git stash execution failed");
None
}
})
})
}
@@ -380,15 +373,12 @@ fn get_repo_status(
status::Item::TreeIndex(change) => {
use gix::diff::index::Change;
match change {
Change::Addition { .. } => {
Change::Addition { .. } | Change::Modification { .. } => {
repo_status.staged += 1;
}
Change::Deletion { .. } => {
repo_status.deleted += 1;
}
Change::Modification { .. } => {
repo_status.staged += 1;
}
Change::Rewrite { .. } => {
repo_status.renamed += 1;
}
@@ -550,7 +540,7 @@ impl RepoStatus {
Some('1') => self.parse_normal_status(&s[2..4]),
Some('2') => {
self.renamed += 1;
self.parse_normal_status(&s[2..4])
self.parse_normal_status(&s[2..4]);
}
Some('u') => self.conflicted += 1,
Some('?') => self.untracked += 1,
+18 -14
View File
@@ -1,3 +1,5 @@
use std::path::Path;
use crate::{
config::ModuleConfig,
configs::gradle::GradleConfig,
@@ -82,29 +84,31 @@ fn parse_gradle_version_from_properties(wrapper_properties: &str) -> Option<Stri
/// Tries to find the gradle-wrapper.properties file.
fn get_wrapper_properties_file(context: &Context, recursive: bool) -> Option<String> {
let mut properties = None;
let read_wrapper_properties = |base_dir: &Path| {
utils::read_file(base_dir.join("gradle/wrapper/gradle-wrapper.properties")).ok()
};
// Try current directory first
if context
.try_begin_scan()?
.set_folders(&["gradle"])
.is_match()
{
properties = utils::read_file(
context
.current_dir
.join("gradle/wrapper/gradle-wrapper.properties"),
)
.ok();
};
if recursive && properties.is_none() {
if let Some(properties) = read_wrapper_properties(&context.current_dir) {
return Some(properties);
}
}
// Try parent directories if recursive
if recursive {
for dir in context.current_dir.ancestors().skip(1) {
properties =
utils::read_file(dir.join("gradle/wrapper/gradle-wrapper.properties")).ok();
if properties.is_some() {
break;
if let Some(properties) = read_wrapper_properties(dir) {
return Some(properties);
}
}
}
properties
None
}
#[cfg(test)]
+1 -1
View File
@@ -15,7 +15,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
if !is_guix_shell {
return None;
};
}
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter
+1 -1
View File
@@ -120,7 +120,7 @@ mod tests {
assert_eq!(
Some("4.3.0-rc.1+".to_string()),
parse_haxe_version(sample_haxe_output)
)
);
}
#[test]
+1 -1
View File
@@ -19,7 +19,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// before it was only checking against whatever is in the config starship.toml
if config.disabled {
return None;
};
}
let len = if config.truncation_length <= 0 {
log::warn!(
+3 -3
View File
@@ -17,7 +17,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// before it was only checking against whatever is in the config starship.toml
if config.disabled {
return None;
};
}
let repo_root = context.begin_ancestor_scan().set_folders(&[".hg"]).scan()?;
@@ -39,7 +39,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
module.set_segments(match parsed {
Ok(segments) => segments,
Err(error) => {
log::warn!("Error in module `hg_state`:\n{}", error);
log::warn!("Error in module `hg_state`:\n{error}");
return None;
}
});
@@ -85,7 +85,7 @@ fn get_state_description<'a>(
label: config.merge,
})
} else {
return None;
None
}
}
+3 -5
View File
@@ -30,12 +30,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
//rustc doesn't let you do an "if" and an "if let" in the same if statement
// if this changes in the future this can become a lot cleaner
let mut host = if !config.trim_at.is_empty() {
if let Some(index) = host.find(config.trim_at) {
host.split_at(index).0
} else {
let mut host = if config.trim_at.is_empty() {
host.as_ref()
}
} else if let Some(index) = host.find(config.trim_at) {
host.split_at(index).0
} else {
host.as_ref()
};
+9 -9
View File
@@ -46,7 +46,15 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let default_threshold = 1;
let mut module_symbol = "";
let mut module_number = String::new();
if config.threshold != default_threshold {
if config.threshold == default_threshold {
if num_of_jobs >= config.symbol_threshold {
module_symbol = config.symbol;
}
if num_of_jobs >= config.number_threshold {
module_number = num_of_jobs.to_string();
}
} else {
log::warn!(
"`threshold` in [jobs] is deprecated . Please remove it and use `symbol_threshold` and `number_threshold`."
);
@@ -61,14 +69,6 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
module_symbol = config.symbol;
module_number = num_of_jobs.to_string();
}
} else {
if num_of_jobs >= config.symbol_threshold {
module_symbol = config.symbol;
}
if num_of_jobs >= config.number_threshold {
module_number = num_of_jobs.to_string();
}
}
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+6 -8
View File
@@ -82,7 +82,7 @@ fn get_aliased_name<'a>(
match replaced {
Cow::Owned(replaced) => Some(replaced),
// It didn't match...
_ => None,
Cow::Borrowed(_) => None,
}
}
@@ -140,7 +140,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// before it was only checking against whatever is in the config starship.toml
if config.disabled {
return None;
};
}
let have_env_config = !config.detect_env_vars.is_empty();
let have_env_vars = have_env_config.then(|| context.detect_env_vars(&config.detect_env_vars));
@@ -326,7 +326,7 @@ mod deprecated {
match replaced {
// We have a match if the replaced string is different from the original
Cow::Owned(replaced) => Some(replaced),
_ => None,
Cow::Borrowed(_) => None,
}
})
};
@@ -1542,7 +1542,7 @@ users: []
}
#[test]
fn test_json_kubeconfig_is_parsed_as_json() -> std::io::Result<()> {
fn test_json_kubeconfig_is_parsed_as_json() {
let json_kubeconfig = r#"{
"apiVersion": "v1",
"clusters": [],
@@ -1569,11 +1569,10 @@ users: []
Document::Json(..) => {}
_ => panic!("Expected Document::Json, got {actual:?}"),
}
Ok(())
}
#[test]
fn fallback_to_yaml_parsing() -> std::io::Result<()> {
fn fallback_to_yaml_parsing() {
let json_kubeconfig = r#"{
"apiVersion": v1,
"clusters": [],
@@ -1598,9 +1597,8 @@ users: []
let actual = results.first().unwrap();
match actual {
Document::Yaml(..) => {}
_ => panic!("Expected Document::Yaml, got {actual:?}"),
Document::Json(_) => panic!("Expected Document::Yaml, got {actual:?}"),
}
Ok(())
}
#[test]
+1 -1
View File
@@ -34,7 +34,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// before it was only checking against whatever is in the config starship.toml
if config.disabled {
return None;
};
}
let ssh_connection = context.get_env("SSH_CONNECTION");
if config.ssh_only && ssh_connection.is_none() {
+2 -2
View File
@@ -170,7 +170,7 @@ mod test {
})
.collect();
assert!(output.is_some())
assert!(output.is_some());
}
#[test]
@@ -183,6 +183,6 @@ mod test {
})
.collect();
assert!(output.is_none())
assert!(output.is_none());
}
}
+3 -6
View File
@@ -10,7 +10,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
if config.disabled {
return None;
};
}
let ctx_str = context
.exec_cmd("nats", &["context", "info", "--json"])?
@@ -53,12 +53,11 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
#[cfg(test)]
mod tests {
use nu_ansi_term::Color;
use std::io;
use crate::test::ModuleRenderer;
#[test]
fn show_context() -> io::Result<()> {
fn show_context() {
let actual = ModuleRenderer::new("nats")
.config(toml::toml! {
[nats]
@@ -69,11 +68,10 @@ mod tests {
.collect();
let expected = Some(format!("{}", Color::Purple.bold().paint("localhost")));
assert_eq!(expected, actual);
Ok(())
}
#[test]
fn test_with_symbol() -> io::Result<()> {
fn test_with_symbol() {
let actual = ModuleRenderer::new("nats")
.config(toml::toml! {
[nats]
@@ -84,6 +82,5 @@ mod tests {
.collect();
let expected = Some(format!("{}", Color::Red.bold().paint("✉️ localhost")));
assert_eq!(expected, actual);
Ok(())
}
}
+1 -1
View File
@@ -95,7 +95,7 @@ mod tests {
git hash: 7e83adff84be5d0c401a213eccb61e321a3fb1ff
active boot switches: -d:release\n";
assert_eq!(Some("1.2.0"), parse_nim_version(sample_nimc_output))
assert_eq!(Some("1.2.0"), parse_nim_version(sample_nimc_output));
}
#[test]
+1 -1
View File
@@ -20,7 +20,7 @@ impl NixShellType {
Some("pure") => return Some(Pure),
Some("impure") => return Some(Impure),
_ => {}
};
}
if use_heuristic {
Self::in_new_nix_shell(context).map(|()| Unknown)
+3 -3
View File
@@ -101,10 +101,10 @@ fn parse_opam_switch(opam_switch: &str) -> Option<OpamSwitch> {
}
let path = Path::new(opam_switch);
if !path.has_root() {
Some((SwitchType::Global, opam_switch.to_string()))
} else {
if path.has_root() {
Some((SwitchType::Local, path.file_name()?.to_str()?.to_string()))
} else {
Some((SwitchType::Global, opam_switch.to_string()))
}
}
+2 -2
View File
@@ -62,10 +62,10 @@ fn get_opa_version(context: &Context) -> Option<String> {
let version_output: String = context
.exec_cmd("opa", &["version"])
.map(get_command_string_output)?;
parse_opa_version(version_output)
parse_opa_version(&version_output)
}
fn parse_opa_version(version_output: String) -> Option<String> {
fn parse_opa_version(version_output: &str) -> Option<String> {
Some(version_output.split_whitespace().nth(1)?.to_string())
}
+7 -8
View File
@@ -21,7 +21,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter
.map_meta(|variable, _| match variable {
"symbol" => get_symbol(&config, &os.os_type()),
"symbol" => get_symbol(&config, os.os_type()),
_ => None,
})
.map_style(|variable| match variable {
@@ -51,7 +51,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// Get the operating system symbol from user config, or else default config
// when user has not defined a symbol for the operating system.
fn get_symbol<'a>(config: &'a OSConfig, os_type: &os_info::Type) -> Option<&'a str> {
fn get_symbol<'a>(config: &'a OSConfig, os_type: os_info::Type) -> Option<&'a str> {
config
.get_symbol(os_type)
.or_else(|| OSConfig::default().get_symbol(os_type))
@@ -171,7 +171,7 @@ mod tests {
];
for (t, e) in type_expected_pairs {
assert_eq!(get_symbol(&config, &t), e);
assert_eq!(get_symbol(&config, t), e);
}
}
@@ -261,7 +261,7 @@ mod tests {
];
for (t, e) in type_expected_pairs {
assert_eq!(get_symbol(&config, &t), e);
assert_eq!(get_symbol(&config, t), e);
}
}
@@ -316,7 +316,7 @@ mod tests {
];
for (t, e) in type_expected_pairs {
assert_eq!(get_symbol(&config, &t), e);
assert_eq!(get_symbol(&config, t), e);
}
}
@@ -344,11 +344,12 @@ mod tests {
Type::Arch | Type::Artix | Type::CachyOS => "🎗️ ",
Type::Bluefin => "🐟 ",
Type::CentOS | Type::AlmaLinux | Type::RockyLinux => "💠 ",
Type::Cygwin => "",
Type::Debian => "🌀 ",
Type::DragonFly => "🐉 ",
Type::Emscripten => "🔗 ",
Type::EndeavourOS => "🚀 ",
Type::Fedora | Type::Nobara => "🎩 ",
Type::Fedora | Type::Nobara | Type::Redhat | Type::RedHatEnterprise => "🎩 ",
Type::FreeBSD => "😈 ",
Type::Garuda => "🦅 ",
Type::Gentoo => "🗜️ ",
@@ -371,8 +372,6 @@ mod tests {
Type::OracleLinux => "🦴 ",
Type::Pop => "🍭 ",
Type::Raspbian => "🍓 ",
Type::Redhat => "🎩 ",
Type::RedHatEnterprise => "🎩 ",
Type::Redox => "🧪 ",
Type::Solus => "",
Type::SUSE => "🦎 ",
+5 -4
View File
@@ -3,6 +3,7 @@ use crate::configs::package::PackageConfig;
use crate::formatter::{StringFormatter, VersionFormatter};
use ini::Ini;
use jsonc_parser::ParseOptions;
use quick_xml::Reader as QXReader;
use quick_xml::events::Event as QXEvent;
use regex::Regex;
@@ -57,13 +58,13 @@ fn get_node_package_version(context: &Context, config: &PackageConfig) -> Option
let raw_version = package_json.get("version")?.as_str()?;
if raw_version == "null" {
return None;
};
}
let formatted_version = format_version(raw_version, config.version_format)?;
if formatted_version == "v0.0.0-development" || formatted_version.starts_with("v0.0.0-semantic")
{
return Some("semantic".to_string());
};
}
Some(formatted_version)
}
@@ -78,7 +79,7 @@ fn get_jsr_package_version(context: &Context, config: &PackageConfig) -> Option<
})?;
let json_content: json::Value = if filename.ends_with(".jsonc") {
jsonc_parser::parse_to_serde_value(&contents, &Default::default()).ok()??
jsonc_parser::parse_to_serde_value(&contents, &ParseOptions::default()).ok()??
} else {
json::from_str(&contents).ok()?
};
@@ -298,7 +299,7 @@ fn get_nimble_version(context: &Context, config: &PackageConfig) -> Option<Strin
.is_match()
{
return None;
};
}
let cmd_output = context.exec_cmd("nimble", &["dump", "--json"])?;
let nimble_json: json::Value = json::from_str(&cmd_output.stdout).ok()?;
+1 -1
View File
@@ -23,7 +23,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// We default to disabled=true, so we have to check after loading our config module.
if config.disabled {
return None;
};
}
let channel_name = get_pijul_current_channel(context)?;
+1 -1
View File
@@ -77,7 +77,7 @@ fn get_pixi_version(context: &Context, config: &PixiConfig) -> Option<String> {
.find_map(|binary| context.exec_cmd(binary, &["--version"]))
.map(get_command_string_output)?;
Some(version.split_once(" ")?.1.trim().to_string())
Some(version.split_once(' ')?.1.trim().to_string())
}
#[cfg(test)]
+7 -8
View File
@@ -96,9 +96,8 @@ fn parse_version(version: &str) -> &str {
if *c == b'.' {
if periods == 2 {
return &sanitized_version[0..i];
} else {
periods += 1;
}
periods += 1;
}
}
// We didn't hit 3 periods, so we just return the whole string.
@@ -210,7 +209,7 @@ mod tests {
use std::io;
use super::*;
use crate::context::Target;
use crate::context::{Properties, Target};
use crate::test::ModuleRenderer;
use nu_ansi_term::Color;
@@ -267,19 +266,19 @@ mod tests {
#[test]
fn get_home_dir() {
let mut context = Context::new(Default::default(), Target::Main);
let mut context = Context::new(Properties::default(), Target::Main);
context.env.insert("HOME", "/home/sweet/home".to_string());
assert_eq!(
pulumi_home_dir(&context),
Some(PathBuf::from("/home/sweet/home/.pulumi"))
);
context.env.insert("PULUMI_HOME", "/a/dir".to_string());
assert_eq!(pulumi_home_dir(&context), Some(PathBuf::from("/a/dir")))
assert_eq!(pulumi_home_dir(&context), Some(PathBuf::from("/a/dir")));
}
#[test]
fn test_get_pulumi_workspace() {
let mut context = Context::new(Default::default(), Target::Main);
let mut context = Context::new(Properties::default(), Target::Main);
context.env.insert("HOME", "/home/sweet/home".to_string());
let name = "foobar";
let project_file = PathBuf::from("/hello/Pulumi.yaml");
@@ -362,7 +361,7 @@ mod tests {
credential.sync_all()?;
let rendered = module_renderer
.path(root.clone())
.logical_path(root.clone())
.logical_path(root)
.config(toml::toml! {
[pulumi]
format = "via [$symbol($username@)$stack]($style) "
@@ -422,7 +421,7 @@ mod tests {
credential.sync_all()?;
let rendered = module_renderer
.path(root.clone())
.logical_path(root.clone())
.logical_path(root)
.config(toml::toml! {
[pulumi]
format = "via [$symbol($username@)$stack]($style) "
+2 -2
View File
@@ -24,7 +24,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
if !is_py_project && !has_env_vars {
return None;
};
}
let pyenv_prefix = if config.pyenv_version_name {
config.pyenv_prefix
@@ -86,7 +86,7 @@ fn get_pyenv_version(context: &Context) -> Option<String> {
.stdout
.trim()
.to_string(),
)
);
}
version_name
+19 -19
View File
@@ -466,9 +466,9 @@ impl RustupSettings {
fn from_toml_str(toml_str: &str) -> Option<Self> {
let settings = toml::from_str::<Self>(toml_str).ok()?;
match settings.version.as_deref() {
Some("12") => Some(settings),
_ => {
if settings.version.as_deref() == Some("12") {
Some(settings)
} else {
log::warn!(
r#"Rustup settings version is {:?}, expected "12""#,
settings.version
@@ -476,7 +476,6 @@ impl RustupSettings {
None
}
}
}
fn default_host_triple(&self) -> Option<&str> {
self.default_host_triple.as_deref()
@@ -499,7 +498,8 @@ impl RustupSettings {
#[cfg(test)]
mod tests {
use crate::context::{Shell, Target};
use crate::context::{Properties, Shell, Target};
use crate::context_env::Env;
use std::io;
use std::process::{ExitStatus, Output};
use std::sync::LazyLock;
@@ -735,7 +735,7 @@ version = "12"
Target::Main,
dir.path().into(),
dir.path().into(),
Default::default(),
Env::default(),
);
assert_eq!(
@@ -752,12 +752,12 @@ version = "12"
)?;
let context = Context::new_with_shell_and_path(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
dir.path().into(),
dir.path().into(),
Default::default(),
Env::default(),
);
assert_eq!(
@@ -779,7 +779,7 @@ version = "12"
Target::Main,
dir.path().into(),
dir.path().into(),
Default::default(),
Env::default(),
);
assert_eq!(
@@ -798,12 +798,12 @@ version = "12"
)?;
let context = Context::new_with_shell_and_path(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
child_dir_path.clone(),
child_dir_path,
Default::default(),
Env::default(),
);
assert_eq!(
@@ -819,12 +819,12 @@ version = "12"
fs::write(dir.path().join("rust-toolchain.toml"), "1.34.0")?;
let context = Context::new_with_shell_and_path(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
dir.path().into(),
dir.path().into(),
Default::default(),
Env::default(),
);
assert_eq!(find_rust_toolchain_file(&context), None);
@@ -838,12 +838,12 @@ version = "12"
)?;
let context = Context::new_with_shell_and_path(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
dir.path().into(),
dir.path().into(),
Default::default(),
Env::default(),
);
assert_eq!(
@@ -860,12 +860,12 @@ version = "12"
)?;
let context = Context::new_with_shell_and_path(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
dir.path().into(),
dir.path().into(),
Default::default(),
Env::default(),
);
assert_eq!(
@@ -884,12 +884,12 @@ version = "12"
)?;
let context = Context::new_with_shell_and_path(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
child_dir_path.clone(),
child_dir_path,
Default::default(),
Env::default(),
);
assert_eq!(
+3 -3
View File
@@ -39,10 +39,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
}
}
let symbol = if repeat_count != 1 {
Cow::Owned(config.symbol.repeat(repeat_count))
} else {
let symbol = if repeat_count == 1 {
Cow::Borrowed(config.symbol)
} else {
Cow::Owned(config.symbol.repeat(repeat_count))
};
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+27 -22
View File
@@ -26,21 +26,25 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// before it was only checking against whatever is in the config starship.toml
if config.disabled {
return None;
};
}
let exit_code = context.properties.status_code.as_deref().unwrap_or("0");
let pipestatus_status = match &context.properties.pipestatus {
None => PipeStatusStatus::Disabled,
Some(ps) => match ps.len() > 1 {
true => PipeStatusStatus::Pipe(ps),
false => PipeStatusStatus::NoPipe,
},
Some(ps) => {
if ps.len() > 1 {
PipeStatusStatus::Pipe(ps)
} else {
PipeStatusStatus::NoPipe
}
}
};
let pipestatus_status = match config.pipestatus {
true => pipestatus_status,
false => PipeStatusStatus::Disabled,
let pipestatus_status = if config.pipestatus {
pipestatus_status
} else {
PipeStatusStatus::Disabled
};
// Exit code is zero while success_symbol and pipestatus are all zero or disabled/missing
@@ -91,7 +95,7 @@ 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, main_format, Some(&pipestatus), &config, context);
module.set_segments(match parsed {
Ok(segments) => segments,
@@ -106,35 +110,36 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
fn format_exit_code<'a>(
exit_code: &'a str,
format: &'a str,
pipestatus: Option<Vec<Segment>>,
pipestatus: Option<&Vec<Segment>>,
config: &'a StatusConfig,
context: &'a Context,
) -> Result<Vec<Segment>, StringFormatterError> {
// First, parse as i64 to accept both i32 or u32, then normalize to i32.
let exit_code_int: ExitCode = match exit_code.parse::<i64>() {
Ok(i) => i as ExitCode,
Err(_) => {
let exit_code_int = if let Ok(i) = exit_code.parse::<i64>() {
i as ExitCode
} else {
log::warn!("Error parsing exit_code string to int");
return Ok(Vec::new());
}
};
let hex_status = format!("0x{exit_code_int:X}");
let common_meaning = status_common_meaning(exit_code_int);
let raw_signal_number = match config.recognize_signal_code {
true => status_to_signal(exit_code_int),
false => None,
let raw_signal_number = if config.recognize_signal_code {
status_to_signal(exit_code_int)
} else {
None
};
let signal_number = raw_signal_number.map(|sn| sn.to_string());
let signal_name =
raw_signal_number.and_then(|sn| status_signal_name(sn).or(signal_number.as_deref()));
// If not a signal and not a common meaning, it should at least print the raw exit code number
let maybe_exit_code_number = match common_meaning.is_none() && signal_name.is_none() {
true => Some(exit_code),
false => None,
let maybe_exit_code_number = if common_meaning.is_none() && signal_name.is_none() {
Some(exit_code)
} else {
None
};
StringFormatter::new(format).and_then(|formatter| {
@@ -184,7 +189,7 @@ fn format_exit_code<'a>(
log::warn!("pipestatus variable is only available in pipestatus_format");
None
}
"pipestatus" => pipestatus.clone().map(Ok),
"pipestatus" => pipestatus.cloned().map(Ok),
_ => None,
})
.parse(None, Some(context))
@@ -835,7 +840,7 @@ mod tests {
.pipestatus(pipe_exit_code)
.width(100);
let context = crate::modules::Context::from(renderer);
let actual = crate::print::get_prompt(context);
let actual = crate::print::get_prompt(&context);
let mut escaping = false;
let mut width = 0;
+9 -13
View File
@@ -13,7 +13,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// before it was only checking against whatever is in the config starship.toml
if config.disabled {
return None;
};
}
// Hide prompt if current time is not inside time_range
let (display_start, display_end) = parse_time_range(config.time_range);
@@ -27,19 +27,15 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
log::trace!("Timer module is enabled with format string: {time_format}");
let formatted_time_string = if config.utc_time_offset != "local" {
match create_offset_time_string(Utc::now(), config.utc_time_offset, time_format) {
Ok(formatted_string) => formatted_string,
Err(_) => {
log::warn!(
"Invalid utc_time_offset configuration provided! Falling back to \"local\"."
);
let formatted_time_string = create_offset_time_string(
Utc::now(),
config.utc_time_offset,
time_format,
)
.unwrap_or_else(|_| {
log::warn!("Invalid utc_time_offset configuration provided! Falling back to \"local\".");
format_time(time_format, Local::now())
}
}
} else {
format_time(time_format, Local::now())
};
});
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter
+3 -3
View File
@@ -31,21 +31,21 @@ mod tests {
fn truncate_smaller_path_than_provided_length() {
let path = "~/starship";
let output = truncate(path, 3);
assert_eq!(output, None)
assert_eq!(output, None);
}
#[test]
fn truncate_same_path_as_provided_length() {
let path = "~/starship/engines";
let output = truncate(path, 3);
assert_eq!(output, None)
assert_eq!(output, None);
}
#[test]
fn truncate_slightly_larger_path_than_provided_length() {
let path = "~/starship/engines/booster";
let output = truncate(path, 3);
assert_eq!(output.as_deref(), Some("starship/engines/booster"))
assert_eq!(output.as_deref(), Some("starship/engines/booster"));
}
#[test]
+5 -4
View File
@@ -38,10 +38,11 @@ pub fn is_write_allowed(folder_path: &Path) -> Result<bool, String> {
#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
fn get_supplementary_groups() -> Vec<u32> {
match nix::unistd::getgroups() {
Err(_) => Vec::new(),
Ok(v) => v.into_iter().map(nix::unistd::Gid::as_raw).collect(),
}
nix::unistd::getgroups()
.unwrap_or_default()
.into_iter()
.map(nix::unistd::Gid::as_raw)
.collect()
}
#[cfg(all(unix, any(target_os = "macos", target_os = "ios")))]
+10 -11
View File
@@ -12,7 +12,6 @@ pub fn truncate_text(text: &str, length: usize, truncation_symbol: &str) -> Stri
let truncated_graphemes = get_graphemes(text, length);
// The truncation symbol should only be added if we truncated
if length < graphemes_len(text) {
let truncation_symbol = get_graphemes(truncation_symbol, 1);
truncated_graphemes + truncation_symbol.as_str()
@@ -45,52 +44,52 @@ mod tests {
#[test]
fn test_changed_truncation_symbol() {
test_truncate_length("1337_hello_world", 15, "1337_hello_worl", "%")
test_truncate_length("1337_hello_world", 15, "1337_hello_worl", "%");
}
#[test]
fn test_no_truncation_symbol() {
test_truncate_length("1337_hello_world", 15, "1337_hello_worl", "")
test_truncate_length("1337_hello_world", 15, "1337_hello_worl", "");
}
#[test]
fn test_ascii_boundary_below() {
test_truncate_length("1337_hello_world", 15, "1337_hello_worl", "")
test_truncate_length("1337_hello_world", 15, "1337_hello_worl", "");
}
#[test]
fn test_ascii_boundary_on() {
test_truncate_length("1337_hello_world", 16, "1337_hello_world", "")
test_truncate_length("1337_hello_world", 16, "1337_hello_world", "");
}
#[test]
fn test_ascii_boundary_above() {
test_truncate_length("1337_hello_world", 17, "1337_hello_world", "")
test_truncate_length("1337_hello_world", 17, "1337_hello_world", "");
}
#[test]
fn test_one() {
test_truncate_length("1337_hello_world", 1, "1", "")
test_truncate_length("1337_hello_world", 1, "1", "");
}
#[test]
fn test_negative() {
test_truncate_length("1337_hello_world", -1, "1337_hello_world", "")
test_truncate_length("1337_hello_world", -1, "1337_hello_world", "");
}
#[test]
fn test_hindi_truncation() {
test_truncate_length("नमस्ते", 2, "नम", "")
test_truncate_length("नमस्ते", 2, "नम", "");
}
#[test]
fn test_hindi_truncation2() {
test_truncate_length("नमस्त", 2, "नम", "")
test_truncate_length("नमस्त", 2, "नम", "");
}
#[test]
fn test_japanese_truncation() {
test_truncate_length("がんばってね", 4, "がんばっ", "")
test_truncate_length("がんばってね", 4, "がんばっ", "");
}
fn test_truncate_length(
+1 -1
View File
@@ -77,7 +77,7 @@ mod tests {
#[test]
fn test_parse_v_version() {
const OUTPUT: &str = "V 0.2 30c0659\n";
assert_eq!(parse_v_version(OUTPUT), Some("0.2".to_string()))
assert_eq!(parse_v_version(OUTPUT), Some("0.2".to_string()));
}
#[test]
+29 -29
View File
@@ -61,10 +61,10 @@ 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();
write!(handle, "{}", get_prompt(&context)).unwrap();
}
pub fn get_prompt(context: Context) -> String {
pub fn get_prompt(context: &Context) -> String {
let config = &context.root_config;
let mut buf = String::new();
@@ -83,7 +83,7 @@ pub fn get_prompt(context: Context) -> String {
buf.push_str("\x1b[J"); // An ASCII control code to clear screen
}
let (formatter, modules) = load_formatter_and_modules(&context);
let (formatter, modules) = load_formatter_and_modules(context);
let formatter = formatter.map_variables_to_segments(|module| {
// Make $all display all modules not explicitly referenced
@@ -91,7 +91,7 @@ pub fn get_prompt(context: Context) -> String {
Some(Ok(all_modules_uniq(&modules)
.par_iter()
.flat_map(|module| {
handle_module(module, &context, &modules)
handle_module(module, context, &modules)
.into_iter()
.flat_map(|module| module.segments)
.collect::<Vec<Segment>>()
@@ -101,7 +101,7 @@ pub fn get_prompt(context: Context) -> String {
None
} else {
// Get segments from module
Some(Ok(handle_module(module, &context, &modules)
Some(Ok(handle_module(module, context, &modules)
.into_iter()
.flat_map(|module| module.segments)
.collect::<Vec<Segment>>()))
@@ -112,7 +112,7 @@ pub fn get_prompt(context: Context) -> String {
let mut root_module = Module::new("Starship Root", "The root module", None);
root_module.set_segments(
formatter
.parse(None, Some(&context))
.parse(None, Some(context))
.expect("Unexpected error returned in root format variables"),
);
@@ -144,12 +144,12 @@ pub fn get_prompt(context: Context) -> String {
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();
let module = get_module(module_name, &context).unwrap_or_default();
print!("{module}");
}
pub fn get_module(module_name: &str, context: Context) -> Option<String> {
modules::handle(module_name, &context).map(|m| m.to_string())
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: Properties) {
@@ -289,7 +289,7 @@ pub fn explain(args: Properties) {
" ".repeat(max_module_width - info.value_len),
info.desc,
);
};
}
}
}
@@ -404,7 +404,7 @@ fn all_modules_uniq(module_list: &BTreeSet<String>) -> Vec<String> {
let mut prompt_order: Vec<String> = Vec::new();
for module in PROMPT_ORDER {
if !module_list.contains(*module) {
prompt_order.push(String::from(*module))
prompt_order.push(String::from(*module));
}
}
@@ -454,7 +454,7 @@ fn load_formatter_and_modules<'a>(context: &'a Context) -> (StringFormatter<'a>,
"format".to_string()
};
log::error!("Error parsing {name:?}: {e}");
};
}
if let Err(ref e) = rf {
log::error!("Error parsing right_format: {e}");
@@ -541,7 +541,7 @@ mod test {
context.target = Target::Main;
let expected = String::from(">\n>");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
}
@@ -555,7 +555,7 @@ mod test {
context.target = Target::Right;
let expected = String::from(">>"); // should strip new lines
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
}
@@ -572,7 +572,7 @@ mod test {
context.current_dir = dir.path().to_path_buf();
let expected = String::from(">");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
dir.close()
}
@@ -591,7 +591,7 @@ mod test {
context.target = Target::Right;
let expected = String::from(">");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
dir.close()
}
@@ -608,7 +608,7 @@ mod test {
context.target = Target::Profile("test".to_string());
let expected = String::from("0_0>>");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
}
@@ -624,7 +624,7 @@ mod test {
context.target = Target::Profile("wrong_prompt".to_string());
let expected = String::from(">");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
}
@@ -636,21 +636,21 @@ mod test {
context.target = Target::Continuation;
let expected = String::from("><>");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
}
#[test]
fn preset_list_returns_one_or_more_items() {
assert!(preset_list().trim().split('\n').count() > 0);
assert!(preset_list().lines().count() > 0);
}
#[test]
fn preset_command_does_not_panic_on_correct_inputs() {
preset_command(None, None, true);
Preset::value_variants()
.iter()
.for_each(|v| preset_command(Some(v.clone()), None, false));
for v in Preset::value_variants() {
preset_command(Some(v.clone()), None, false);
}
}
#[test]
@@ -687,7 +687,7 @@ mod test {
context.current_dir = dir.path().to_path_buf();
let expected = String::from("\nab");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
dir.close()
}
@@ -709,7 +709,7 @@ mod test {
context.env.insert("c", "c".to_string());
let expected = String::from("\nabc");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
}
@@ -731,7 +731,7 @@ mod test {
context.current_dir = dir.path().to_path_buf();
let expected = String::from("\ncab");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
dir.close()
}
@@ -756,7 +756,7 @@ mod test {
context.env.insert("d", "d".to_string());
let expected = String::from("\ncdab");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
}
@@ -775,7 +775,7 @@ mod test {
context.current_dir = dir.path().to_path_buf();
let expected = String::from("\nb");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
dir.close()
}
@@ -792,7 +792,7 @@ mod test {
context.current_dir = dir.path().to_path_buf();
let expected = String::from("\n");
let actual = get_prompt(context);
let actual = get_prompt(&context);
assert_eq!(expected, actual);
dir.close()
}
+4 -4
View File
@@ -103,12 +103,12 @@ impl Segment {
let mut segs: Vec<Self> = Vec::new();
value.into().split(LINE_TERMINATOR).for_each(|s| {
if !segs.is_empty() {
segs.push(Self::LineTerm)
segs.push(Self::LineTerm);
}
segs.push(Self::Text(TextSegment {
value: String::from(s),
style,
}))
}));
});
segs
}
@@ -136,12 +136,12 @@ impl Segment {
match self {
Self::Fill(fs) => {
if fs.style.is_none() {
fs.style = style
fs.style = style;
}
}
Self::Text(ts) => {
if ts.style.is_none() {
ts.style = style
ts.style = style;
}
}
Self::LineTerm => {}
+1 -1
View File
@@ -398,7 +398,7 @@ mod test {
let deserializer = ValueDeserializer::new(&value);
let result = StarshipRootConfig::deserialize(deserializer);
assert!(result.is_ok())
assert!(result.is_ok());
}
#[test]
+5 -4
View File
@@ -1,4 +1,5 @@
use crate::context::{Context, Shell, Target};
use crate::context::{Context, Properties, Shell, Target};
use crate::context_env::Env;
use crate::logger::StarshipLogger;
use crate::{
config::StarshipConfig,
@@ -37,12 +38,12 @@ fn init_logger() {
pub fn default_context() -> Context<'static> {
let mut context = Context::new_with_shell_and_path(
Default::default(),
Properties::default(),
Shell::Unknown,
Target::Main,
PathBuf::new(),
PathBuf::new(),
Default::default(),
Env::default(),
);
context.config = StarshipConfig { config: None };
context
@@ -168,7 +169,7 @@ impl<'a> ModuleRenderer<'a> {
/// Renders the module returning its output
pub fn collect(self) -> Option<String> {
let ret = crate::print::get_module(self.name, self.context);
let ret = crate::print::get_module(self.name, &self.context);
// all tests rely on the fact that an empty module produces None as output as the
// convention was that there would be no module but None. This is nowadays not anymore
// the case (to get durations for all modules). So here we make it so, that an empty
+22 -30
View File
@@ -43,7 +43,7 @@ pub fn read_file<P: AsRef<Path> + Debug>(file_name: P) -> Result<String> {
log::debug!("Error reading file: {result:?}");
} else {
log::trace!("File read successfully");
};
}
result
}
@@ -291,10 +291,12 @@ Elixir 1.10 (compiled with Erlang/OTP 22)\n",
stdout: String::from("topic-branch"),
stderr: String::default(),
}),
"fossil branch new topic-branch trunk" => Some(CommandOutput {
"fossil branch new topic-branch trunk" | "fossil update topic-branch" => {
Some(CommandOutput {
stdout: String::default(),
stderr: String::default(),
}),
})
}
"fossil diff -i --numstat" => Some(CommandOutput {
stdout: String::from(
"\
@@ -303,10 +305,6 @@ Elixir 1.10 (compiled with Erlang/OTP 22)\n",
),
stderr: String::default(),
}),
"fossil update topic-branch" => Some(CommandOutput {
stdout: String::default(),
stderr: String::default(),
}),
"gleam --version" => Some(CommandOutput {
stdout: String::from("gleam 1.0.0\n"),
stderr: String::default(),
@@ -774,19 +772,13 @@ impl PathExt for Path {
#[cfg(target_os = "linux")]
fn device_id(&self) -> Option<u64> {
use std::os::linux::fs::MetadataExt;
match self.metadata() {
Ok(m) => Some(m.st_dev()),
Err(_) => None,
}
Some(self.metadata().ok()?.st_dev())
}
#[cfg(all(unix, not(target_os = "linux")))]
fn device_id(&self) -> Option<u64> {
use std::os::unix::fs::MetadataExt;
match self.metadata() {
Ok(m) => Some(m.dev()),
Err(_) => None,
}
Some(self.metadata().ok()?.dev())
}
}
@@ -796,35 +788,35 @@ mod tests {
#[test]
fn render_time_test_0ms() {
assert_eq!(render_time(0_u128, true), "0ms")
assert_eq!(render_time(0_u128, true), "0ms");
}
#[test]
fn render_time_test_0s() {
assert_eq!(render_time(0_u128, false), "0s")
assert_eq!(render_time(0_u128, false), "0s");
}
#[test]
fn render_time_test_500ms() {
assert_eq!(render_time(500_u128, true), "500ms")
assert_eq!(render_time(500_u128, true), "500ms");
}
#[test]
fn render_time_test_500ms_no_millis() {
assert_eq!(render_time(500_u128, false), "0s")
assert_eq!(render_time(500_u128, false), "0s");
}
#[test]
fn render_time_test_10s() {
assert_eq!(render_time(10_000_u128, true), "10s0ms")
assert_eq!(render_time(10_000_u128, true), "10s0ms");
}
#[test]
fn render_time_test_90s() {
assert_eq!(render_time(90_000_u128, true), "1m30s0ms")
assert_eq!(render_time(90_000_u128, true), "1m30s0ms");
}
#[test]
fn render_time_test_10110s() {
assert_eq!(render_time(10_110_000_u128, true), "2h48m30s0ms")
assert_eq!(render_time(10_110_000_u128, true), "2h48m30s0ms");
}
#[test]
fn render_time_test_1d() {
assert_eq!(render_time(86_400_000_u128, false), "1d0h0m0s")
assert_eq!(render_time(86_400_000_u128, false), "1d0h0m0s");
}
#[test]
@@ -839,7 +831,7 @@ mod tests {
stderr: String::from("stderr ok!\n"),
});
assert_eq!(result, expected)
assert_eq!(result, expected);
}
// While the exec_cmd should work on Windows some of these tests assume a Unix-like
@@ -854,7 +846,7 @@ mod tests {
stderr: String::new(),
});
assert_eq!(result, expected)
assert_eq!(result, expected);
}
#[test]
@@ -867,7 +859,7 @@ mod tests {
stderr: String::new(),
});
assert_eq!(result, expected)
assert_eq!(result, expected);
}
#[test]
@@ -883,7 +875,7 @@ mod tests {
stderr: String::from("hello\n"),
});
assert_eq!(result, expected)
assert_eq!(result, expected);
}
#[test]
@@ -899,7 +891,7 @@ mod tests {
stderr: String::from("world\n"),
});
assert_eq!(result, expected)
assert_eq!(result, expected);
}
#[test]
@@ -908,7 +900,7 @@ mod tests {
let result = internal_exec_cmd("false", &[] as &[&OsStr], Duration::from_millis(500));
let expected = None;
assert_eq!(result, expected)
assert_eq!(result, expected);
}
#[test]
@@ -917,7 +909,7 @@ mod tests {
let result = internal_exec_cmd("sleep", &["500"], Duration::from_millis(500));
let expected = None;
assert_eq!(result, expected)
assert_eq!(result, expected);
}
#[test]