Fix bug in path truncation

Paths with 3 components would truncate to 2 despite the truncation length begin set to 3.
This commit is contained in:
Matan Kushner 2019-04-15 11:40:18 -04:00
parent 71cac5bd1f
commit bca4a7079f
No known key found for this signature in database
GPG key ID: 4B98C3A8949CA8A4
3 changed files with 93 additions and 38 deletions

View file

@ -91,11 +91,11 @@ fn truncate(dir_string: String, length: usize) -> String {
let components = dir_string let components = dir_string
.split(std::path::MAIN_SEPARATOR) .split(std::path::MAIN_SEPARATOR)
.collect::<Vec<&str>>(); .collect::<Vec<&str>>();
if components.len() < length { if components.len() <= length {
return dir_string; return dir_string;
} }
let truncated_components = &components[..length]; let truncated_components = &components[components.len() - length..];
truncated_components.join(&std::path::MAIN_SEPARATOR.to_string()) truncated_components.join(&std::path::MAIN_SEPARATOR.to_string())
} }
@ -103,45 +103,71 @@ fn truncate(dir_string: String, length: usize) -> String {
mod tests { mod tests {
// TODO: Look into stubbing `env` so that tests can be run in parallel // TODO: Look into stubbing `env` so that tests can be run in parallel
use super::*; use super::*;
use clap::{App, Arg};
use std::path::Path; // #[test]
// fn truncate_home_dir() {
// let args = App::new("starship")
// .arg(Arg::with_name("status_code"))
// .get_matches_from(vec!["starship", "0"]);
// let home_dir = dirs::home_dir().unwrap();
// env::set_current_dir(&home_dir).unwrap();
// let segment = segment(&args).unwrap();
// assert_eq!(segment.output(), "~");
// }
// #[test]
// fn dont_truncate_non_home_dir() {
// let args = App::new("starship")
// .arg(Arg::with_name("status_code"))
// .get_matches_from(vec!["starship", "0"]);
// let root_dir = Path::new("/");
// env::set_current_dir(&root_dir).unwrap();
// let segment = segment(&args).unwrap();
// assert_eq!(segment.output(), "/");
// }
// #[test]
// fn do_not_canonicalize_paths() {
// let args = App::new("starship")
// .arg(Arg::with_name("status_code"))
// .get_matches_from(vec!["starship", "0"]);
// let root_dir = Path::new("/var");
// env::set_current_dir(&root_dir).unwrap();
// let segment = segment(&args).unwrap();
// assert_eq!(segment.output(), "/var");
// }
#[test] #[test]
fn truncate_home_dir() { fn truncate_smaller_path_than_provided_length() {
let args = App::new("starship") let path = "~/starship";
.arg(Arg::with_name("status_code")) let output = truncate(path.to_string(), 3);
.get_matches_from(vec!["starship", "0"]); assert_eq!(output, "~/starship")
let home_dir = dirs::home_dir().unwrap();
env::set_current_dir(&home_dir).unwrap();
let segment = segment(&args);
// assert_eq!(segment.value, "~");
} }
#[test] #[test]
fn dont_truncate_non_home_dir() { fn truncate_same_path_as_provided_length() {
let args = App::new("starship") let path = "~/starship/engines";
.arg(Arg::with_name("status_code")) let output = truncate(path.to_string(), 3);
.get_matches_from(vec!["starship", "0"]); assert_eq!(output, "~/starship/engines")
let root_dir = Path::new("/");
env::set_current_dir(&root_dir).unwrap();
let segment = segment(&args);
// assert_eq!(segment.value, "/");
} }
#[test] #[test]
fn do_not_canonicalize_paths() { fn truncate_slightly_larger_path_then_provided_length() {
let args = App::new("starship") let path = "~/starship/engines/booster";
.arg(Arg::with_name("status_code")) let output = truncate(path.to_string(), 3);
.get_matches_from(vec!["starship", "0"]); assert_eq!(output, "starship/engines/booster")
}
let root_dir = Path::new("/var"); #[test]
env::set_current_dir(&root_dir).unwrap(); fn truncate_larger_path_than_provided_length() {
let path = "~/starship/engines/booster/rocket";
let segment = segment(&args); let output = truncate(path.to_string(), 3);
// assert_eq!(segment.value, "/var"); assert_eq!(output, "engines/booster/rocket")
} }
} }

View file

@ -21,6 +21,6 @@ pub fn prompt(args: ArgMatches) {
.map(|module| modules::handle(module, &args)) // Compute segments .map(|module| modules::handle(module, &args)) // Compute segments
.flatten() // Remove segments set to `None` .flatten() // Remove segments set to `None`
.enumerate() // Turn segment into tuple with index .enumerate() // Turn segment into tuple with index
.map(|(index, segment)| segment.output(index)) // Generate string outputs .map(|(index, segment)| segment.output_index(index)) // Generate string outputs
.for_each(|segment_string| write!(handle, "{}", segment_string).unwrap()); .for_each(|segment_string| write!(handle, "{}", segment_string).unwrap());
} }

View file

@ -76,8 +76,37 @@ impl Segment {
/// Create a string with the formatted contents of a segment /// Create a string with the formatted contents of a segment
/// ///
/// Will recursively also format the prefix and suffix of the segment being /// Will recursively also format the prefix and suffix of the segment being
/// stringified. Skips the prefix of the first segment. /// stringified.
pub fn output(&self, index: usize) -> String { pub fn output(&self) -> String {
let Segment {
name: _name,
prefix,
value,
style,
suffix,
} = self;
let mut segment_string = String::new();
// Skip the prefix for the first segment
if let Some(prefix) = prefix {
segment_string += &prefix.output()
}
segment_string += &style.paint(value).to_string();
if let Some(suffix) = suffix {
segment_string += &suffix.output();
}
segment_string
}
/// Create a string with the formatted contents of a segment while skipping the first segment.
///
/// Will recursively also format the prefix and suffix of the segment being
/// stringified.
pub fn output_index(&self, index: usize) -> String {
let Segment { let Segment {
name: _name, name: _name,
prefix, prefix,
@ -91,14 +120,14 @@ impl Segment {
// Skip the prefix for the first segment // Skip the prefix for the first segment
if index != 0 { if index != 0 {
if let Some(prefix) = prefix { if let Some(prefix) = prefix {
segment_string += &prefix.output(index) segment_string += &prefix.output_index(index)
} }
} }
segment_string += &style.paint(value).to_string(); segment_string += &style.paint(value).to_string();
if let Some(suffix) = suffix { if let Some(suffix) = suffix {
segment_string += &suffix.output(index); segment_string += &suffix.output();
} }
segment_string segment_string