1use std::ffi::OsString;
13
14pub static ALIASES: &[(&str, &[&str])] = &[
16 ("fetch", &["source", "fetch"]),
17 ("install", &["module", "install"]),
18 ("list", &["source", "list"]),
19 ("resolve", &["module", "resolve"]),
20 ("snap", &["source", "snap"]),
21 ("uninstall", &["module", "uninstall"]),
22 ("upgrade", &["module", "upgrade"]),
23];
24
25const OPTIONS_WITH_VALUES: &[&str] = &["--color"];
29
30pub fn resolve(args: &mut Vec<OsString>) {
39 let mut i = 1; while i < args.len() {
41 let Some(arg) = args[i].to_str() else {
42 return; };
44
45 if arg == "--" {
47 return;
48 }
49
50 if arg.starts_with('-') && arg.len() > 1 {
52 i += if OPTIONS_WITH_VALUES.contains(&arg) {
53 2
54 } else {
55 1
56 };
57 continue;
58 }
59
60 if arg == "help" {
62 i += 1;
63 continue;
64 }
65
66 if let Some((_, expansion)) = ALIASES.iter().find(|(name, _)| *name == arg) {
68 args.splice(i..=i, expansion.iter().map(OsString::from));
69 }
70 return;
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 fn resolved(args: &[&str]) -> Vec<String> {
79 let mut args: Vec<OsString> = args.iter().map(OsString::from).collect();
80 resolve(&mut args);
81 args.into_iter()
82 .map(|arg| arg.into_string().unwrap())
83 .collect()
84 }
85
86 #[test]
87 fn expands_fetch() {
88 assert_eq!(
89 resolved(&["asimov", "fetch", "http://example.org"]),
90 ["asimov", "source", "fetch", "http://example.org"]
91 );
92 }
93
94 #[test]
95 fn expands_snap() {
96 assert_eq!(resolved(&["asimov", "snap"]), ["asimov", "source", "snap"]);
97 }
98
99 #[test]
100 fn expands_install() {
101 assert_eq!(
102 resolved(&["asimov", "install", "serpapi"]),
103 ["asimov", "module", "install", "serpapi"]
104 );
105 }
106
107 #[test]
108 fn skips_leading_flags() {
109 assert_eq!(
110 resolved(&["asimov", "-d", "--color", "auto", "fetch", "url"]),
111 ["asimov", "-d", "--color", "auto", "source", "fetch", "url"]
112 );
113 }
114
115 #[test]
116 fn leaves_non_aliases_untouched() {
117 assert_eq!(
118 resolved(&["asimov", "module", "list"]),
119 ["asimov", "module", "list"]
120 );
121 }
122
123 #[test]
124 fn only_expands_the_subcommand_position() {
125 assert_eq!(
126 resolved(&["asimov", "module", "install", "fetch"]),
127 ["asimov", "module", "install", "fetch"]
128 );
129 }
130
131 #[test]
132 fn expands_alias_after_help() {
133 assert_eq!(
134 resolved(&["asimov", "help", "fetch"]),
135 ["asimov", "help", "source", "fetch"]
136 );
137 assert_eq!(
138 resolved(&["asimov", "help", "install"]),
139 ["asimov", "help", "module", "install"]
140 );
141 }
142
143 #[test]
144 fn leaves_help_for_non_aliases_untouched() {
145 assert_eq!(resolved(&["asimov", "help"]), ["asimov", "help"]);
146 assert_eq!(
147 resolved(&["asimov", "help", "module"]),
148 ["asimov", "help", "module"]
149 );
150 }
151
152 #[test]
153 fn ignores_args_after_double_dash() {
154 assert_eq!(
155 resolved(&["asimov", "--", "fetch"]),
156 ["asimov", "--", "fetch"]
157 );
158 }
159}