diff --git a/Cargo.lock b/Cargo.lock index 6eaaf85..6c5e76b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,6 +31,7 @@ version = "0.1.0" dependencies = [ "clap", "crossterm", + "enumset", "git2", "machine-uid", "semver", @@ -117,6 +118,67 @@ dependencies = [ "winapi", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "enumset" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4799cdb24d48f1f8a7a98d06b7fde65a85a2d1e42b25a889f5406aa1fbefe074" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea83a3fbdc1d999ccfbcbee717eab36f8edf2d71693a23ce0d7cca19e085304c" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -163,6 +225,12 @@ dependencies = [ "libc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.3" diff --git a/Cargo.toml b/Cargo.toml index 5db64fa..71abb57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ repository = "https://codeberg.org/almindor/cargo-vcs" [dependencies] clap = { version = "3.2", features = ["derive"] } crossterm = "0.24" +enumset = "1.0" git2 = "0.14" machine-uid = "0.2" semver = "1.0" diff --git a/src/vcs.rs b/src/vcs.rs index fede651..5a1028a 100644 --- a/src/vcs.rs +++ b/src/vcs.rs @@ -103,6 +103,20 @@ impl Vcs { format!("{}", self.work_dir.display()).italic(), self.min_msrv_str(), ); + + let mut once = true; + for project in &self.projects { + if once { + println!("\n{}\n", "** Projects with uncommitted changes **".italic()); + once = false; + } + if !project.repo.uncommitted_changes()?.is_empty() { + println!( + "{}", + project.display(ProjectDisplayOptions::Changes.into())? + ); + } + } } else { if self.profiles.is_empty() { println!( diff --git a/src/vcs/cli.rs b/src/vcs/cli.rs index 60ace4e..8a6c21b 100644 --- a/src/vcs/cli.rs +++ b/src/vcs/cli.rs @@ -17,6 +17,7 @@ pub struct Cli { pub enum Commands { /// Show workspace status Status { + /// Show verbose status information #[clap(short = 'v')] verbose: bool, }, diff --git a/src/vcs/project.rs b/src/vcs/project.rs index a21c4b2..e0b990d 100644 --- a/src/vcs/project.rs +++ b/src/vcs/project.rs @@ -5,6 +5,7 @@ use std::{ }; use crossterm::style::Stylize; +use enumset::{EnumSet, EnumSetType}; use semver::Version; use termtree::Tree; @@ -20,6 +21,19 @@ pub struct Project { profile_map: HashMap, // vcs profile name to branch names } +#[derive(EnumSetType, Debug)] +pub enum ProjectDisplayOptions { + Profiles, + Msrv, + Changes, +} + +impl ProjectDisplayOptions { + pub fn all() -> EnumSet { + Self::Profiles | Self::Msrv | Self::Changes + } +} + pub type Projects<'origin> = std::slice::Iter<'origin, Project>; impl Project { @@ -109,7 +123,7 @@ impl Project { Ok(None) } - pub fn display(&self, profiles: bool, changes: bool) -> Result, Error> { + pub fn display(&self, options: EnumSet) -> Result, Error> { let title = format!( "{}: {} [{}]", self.name().bold().with(PROJECT_COLOR), @@ -118,8 +132,9 @@ impl Project { ); let mut root = Tree::new(title); - if profiles { + if options & ProjectDisplayOptions::Profiles == ProjectDisplayOptions::Profiles { let mut profiles_tree = Tree::new("[PROFILES]".with(PROFILE_COLOR).to_string()); + let mut count = 0; for (profile_name, branch_name) in &self.profile_map { let leaf = Tree::new(format!( "{} -> {}", @@ -127,20 +142,25 @@ impl Project { branch_name.as_str().with(REFS_COLOR) )); profiles_tree.push(leaf); + count += 1; } - root.push(profiles_tree); + if count > 0 { + root.push(profiles_tree); + } } - if let Some(msrv) = &self.msrv { - let leaf = Tree::new(msrv.to_string().with(MSRV_COLOR).to_string()); - let mut msrv_tree = Tree::new("[MSRV]".with(MSRV_COLOR).to_string()); - msrv_tree.push(leaf); + if options & ProjectDisplayOptions::Msrv == ProjectDisplayOptions::Msrv { + if let Some(msrv) = &self.msrv { + let leaf = Tree::new(msrv.to_string().with(MSRV_COLOR).to_string()); + let mut msrv_tree = Tree::new("[MSRV]".with(MSRV_COLOR).to_string()); + msrv_tree.push(leaf); - root.push(msrv_tree); + root.push(msrv_tree); + } } - if changes { + if options & ProjectDisplayOptions::Changes == ProjectDisplayOptions::Changes { let statuses = self.repo.uncommitted_changes()?; let uncommitted = statuses .iter() @@ -166,7 +186,8 @@ impl Display for Project { write!( f, "{}", - self.display(true, true).map_err(|_| std::fmt::Error)? + self.display(ProjectDisplayOptions::all()) + .map_err(|_| std::fmt::Error)? ) } }