Skip to content

Commit d5dcfe4

Browse files
committed
review
review
1 parent a2b395d commit d5dcfe4

File tree

4 files changed

+136
-102
lines changed

4 files changed

+136
-102
lines changed

β€Ž.vscode/settings.jsonβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"cSpell.words": ["popen"]
2+
"cSpell.words": ["maplit", "popen"]
33
}

β€ŽCargo.lockβ€Ž

Lines changed: 54 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

β€ŽCargo.tomlβ€Ž

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
[package]
22
name = "n"
3-
version = "0.0.2"
3+
version = "0.0.3"
44
edition = "2021"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
clap = {version="4.3.17",features = ["derive"]}
9+
clap = {version="4.3.17",features = ["derive","cargo"]}
10+
maplit = "1.0.2"
11+
regex = "1.9.1"
1012
serde_json = "1.0.103"
1113
subprocess = "0.2.9"

β€Žsrc/main.rsβ€Ž

Lines changed: 77 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,106 @@
1-
use clap::{Arg, ArgAction, Command};
1+
use clap::{arg, command, ArgAction};
2+
3+
use regex::Regex;
24
use serde_json::Value;
35
use std::fs;
4-
use std::io::{BufRead, BufReader};
56
use std::path::Path;
67
use subprocess::Exec;
7-
// ni
8-
// nr
9-
// nlx
10-
// nu
11-
// nun
12-
// nci
138

149
fn main() {
10+
let m: clap::ArgMatches = command!("n")
11+
.subcommands([
12+
command!("add")
13+
.about("Add new packages to dependencies")
14+
.args([
15+
arg!(<package> "Package name"),
16+
arg!(-'S' --"save" "Save installed packages to a package.json file as dependencies.")
17+
.required(false),
18+
arg!(-'D' --"save-dev" "Package will appear in your devDependencies.")
19+
.required(false),
20+
arg!(-'O' --"save-optional" "Install the specified packages as optionalDependencies.")
21+
.required(false)
22+
.action(ArgAction::SetTrue),
23+
arg!(-'g' --"global" "Install a package globally.")
24+
.required(false)
25+
.action(ArgAction::SetTrue)
26+
]),
27+
command!("install")
28+
.about("Used to install all dependencies for a project.")
29+
.alias("i"),
30+
command!("clean-install")
31+
.about("Like npm ci")
32+
.alias("ci"),
33+
])
34+
.get_matches();
35+
1536
let pkg_manager = read_package_manager().unwrap();
1637

1738
if let [p, v] = &pkg_manager[..2] {
18-
println!("πŸ‘ Package manage tool is {} , the version is {}", p, v);
19-
let matches = Command::new("n")
20-
.subcommand(
21-
Command::new("i").about("Install operations").arg(
22-
Arg::new("package")
23-
.required(false)
24-
.action(ArgAction::Append),
25-
),
26-
)
27-
.subcommand(Command::new("ci"))
28-
.subcommand(
29-
Command::new("r")
30-
.about("Running script")
31-
.arg(Arg::new("script").required(true)),
32-
)
33-
.subcommand(
34-
Command::new("x")
35-
.about("Operation X")
36-
.arg(Arg::new("package").required(true).action(ArgAction::Append)),
37-
)
38-
.get_matches();
39-
40-
// Then you can check which subcommand was used
41-
match matches.subcommand() {
42-
Some(("i", i_matches)) => {
43-
if let Some(package) = i_matches.get_one::<String>("package") {
44-
run_install_command(p, vec!["install", package])
39+
println!(
40+
"πŸ₯³ The current package manager being used is : '{}@{}' ",
41+
p, v
42+
);
43+
match m.subcommand() {
44+
Some(("add", add_matches)) => {
45+
let package = add_matches.get_one::<String>("package").unwrap();
46+
let save = add_matches.get_flag("save");
47+
let save_dev = add_matches.get_flag("save-dev");
48+
let save_optional = add_matches.get_flag("save-optional");
49+
let global = add_matches.get_flag("global");
50+
if save {
51+
run_shell(format!("{} add --save {}", p, package))
52+
} else if save_dev {
53+
run_shell(format!("{} add --save-dev {}", p, package));
54+
} else if save_optional {
55+
run_shell(format!("{} add --save-optional {}", p, package))
56+
} else if global {
57+
match p.as_str() {
58+
"yarn" => run_shell(format!("yarn global add {}", package)),
59+
_ => run_shell(format!("{} add --global {}", p, package)),
60+
}
4561
} else {
46-
run_install_command(p, vec!["install"])
62+
run_shell(format!("{} add {}", p, package));
4763
}
4864
}
49-
Some(("ci", _ci_matches)) => match p.as_str() {
50-
"npm" => {
51-
run_install_command(p, vec!["ci"]);
52-
}
53-
"pnpm" => {
54-
run_install_command(p, vec!["install", "--frozen-lockfile"]);
55-
}
56-
"yarn" => {
57-
run_install_command(p, vec!["install", "--frozen-lockfile"]);
58-
}
59-
_ => {}
65+
Some(("install", _install_matches)) => run_shell(format!("{} install", p)),
66+
Some(("clean-install", _clean_install_matches)) => match p.as_str() {
67+
"npm" => run_shell(format!("npm ci")),
68+
_ => run_shell(format!("{} install --frozen-lockfile", p)),
6069
},
61-
Some(("r", r_matches)) => match r_matches.get_one::<String>("script") {
62-
Some(script) => {
63-
run_install_command(p, vec![script]);
64-
}
65-
None => {
66-
panic!("😒")
67-
}
68-
},
69-
Some(("x", x_matches)) => {
70-
if let Some(_package) = x_matches.get_many::<String>("package") {
71-
// println!("{}", package.map(|s| s.as_str()));
72-
match p.as_str() {
73-
"npm" => {
74-
// run_install_command(&"npx".to_string(), vec![package]);
75-
}
76-
"pnpm" => {
77-
// run_install_command(&"pnpx".to_string(), vec![package]);
78-
}
79-
"yarn" => {
80-
// run_install_command(&"yarn".to_string(), vec![package]);
81-
}
82-
_ => {}
83-
}
84-
}
70+
_ => {
71+
println!("πŸ™ Sorry, the command you entered is currently not supported.")
8572
}
86-
None => (),
87-
_ => unreachable!(),
8873
}
8974
}
9075
}
9176

9277
pub fn read_package_manager() -> Result<Vec<String>, &'static str> {
9378
let path = Path::new("./package.json");
9479
if path.exists() {
95-
if let Ok(contents) = fs::read_to_string(path) {
96-
let parsed: Value = serde_json::from_str(&contents).unwrap();
97-
match parsed["packageManager"].as_str() {
98-
Some(manager) => {
99-
let vec: Vec<String> = manager.split('@').map(|s| s.to_string()).collect();
100-
101-
return Ok(vec);
102-
}
103-
None => {
80+
let contents = fs::read_to_string(path).unwrap();
81+
let parsed: Value = serde_json::from_str(&contents).unwrap();
82+
match parsed["packageManager"].as_str() {
83+
Some(manager) => {
84+
let re = Regex::new(r"(npm|pnpm|yarn)@(.*)").unwrap();
85+
if let Some(caps) = re.captures(manager) {
86+
return Ok(vec![caps[1].to_string(), caps[2].to_string()]);
87+
} else {
10488
return Err(
105-
"😒 Sorry, you must to be configure packageManager in package.json file ",
106-
)
89+
"😒 PackageManager parsing failed, possibly due to incorrect format. ",
90+
);
10791
}
10892
}
109-
} else {
110-
return Err("😒 Failure to read package.json ");
93+
None => {
94+
return Err(
95+
"😒 Sorry, you must to be configure packageManager in package.json file ",
96+
)
97+
}
11198
}
11299
}
113-
Err("πŸ”Ž Could not found package.json")
100+
return Err("πŸ”Ž Could not found package.json");
114101
}
115102

116-
pub fn run_install_command(package_manager: &String, cmd_arg: Vec<&str>) {
117-
let mut cmd = Exec::cmd(package_manager).stdout(subprocess::Redirection::Pipe);
118-
for arg in cmd_arg {
119-
cmd = cmd.arg(arg);
120-
}
121-
let mut popen = cmd.popen().unwrap();
122-
let stdout = popen.stdout.take().unwrap();
123-
let reader = BufReader::new(stdout);
124-
for line in reader.lines() {
125-
println!("{}", line.unwrap());
126-
}
103+
fn run_shell(cmd: String) {
104+
println!("🎯 The instruction to be executed is : '{}' ", cmd);
105+
Exec::cmd("sh").arg("-c").arg(cmd).popen().unwrap();
127106
}

0 commit comments

Comments
Β (0)