diff --git a/Cargo.toml b/Cargo.toml index 486dac7..09e2df7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scidataflow" -version = "0.8.11" +version = "0.8.2" edition = "2021" exclude = ["logo.png", "tests/test_data/**"] license = "MIT" diff --git a/src/lib/data.rs b/src/lib/data.rs index 41a0767..27da4a6 100644 --- a/src/lib/data.rs +++ b/src/lib/data.rs @@ -43,6 +43,9 @@ pub struct StatusEntry { } impl StatusEntry { + pub fn is_changed(&self) -> bool { + self.local_status != Some(LocalStatusCode::Current) + } fn local_md5_column(&self, abbrev: Option) -> Result { Ok(md5_status( self.local_md5.as_ref(), diff --git a/src/lib/project.rs b/src/lib/project.rs index 3402f94..8969369 100644 --- a/src/lib/project.rs +++ b/src/lib/project.rs @@ -309,13 +309,13 @@ impl Project { self.save() } - pub async fn status(&mut self, include_remotes: bool, all: bool) -> Result<()> { + pub async fn status(&mut self, include_remotes: bool, all: bool, concicse: bool) -> Result<()> { // if include_remotes (e.g. --remotes) is set, we need to merge // in the remotes, so we authenticate first and then get them. let path_context = &canonicalize(self.path_context())?; let status_rows = self.data.status(path_context, include_remotes).await?; //let remotes: Option<_> = include_remotes.then(|| &self.data.remotes); - print_status(status_rows, Some(&self.data.remotes), all); + print_status(status_rows, Some(&self.data.remotes), all, concicse); Ok(()) } diff --git a/src/lib/utils.rs b/src/lib/utils.rs index ebf9384..595b1c3 100644 --- a/src/lib/utils.rs +++ b/src/lib/utils.rs @@ -130,6 +130,7 @@ println!(); } } */ + // More specialized version of print_fixed_width() for statuses. // Handles coloring, manual annotation, etc pub fn print_fixed_width_status( @@ -138,36 +139,47 @@ pub fn print_fixed_width_status( indent: Option, color: bool, all: bool, + concise: bool, ) { - //debug!("rows: {:?}", rows); let indent = indent.unwrap_or(0); let nspaces = nspaces.unwrap_or(6); - let abbrev = Some(8); - // get the max number of columns (in case ragged) - let max_cols = rows + // Filter rows if concise is true + let filtered_rows: BTreeMap> = if concise { + rows.into_iter() + .map(|(key, statuses)| { + let filtered_statuses: Vec = statuses + .into_iter() + .filter(|status| status.is_changed()) + .collect(); + (key, filtered_statuses) + }) + .filter(|(_, statuses)| !statuses.is_empty()) + .collect() + } else { + rows + }; + + let max_cols = filtered_rows .values() .flat_map(|v| v.iter()) .map(|entry| entry.columns(abbrev).len()) .max() .unwrap_or(0); - let mut max_lengths = vec![0; max_cols]; - // compute max lengths across all rows - for status in rows.values().flat_map(|v| v.iter()) { + for status in filtered_rows.values().flat_map(|v| v.iter()) { let cols = status.columns(abbrev); for (i, col) in cols.iter().enumerate() { - max_lengths[i] = max_lengths[i].max(col.len()); // Assuming col is a string + max_lengths[i] = max_lengths[i].max(col.len()); } } - // print status table - let mut dir_keys: Vec<&String> = rows.keys().collect(); + let mut dir_keys: Vec<&String> = filtered_rows.keys().collect(); dir_keys.sort(); for key in dir_keys { - let statuses = &rows[key]; + let statuses = &filtered_rows[key]; let pretty_key = if key.is_empty() { "." } else { key }; let prettier_key = if color { pretty_key.bold().to_string() @@ -176,16 +188,13 @@ pub fn print_fixed_width_status( }; println!("[{}]", prettier_key); - // Print the rows with the correct widths for status in statuses { if status.local_status.is_none() && !all { - // ignore things that aren't in the manifest, unless --all continue; } let cols = status.columns(abbrev); let mut fixed_row = Vec::new(); for (i, col) in cols.iter().enumerate() { - // push a fixed-width column to vector let spacer = if i == 0 { " " } else { "" }; let fixed_col = format!("{}{:width$}", spacer, col, width = max_lengths[i]); fixed_row.push(fixed_col); @@ -295,6 +304,7 @@ pub fn print_status( rows: BTreeMap>, remote: Option<&HashMap>, all: bool, + concise: bool, ) { println!("{}", "Project data status:".bold()); let counts = get_counts(&rows).expect("Internal Error: get_counts() panicked."); @@ -325,7 +335,7 @@ pub fn print_status( None => rows, }; - print_fixed_width_status(rows_by_dir, None, None, true, all); + print_fixed_width_status(rows_by_dir, None, None, true, all, concise); } pub fn format_bytes(size: u64) -> String { diff --git a/src/main.rs b/src/main.rs index 56c4ef2..847b025 100644 --- a/src/main.rs +++ b/src/main.rs @@ -130,6 +130,10 @@ enum Commands { /// Show statuses of all files, including those on remote(s) but not in the manifest. #[arg(long)] all: bool, + + /// Only show locally changed files. + #[arg(short, long)] + concise: bool, }, /// Show file size statistics. Stats {}, @@ -289,9 +293,13 @@ async fn run() -> Result<()> { proj.bulk(filename, *column, *header, *overwrite).await } Some(Commands::Init { name }) => Project::init(name.clone()), - Some(Commands::Status { remotes, all }) => { + Some(Commands::Status { + remotes, + all, + concise, + }) => { let mut proj = Project::new()?; - proj.status(*remotes, *all).await + proj.status(*remotes, *all, *concise).await } Some(Commands::Stats {}) => { //let proj = Project::new()?;