1#[cfg(feature = "cmd")]
2use anstyle::{
3 AnsiColor::{BrightBlue, BrightCyan, BrightGreen, Green, Red},
4 Color::Ansi,
5 Style,
6};
7#[cfg(feature = "cmd")]
8use chardet::detect;
9#[cfg(feature = "cmd")]
10use encoding_rs::{Encoding, GBK, UTF_8, WINDOWS_1252};
11#[cfg(feature = "cmd")]
12use serde::{Deserialize, Serialize};
13
14#[cfg(feature = "cmd")]
15fn detect_encoding(buf: &[u8]) -> &'static Encoding {
16 let result = detect(buf);
17 let encoding_name = result.0.to_lowercase();
18 let encoding_label = encoding_name.as_bytes();
19
20 if let Some((bom_encoding, _)) = Encoding::for_bom(buf) {
22 return bom_encoding;
23 }
24
25 if let Some(encoding) = Encoding::for_label(encoding_label) {
27 return encoding;
28 }
29
30 let (_, _, utf8_had_errors) = UTF_8.decode(buf);
32 if !utf8_had_errors {
33 return UTF_8;
34 }
35
36 let (_, _, gbk_had_errors) = GBK.decode(buf);
37 if !gbk_had_errors {
38 return GBK;
39 }
40
41 WINDOWS_1252
42}
43#[cfg(feature = "cmd")]
54pub fn clap_help_styles() -> clap::builder::Styles {
55 clap::builder::Styles::styled()
56 .usage(Style::new().fg_color(Some(Ansi(BrightBlue))))
57 .header(Style::new().fg_color(Some(Ansi(BrightBlue))))
58 .literal(Style::new().fg_color(Some(Ansi(BrightGreen))))
59 .invalid(Style::new().bold().fg_color(Some(Ansi(Red))))
60 .error(Style::new().bold().fg_color(Some(Ansi(Red))))
61 .valid(Style::new().fg_color(Some(Ansi(Green))))
62 .placeholder(Style::new().fg_color(Some(Ansi(BrightCyan))))
63}
64
65#[cfg(feature = "cmd")]
66#[derive(Debug, Deserialize, Serialize)]
67pub struct CmdResult {
68 pub code: i32,
69 pub stdout: String,
70 pub stderr: String,
71}
72#[cfg(feature = "cmd")]
74pub fn exec(cmd: &str, args: &Vec<&str>) -> Result<CmdResult, std::io::Error> {
75 use std::process::Command;
76 let mut cmd = Command::new(cmd);
77 if !args.is_empty() {
78 cmd.args(args);
79 }
80 let ret = cmd.output();
81 let Ok(ret) = ret else {
82 return Err(ret.unwrap_err());
83 };
84
85 let code = ret.status.code().unwrap_or(-1);
86 let coding = detect_encoding(&ret.stdout);
87 println!("{}", coding.name());
88 let stdout = coding.decode(&ret.stdout).0.to_string();
89 let coding = detect_encoding(&ret.stderr);
90 let stderr = coding.decode(&ret.stderr).0.to_string();
91 println!("{}", coding.name());
92
93 Ok(CmdResult {
94 code,
95 stdout,
96 stderr,
97 })
98}
99
100#[test]
101#[cfg(feature = "cmd")]
102fn test_exec() {
103 let ret = exec("cmd", &vec!["dir"]).unwrap();
104 println!("{:?}", ret);
105}