Skip to content

Commit

Permalink
feat: support aliases to subcmds (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
sigoden authored Dec 11, 2023
1 parent 43f1b87 commit 90fdec5
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 39 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ In this way, you can use the syntax of the tool you are most familiar with to ma
```
| Tool | Install | Uninstall | Upgrade | Search | Info | Update Index | Upgrade All | List Installed |
| -------- | --------------------------- | --------------------------- | ------------------------------- | -------------------------- | ------------------------------ | ------------------------ | ------------------------ | --------------------------------- |
| upt | upt install $pkg | upt remove $pkg | upt upgrade $pkg | upt search $pkg | upt info $pkg | upt update | upt upgrade | upt list |
| upt | upt install $pkg | upt remove/uninstall $pkg | upt upgrade $pkg | upt search $pkg | upt info/show $pkg | upt update | upt upgrade | upt list |
| apk | apk add $pkg | apk del $pkg | apk upgrade $pkg | apk search $pkg | apk info $pkg | apk update | apk upgrade | apk list -I/--installed |
| apt | apt install $pkg | apt remove $pkg | apt install --only-upgrade $pkg | apt search $pkg | apt show $pkg | apt update | apt upgrade | apt list -i/--installed |
| brew | brew install $pkg | brew uninstall $pkg | brew upgrade $pkg | brew search $pkg | brew info $pkg | brew update | brew upgrade | brew list |
Expand Down
67 changes: 35 additions & 32 deletions src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use std::str::FromStr;
#[derive(Debug, Clone, PartialEq, Default)]
pub(crate) struct Action {
cmd: String,
action: Option<String>,
has_pkg: bool,
subcmd: Vec<String>,
options: Vec<Vec<String>>,
has_pkg: bool,
}

impl FromStr for Action {
Expand All @@ -23,18 +23,11 @@ impl FromStr for Action {
if words.len() < 2 {
return Err(UptError::InvalidAction(s.to_string()));
}
let (cmd, action, reminder) = if words[1].starts_with('-') || words[1] == "$" {
(words[0].to_string(), None, &words[1..])
let (cmd, subcmd, reminder) = if words[1].starts_with('-') || words[1] == "$" {
(words[0].to_string(), vec![], &words[1..])
} else {
(
words[0].to_string(),
Some(words[1].to_string()),
&words[2..],
)
(words[0].to_string(), split(words[1]), &words[2..])
};
fn split(v: &str) -> Vec<String> {
v.split('/').map(|x| x.to_string()).collect::<Vec<String>>()
}
for elem in reminder {
if elem == &"$" {
has_pkg = true;
Expand All @@ -46,15 +39,14 @@ impl FromStr for Action {
}
Ok(Action {
cmd,
action,
has_pkg,
subcmd,
options,
has_pkg,
})
}
}

impl Action {
/// Try to parse the command line arguemnts
pub fn parse(&self, args: &[String], confirm: &str) -> Option<(Option<String>, bool)> {
if self.invalid() {
return None;
Expand All @@ -81,7 +73,7 @@ impl Action {
return None;
}
let mut segs: Vec<&str> = vec![&self.cmd];
if let Some(action) = &self.action {
if let Some(action) = &self.subcmd.first() {
segs.push(action);
}
for item in &self.options {
Expand All @@ -96,20 +88,19 @@ impl Action {
Some(segs.join(" "))
}

/// Genereate help message
pub fn help(&self) -> Option<String> {
if self.invalid() {
return None;
}
let mut segs: Vec<String> = vec![self.cmd.clone()];

if let Some(action) = &self.action {
segs.push(action.clone());
if !self.subcmd.is_empty() {
segs.push(join(&self.subcmd));
}

for item in &self.options {
if item.len() > 1 {
segs.push(item.join("/"));
segs.push(join(item));
} else {
segs.push(item[0].clone());
}
Expand All @@ -131,13 +122,13 @@ impl Action {
if self.cmd != args[0] {
return None;
}
let reminder = if let Some(action) = &self.action {
if &args[1] != action {
let reminder = if self.subcmd.is_empty() {
&args[1..]
} else {
if !self.subcmd.contains(&args[1]) {
return None;
}
&args[2..]
} else {
&args[1..]
};
let mut options: Vec<String> = vec![];
let mut operands: Vec<String> = vec![];
Expand Down Expand Up @@ -188,17 +179,25 @@ pub(crate) fn must_from_str(s: &str, name: &str, field: &str) -> Action {
}
}

fn split(v: &str) -> Vec<String> {
v.split('/').map(|x| x.to_string()).collect::<Vec<String>>()
}

fn join(v: &[String]) -> String {
v.join("/")
}

#[cfg(test)]
mod tests {
use super::Action;
use std::str::FromStr;

macro_rules! check_action_from_str {
($input:expr, { $cmd:expr, $action:expr, [$([$($options:expr),* $(,)*]),*], $has_pkg:expr }) => {
($input:expr, { $cmd:expr, $subcmd:expr, [$([$($options:expr),* $(,)*]),*], $has_pkg:expr }) => {
let action = Action::from_str($input).unwrap();
let expect_action = Action {
cmd: $cmd.to_string(),
action: $action.map(|v| v.to_string()),
subcmd: $subcmd.iter().map(|v| v.to_string()).collect(),
has_pkg: $has_pkg,
options: vec![$(vec![$($options.to_string(),)*],)*],
};
Expand All @@ -210,27 +209,31 @@ mod tests {
fn test_action_from_str() {
check_action_from_str!(
"upt install $",
{ "upt", Some("install"), [], true }
{ "upt", ["install"], [], true }
);
check_action_from_str!(
"upt search $",
{ "upt", Some("search"), [], true }
{ "upt", ["search"], [], true }
);
check_action_from_str!(
"upt remove/uninstall $",
{ "upt", ["remove", "uninstall"], [], true }
);
check_action_from_str!(
"apt list --installed",
{"apt", Some("list"), [["--installed"]], false }
{"apt", ["list"], [["--installed"]], false }
);
check_action_from_str!(
"pacman -R -s $",
{ "pacman", None::<&str>, [["-R"], ["-s"]], true }
{ "pacman", Vec::<&str>::new(), [["-R"], ["-s"]], true }
);
check_action_from_str!(
"pacman -S -y -y",
{ "pacman", None::<&str>, [["-S"], ["-y"], ["-y"]], false }
{ "pacman", Vec::<&str>::new(), [["-S"], ["-y"], ["-y"]], false }
);
check_action_from_str!(
"pacman -S $",
{ "pacman", None::<&str>, [["-S"]], true }
{ "pacman", Vec::<&str>::new(), [["-S"]], true }
);
}

Expand Down
14 changes: 8 additions & 6 deletions src/vendor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ vendors![
name: "upt",
confirm: "-y/--yes",
install: "upt install $",
remove: "upt remove $",
remove: "upt remove/uninstall $",
upgrade: "upt upgrade $",
search: "upt search $",
info: "upt info $",
info: "upt info/show $",
update_index: "upt update",
upgrade_all: "upt upgrade",
list_installed: "upt list",
Expand Down Expand Up @@ -469,10 +469,7 @@ impl Vendor {
}
if !self.confirm.is_empty() {
lines.push(String::new());
lines.push(format!(
"Automatically confirm the action with: {}",
self.confirm
));
lines.push(format!("Automatic answer yes to prompts: {}", self.confirm));
}
lines.join("\n")
}
Expand Down Expand Up @@ -515,6 +512,11 @@ mod tests {
["upt", "remove", "--yes", "vim", "jq"],
(Remove, "vim jq", true)
);
check_parse!(
upt,
["upt", "uninstall", "--yes", "vim", "jq"],
(Remove, "vim jq", true)
);
check_parse!(upt, ["upt", "upgrade", "vim"], (Upgrade, "vim", false));
check_parse!(upt, ["upt", "search", "vim"], (Search, pkg = "vim"));
check_parse!(
Expand Down

0 comments on commit 90fdec5

Please sign in to comment.