diff --git a/Cargo.lock b/Cargo.lock index 0257ed6f..f27c70f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -689,7 +689,9 @@ dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -758,6 +760,14 @@ dependencies = [ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toml" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -930,6 +940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7655088894274afb52b807bd3c87072daa1fedd155068b8705cabfd628956115" +"checksum toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c5890a989fa47ecdc7bcb4c63a77a82c18f306714104b1decfd722db17b39e" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" diff --git a/Cargo.toml b/Cargo.toml index adde6e24..ece4734e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ clap = "2.33.0" ansi_term = "0.11.0" dirs = "1.0.5" git2 = "0.8.0" +toml = "0.5.0" +serde_json = "1.0.39" [dev-dependencies] tempfile = "3.0.7" diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 4ed912ad..5c55f6aa 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -3,6 +3,7 @@ mod directory; mod git_branch; mod line_break; mod nodejs; +mod package; mod python; mod rust; @@ -17,6 +18,7 @@ pub fn handle(module: &str, context: &Context) -> Option { "rust" | "rustlang" => rust::segment(context), "python" => python::segment(context), "line_break" => line_break::segment(context), + "package" => package::segment(context), "git_branch" => git_branch::segment(context), _ => panic!("Unknown module: {}", module), diff --git a/src/modules/package.rs b/src/modules/package.rs new file mode 100644 index 00000000..ab201e4b --- /dev/null +++ b/src/modules/package.rs @@ -0,0 +1,108 @@ +use super::Segment; +use crate::context::Context; +use ansi_term::Color; +use serde_json; +use std::fs::File; +use std::io; +use std::io::Read; +use std::path::PathBuf; +use toml; + +/// Creates a segment with the current package version +/// +/// Will display if a version is defined for your Node.js or Rust project (if one exists) +pub fn segment(context: &Context) -> Option { + match get_package_version(context) { + Some(package_version) => { + const PACKAGE_CHAR: &str = "📦"; + const SEGMENT_COLOR: Color = Color::Red; + + // TODO: Make the prefix for the module "is " + let mut segment = Segment::new("package"); + segment.set_style(SEGMENT_COLOR.bold()); + + segment.set_value(format!("{} {}", PACKAGE_CHAR, package_version)); + + Some(segment) + } + None => None, + } +} + +// TODO: Combine into one function and just call for different file names! +fn is_cargo_toml(dir_entry: &PathBuf) -> bool { + dir_entry.is_file() && dir_entry.file_name().unwrap_or_default() == "Cargo.toml" +} + +fn is_package_json(dir_entry: &PathBuf) -> bool { + dir_entry.is_file() && dir_entry.file_name().unwrap_or_default() == "package.json" +} + +// TODO: Move to `utils.rs` file and import +fn read_file(file_name: &str) -> io::Result { + let mut file = File::open(file_name)?; + let mut data = String::new(); + + file.read_to_string(&mut data)?; + + Ok(data) +} + +fn extract_cargo_version(file_contents: String) -> Option { + let cargo_toml = file_contents.parse::().ok()?; + + match cargo_toml["package"]["version"].as_str() { + Some(raw_version) => { + let version = format_version(raw_version.to_string()); + Some(version) + } + None => None, + } +} + +fn extract_package_version(file_contents: String) -> Option { + let json: Option = serde_json::from_str(&file_contents).ok()?; + + match json { + Some(json) => { + let raw_version = json["version"].to_string(); + if raw_version == "null" { + None + } else { + Some(format_version(raw_version)) + } + } + None => None, + } +} + +fn get_package_version(context: &Context) -> Option { + let has_cargo_toml = context.dir_files.iter().any(is_cargo_toml); + if has_cargo_toml { + let file_contents = read_file("Cargo.toml").ok()?; + return extract_cargo_version(file_contents); + } + + let has_package_json = context.dir_files.iter().any(is_package_json); + if has_package_json { + let file_contents = read_file("package.json").ok()?; + return extract_package_version(file_contents); + } + + None +} + +fn format_version(version: String) -> String { + format!("v{}", version.replace('"', "").trim()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_format_version() { + let input = String::from("0.1.0"); + assert_eq!(format_version(input), "v0.1.0"); + } +} diff --git a/src/print.rs b/src/print.rs index b175252e..e2f0a066 100644 --- a/src/print.rs +++ b/src/print.rs @@ -8,6 +8,7 @@ pub fn prompt(args: ArgMatches) { let prompt_order = vec![ "directory", "git_branch", + "package", "nodejs", "rust", "python",