refactor(directory): avoid unnecessary string copies (#5313)

This commit is contained in:
cgzones 2023-07-30 14:32:20 +02:00 committed by GitHub
parent 41867711d1
commit 4fa4230dda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 26 additions and 44 deletions

View File

@ -35,7 +35,6 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("directory"); let mut module = context.new_module("directory");
let config: DirectoryConfig = DirectoryConfig::try_load(module.config); let config: DirectoryConfig = DirectoryConfig::try_load(module.config);
let home_symbol = String::from(config.home_symbol);
let home_dir = context let home_dir = context
.get_home() .get_home()
.expect("Unable to determine HOME_DIR for user"); .expect("Unable to determine HOME_DIR for user");
@ -69,7 +68,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// the home directory if required. // the home directory if required.
let dir_string = dir_string let dir_string = dir_string
.unwrap_or_else(|| contract_path(display_dir, &home_dir, &home_symbol).to_string()); .unwrap_or_else(|| contract_path(display_dir, &home_dir, config.home_symbol).to_string());
#[cfg(windows)] #[cfg(windows)]
let dir_string = remove_extended_path_prefix(dir_string); let dir_string = remove_extended_path_prefix(dir_string);
@ -91,10 +90,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// fish-style path contraction together // fish-style path contraction together
if config.fish_style_pwd_dir_length > 0 && config.substitutions.is_empty() { if config.fish_style_pwd_dir_length > 0 && config.substitutions.is_empty() {
// If user is using fish style path, we need to add the segment first // If user is using fish style path, we need to add the segment first
let contracted_home_dir = contract_path(display_dir, &home_dir, &home_symbol); let contracted_home_dir = contract_path(display_dir, &home_dir, config.home_symbol);
to_fish_style( to_fish_style(
config.fish_style_pwd_dir_length as usize, config.fish_style_pwd_dir_length as usize,
contracted_home_dir.to_string(), &contracted_home_dir,
&dir_string, &dir_string,
) )
} else { } else {
@ -116,7 +115,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
{ {
let root = repo_path_vec[0]; let root = repo_path_vec[0];
let before = before_root_dir(&dir_string, &contracted_path); let before = before_root_dir(&dir_string, &contracted_path);
[prefix + before.as_str(), root.to_string(), after_repo_root] [prefix + before, root.to_string(), after_repo_root]
} else { } else {
[String::new(), String::new(), prefix + dir_string.as_str()] [String::new(), String::new(), prefix + dir_string.as_str()]
} }
@ -130,7 +129,6 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
path_vec path_vec
}; };
let lock_symbol = String::from(config.read_only);
let display_format = if path_vec[0].is_empty() && path_vec[1].is_empty() { let display_format = if path_vec[0].is_empty() && path_vec[1].is_empty() {
config.format config.format
} else { } else {
@ -149,12 +147,12 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
_ => None, _ => None,
}) })
.map(|variable| match variable { .map(|variable| match variable {
"path" => Some(Ok(&path_vec[2])), "path" => Some(Ok(path_vec[2].as_str())),
"before_root_path" => Some(Ok(&path_vec[0])), "before_root_path" => Some(Ok(path_vec[0].as_str())),
"repo_root" => Some(Ok(&path_vec[1])), "repo_root" => Some(Ok(path_vec[1].as_str())),
"read_only" => { "read_only" => {
if is_readonly_dir(physical_dir) { if is_readonly_dir(physical_dir) {
Some(Ok(&lock_symbol)) Some(Ok(config.read_only))
} else { } else {
None None
} }
@ -317,12 +315,12 @@ fn substitute_path(dir_string: String, substitutions: &IndexMap<String, &str>) -
/// Absolute Path: `/some/Path/not/in_a/repo/but_nested` /// Absolute Path: `/some/Path/not/in_a/repo/but_nested`
/// Contracted Path: `in_a/repo/but_nested` /// Contracted Path: `in_a/repo/but_nested`
/// With Fish Style: `/s/P/n/in_a/repo/but_nested` /// With Fish Style: `/s/P/n/in_a/repo/but_nested`
fn to_fish_style(pwd_dir_length: usize, dir_string: String, truncated_dir_string: &str) -> String { fn to_fish_style(pwd_dir_length: usize, dir_string: &str, truncated_dir_string: &str) -> String {
let replaced_dir_string = dir_string.trim_end_matches(truncated_dir_string).to_owned(); let replaced_dir_string = dir_string.trim_end_matches(truncated_dir_string);
let components = replaced_dir_string.split('/').collect::<Vec<&str>>(); let components = replaced_dir_string.split('/').collect::<Vec<&str>>();
if components.is_empty() { if components.is_empty() {
return replaced_dir_string; return replaced_dir_string.to_string();
} }
components components
@ -346,10 +344,10 @@ fn convert_path_sep(path: &str) -> String {
} }
/// Get the path before the git repo root by trim the most right repo name. /// Get the path before the git repo root by trim the most right repo name.
fn before_root_dir(path: &str, repo: &str) -> String { fn before_root_dir<'a>(path: &'a str, repo: &'a str) -> &'a str {
match path.rsplit_once(repo) { match path.rsplit_once(repo) {
Some((a, _)) => a.to_string(), Some((a, _)) => a,
None => path.to_string(), None => path,
} }
} }
@ -460,14 +458,14 @@ mod tests {
#[test] #[test]
fn fish_style_with_user_home_contracted_path() { fn fish_style_with_user_home_contracted_path() {
let path = "~/starship/engines/booster/rocket"; let path = "~/starship/engines/booster/rocket";
let output = to_fish_style(1, path.to_string(), "engines/booster/rocket"); let output = to_fish_style(1, path, "engines/booster/rocket");
assert_eq!(output, "~/s/"); assert_eq!(output, "~/s/");
} }
#[test] #[test]
fn fish_style_with_user_home_contracted_path_and_dot_dir() { fn fish_style_with_user_home_contracted_path_and_dot_dir() {
let path = "~/.starship/engines/booster/rocket"; let path = "~/.starship/engines/booster/rocket";
let output = to_fish_style(1, path.to_string(), "engines/booster/rocket"); let output = to_fish_style(1, path, "engines/booster/rocket");
assert_eq!(output, "~/.s/"); assert_eq!(output, "~/.s/");
} }
@ -475,7 +473,7 @@ mod tests {
fn fish_style_with_no_contracted_path() { fn fish_style_with_no_contracted_path() {
// `truncation_length = 2` // `truncation_length = 2`
let path = "/absolute/Path/not/in_a/repo/but_nested"; let path = "/absolute/Path/not/in_a/repo/but_nested";
let output = to_fish_style(1, path.to_string(), "repo/but_nested"); let output = to_fish_style(1, path, "repo/but_nested");
assert_eq!(output, "/a/P/n/i/"); assert_eq!(output, "/a/P/n/i/");
} }
@ -483,21 +481,21 @@ mod tests {
fn fish_style_with_pwd_dir_len_no_contracted_path() { fn fish_style_with_pwd_dir_len_no_contracted_path() {
// `truncation_length = 2` // `truncation_length = 2`
let path = "/absolute/Path/not/in_a/repo/but_nested"; let path = "/absolute/Path/not/in_a/repo/but_nested";
let output = to_fish_style(2, path.to_string(), "repo/but_nested"); let output = to_fish_style(2, path, "repo/but_nested");
assert_eq!(output, "/ab/Pa/no/in/"); assert_eq!(output, "/ab/Pa/no/in/");
} }
#[test] #[test]
fn fish_style_with_duplicate_directories() { fn fish_style_with_duplicate_directories() {
let path = "~/starship/tmp/C++/C++/C++"; let path = "~/starship/tmp/C++/C++/C++";
let output = to_fish_style(1, path.to_string(), "C++"); let output = to_fish_style(1, path, "C++");
assert_eq!(output, "~/s/t/C/C/"); assert_eq!(output, "~/s/t/C/C/");
} }
#[test] #[test]
fn fish_style_with_unicode() { fn fish_style_with_unicode() {
let path = "~/starship/tmp/目录/a̐éö̲/目录"; let path = "~/starship/tmp/目录/a̐éö̲/目录";
let output = to_fish_style(1, path.to_string(), "目录"); let output = to_fish_style(1, path, "目录");
assert_eq!(output, "~/s/t/目/a̐/"); assert_eq!(output, "~/s/t/目/a̐/");
} }
@ -840,7 +838,7 @@ mod tests {
"{} ", "{} ",
Color::Cyan.bold().paint(convert_path_sep(&to_fish_style( Color::Cyan.bold().paint(convert_path_sep(&to_fish_style(
100, 100,
dir.to_slash_lossy().to_string(), &dir.to_slash_lossy(),
"" ""
))) )))
)); ));
@ -891,7 +889,7 @@ mod tests {
"{} ", "{} ",
Color::Cyan.bold().paint(convert_path_sep(&format!( Color::Cyan.bold().paint(convert_path_sep(&format!(
"{}/thrusters/rocket", "{}/thrusters/rocket",
to_fish_style(1, dir.to_slash_lossy().to_string(), "/thrusters/rocket") to_fish_style(1, &dir.to_slash_lossy(), "/thrusters/rocket")
))) )))
)); ));
@ -1013,7 +1011,7 @@ mod tests {
"{} ", "{} ",
Color::Cyan.bold().paint(convert_path_sep(&format!( Color::Cyan.bold().paint(convert_path_sep(&format!(
"{}/above-repo/rocket-controls/src/meters/fuel-gauge", "{}/above-repo/rocket-controls/src/meters/fuel-gauge",
to_fish_style(1, tmp_dir.path().to_slash_lossy().to_string(), "") to_fish_style(1, &tmp_dir.path().to_slash_lossy(), "")
))) )))
)); ));
@ -1044,15 +1042,7 @@ mod tests {
"{} ", "{} ",
Color::Cyan.bold().paint(convert_path_sep(&format!( Color::Cyan.bold().paint(convert_path_sep(&format!(
"{}/rocket-controls/src/meters/fuel-gauge", "{}/rocket-controls/src/meters/fuel-gauge",
to_fish_style( to_fish_style(1, &tmp_dir.path().join("above-repo").to_slash_lossy(), "")
1,
tmp_dir
.path()
.join("above-repo")
.to_slash_lossy()
.to_string(),
""
)
))) )))
)); ));
@ -1227,7 +1217,7 @@ mod tests {
"{} ", "{} ",
Color::Cyan.bold().paint(convert_path_sep(&format!( Color::Cyan.bold().paint(convert_path_sep(&format!(
"{}/above-repo/rocket-controls-symlink/src/meters/fuel-gauge", "{}/above-repo/rocket-controls-symlink/src/meters/fuel-gauge",
to_fish_style(1, tmp_dir.path().to_slash_lossy().to_string(), "") to_fish_style(1, &tmp_dir.path().to_slash_lossy(), "")
))) )))
)); ));
@ -1264,15 +1254,7 @@ mod tests {
"{} ", "{} ",
Color::Cyan.bold().paint(convert_path_sep(&format!( Color::Cyan.bold().paint(convert_path_sep(&format!(
"{}/rocket-controls-symlink/src/meters/fuel-gauge", "{}/rocket-controls-symlink/src/meters/fuel-gauge",
to_fish_style( to_fish_style(1, &tmp_dir.path().join("above-repo").to_slash_lossy(), "")
1,
tmp_dir
.path()
.join("above-repo")
.to_slash_lossy()
.to_string(),
""
)
))) )))
)); ));