diff --git a/Cargo.lock b/Cargo.lock index 6102ba1..9579989 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,6 +235,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + [[package]] name = "lazy_static" version = "1.4.0" @@ -523,6 +529,43 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -541,6 +584,17 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "syn" +version = "2.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sysinfo" version = "0.30.13" @@ -639,6 +693,8 @@ dependencies = [ "rand", "regex", "rlimit", + "serde", + "serde_json", "tempfile", "textwrap", "uu_ctrlaltdel", @@ -663,6 +719,8 @@ version = "0.0.1" dependencies = [ "clap", "regex", + "serde", + "serde_json", "sysinfo", "uucore", ] diff --git a/Cargo.toml b/Cargo.toml index 95d2a31..c492e1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,8 @@ textwrap = { version = "0.16.0", features = ["terminal_size"] } xattr = "1.3.1" tempfile = "3.9.0" rand = { version = "0.8", features = ["small_rng"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" [dependencies] clap = { workspace = true } @@ -53,7 +55,8 @@ clap_mangen = { workspace = true } uucore = { workspace = true } phf = { workspace = true } textwrap = { workspace = true } - +serde = { workspace = true } +serde_json = { workspace = true } # lscpu = { optional = true, version = "0.0.1", package = "uu_lscpu", path = "src/uu/lscpu" } diff --git a/src/uu/lscpu/Cargo.toml b/src/uu/lscpu/Cargo.toml index c59e07e..dff4b76 100644 --- a/src/uu/lscpu/Cargo.toml +++ b/src/uu/lscpu/Cargo.toml @@ -15,3 +15,5 @@ regex = { workspace = true } sysinfo = { workspace = true } uucore = { workspace = true } clap = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } diff --git a/src/uu/lscpu/src/lscpu.rs b/src/uu/lscpu/src/lscpu.rs index 2925921..9c9d5ab 100644 --- a/src/uu/lscpu/src/lscpu.rs +++ b/src/uu/lscpu/src/lscpu.rs @@ -3,31 +3,66 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -use clap::{crate_version, Command}; +use clap::{crate_version, Arg, ArgAction, Command}; use regex::Regex; +use serde::Serialize; +use serde_json; use std::fs; use sysinfo::System; use uucore::{error::UResult, format_usage, help_about, help_usage}; +mod options { + pub const JSON: &str = "json"; +} + const ABOUT: &str = help_about!("lscpu.md"); const USAGE: &str = help_usage!("lscpu.md"); +#[derive(Serialize)] +struct Elt { + field: String, + data: String, +} + #[uucore::main] -pub fn uumain(_args: impl uucore::Args) -> UResult<()> { +pub fn uumain(args: impl uucore::Args) -> UResult<()> { + let matches = uu_app().try_get_matches_from(args)?; + + let json = matches.get_flag(options::JSON); + let system = System::new_all(); let _cpu = system.global_cpu_info(); - println!("Architecture: {}", get_architecture()); - println!("CPU(s): {}", system.cpus().len()); + let mut elts: Vec = Vec::new(); + elts.push(Elt { + field: String::from("Architecture"), + data: String::from(format!("{}", get_architecture())), + }); + elts.push(Elt { + field: String::from("CPU(s)"), + data: String::from(format!("{}", system.cpus().len())), + }); // Add more CPU information here... if let Ok(contents) = fs::read_to_string("/proc/cpuinfo") { let re = Regex::new(r"^model name\s+:\s+(.*)$").unwrap(); // Assuming all CPUs have the same model name if let Some(cap) = re.captures_iter(&contents).next() { - println!("Model name: {}", &cap[1]); + elts.push(Elt { + field: String::from("Model name"), + data: cap[1].to_string(), + }); }; } + + if json { + let json_string = serde_json::to_string(&elts).unwrap(); + println!("{}", json_string); + } else { + for elt in &elts { + println!("{}: {}", elt.field, elt.data); + } + } Ok(()) } @@ -47,4 +82,10 @@ pub fn uu_app() -> Command { .about(ABOUT) .override_usage(format_usage(USAGE)) .infer_long_args(true) + .arg( + Arg::new(options::JSON) + .long("json") + .help("Use JSON output format for the default summary or extended output (see --extended). For backward compatibility, JSON output follows the default summary behavior for non-terminals (e.g., pipes) where subsections are missing. See also --hierarchic.") + .action(ArgAction::SetTrue), + ) }