aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-02-17 17:02:10 +0000
committerAleksey Kladov <[email protected]>2020-02-17 17:02:10 +0000
commit017f0e4e53dfb1fb1b8a1844cf99b253dd9dbd25 (patch)
tree8800cc2503cd4a0c71537f008780e014ff11c248 /crates
parent90e61ac75dcf4cdae41de4df41557f6ae5186a9a (diff)
Refactor arg parsing
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_cli/src/main.rs284
1 files changed, 169 insertions, 115 deletions
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 4a428faff..7479fbd80 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -14,6 +14,15 @@ use ra_syntax::{AstNode, SourceFile};
14 14
15type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>; 15type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
16 16
17fn main() -> Result<()> {
18 env_logger::try_init()?;
19
20 let command = Command::from_args()?;
21 command.run()?;
22
23 Ok(())
24}
25
17#[derive(Clone, Copy)] 26#[derive(Clone, Copy)]
18pub enum Verbosity { 27pub enum Verbosity {
19 Spammy, 28 Spammy,
@@ -37,17 +46,40 @@ impl Verbosity {
37 } 46 }
38} 47}
39 48
40fn main() -> Result<()> { 49enum Command {
41 env_logger::try_init()?; 50 Parse {
51 no_dump: bool,
52 },
53 Symbols,
54 Highlight {
55 rainbow: bool,
56 },
57 Stats {
58 verbosity: Verbosity,
59 randomize: bool,
60 memory_usage: bool,
61 only: Option<String>,
62 with_deps: bool,
63 path: String,
64 },
65 Bench {
66 verbose: bool,
67 path: String,
68 op: analysis_bench::Op,
69 },
70 HelpPrinted,
71}
42 72
43 let mut matches = Arguments::from_env(); 73impl Command {
44 let subcommand = matches.subcommand()?.unwrap_or_default(); 74 fn from_args() -> Result<Command> {
75 let mut matches = Arguments::from_env();
76 let subcommand = matches.subcommand()?.unwrap_or_default();
45 77
46 match subcommand.as_str() { 78 let command = match subcommand.as_str() {
47 "parse" => { 79 "parse" => {
48 if matches.contains(["-h", "--help"]) { 80 if matches.contains(["-h", "--help"]) {
49 eprintln!( 81 eprintln!(
50 "\ 82 "\
51ra-cli-parse 83ra-cli-parse
52 84
53USAGE: 85USAGE:
@@ -56,24 +88,18 @@ USAGE:
56FLAGS: 88FLAGS:
57 -h, --help Prints help inforamtion 89 -h, --help Prints help inforamtion
58 --no-dump" 90 --no-dump"
59 ); 91 );
60 return Ok(()); 92 return Ok(Command::HelpPrinted);
61 } 93 }
62
63 let no_dump = matches.contains("--no-dump");
64 matches.finish().or_else(handle_extra_flags)?;
65 94
66 let _p = profile("parsing"); 95 let no_dump = matches.contains("--no-dump");
67 let file = file()?; 96 matches.finish().or_else(handle_extra_flags)?;
68 if !no_dump { 97 Command::Parse { no_dump }
69 println!("{:#?}", file.syntax());
70 } 98 }
71 std::mem::forget(file); 99 "symbols" => {
72 } 100 if matches.contains(["-h", "--help"]) {
73 "symbols" => { 101 eprintln!(
74 if matches.contains(["-h", "--help"]) { 102 "\
75 eprintln!(
76 "\
77ra-cli-symbols 103ra-cli-symbols
78 104
79USAGE: 105USAGE:
@@ -81,21 +107,18 @@ USAGE:
81 107
82FLAGS: 108FLAGS:
83 -h, --help Prints help inforamtion" 109 -h, --help Prints help inforamtion"
84 ); 110 );
85 return Ok(()); 111 return Ok(Command::HelpPrinted);
86 } 112 }
87 113
88 matches.finish().or_else(handle_extra_flags)?; 114 matches.finish().or_else(handle_extra_flags)?;
89 115
90 let file = file()?; 116 Command::Symbols
91 for s in file_structure(&file) {
92 println!("{:?}", s);
93 } 117 }
94 } 118 "highlight" => {
95 "highlight" => { 119 if matches.contains(["-h", "--help"]) {
96 if matches.contains(["-h", "--help"]) { 120 eprintln!(
97 eprintln!( 121 "\
98 "\
99ra-cli-highlight 122ra-cli-highlight
100 123
101USAGE: 124USAGE:
@@ -104,21 +127,18 @@ USAGE:
104FLAGS: 127FLAGS:
105 -h, --help Prints help information 128 -h, --help Prints help information
106 -r, --rainbow" 129 -r, --rainbow"
107 ); 130 );
108 return Ok(()); 131 return Ok(Command::HelpPrinted);
109 } 132 }
110
111 let rainbow_opt = matches.contains(["-r", "--rainbow"]);
112 matches.finish().or_else(handle_extra_flags)?;
113 133
114 let (analysis, file_id) = Analysis::from_single_file(read_stdin()?); 134 let rainbow = matches.contains(["-r", "--rainbow"]);
115 let html = analysis.highlight_as_html(file_id, rainbow_opt).unwrap(); 135 matches.finish().or_else(handle_extra_flags)?;
116 println!("{}", html); 136 Command::Highlight { rainbow }
117 } 137 }
118 "analysis-stats" => { 138 "analysis-stats" => {
119 if matches.contains(["-h", "--help"]) { 139 if matches.contains(["-h", "--help"]) {
120 eprintln!( 140 eprintln!(
121 "\ 141 "\
122ra-cli-analysis-stats 142ra-cli-analysis-stats
123 143
124USAGE: 144USAGE:
@@ -135,47 +155,40 @@ OPTIONS:
135 155
136ARGS: 156ARGS:
137 <PATH>" 157 <PATH>"
138 ); 158 );
139 return Ok(()); 159 return Ok(Command::HelpPrinted);
140 }
141
142 let verbosity = match (
143 matches.contains(["-vv", "--spammy"]),
144 matches.contains(["-v", "--verbose"]),
145 matches.contains(["-q", "--quiet"]),
146 ) {
147 (true, _, true) => Err("Invalid flags: -q conflicts with -vv")?,
148 (true, _, false) => Verbosity::Spammy,
149 (false, false, false) => Verbosity::Normal,
150 (false, false, true) => Verbosity::Quiet,
151 (false, true, false) => Verbosity::Verbose,
152 (false, true, true) => Err("Invalid flags: -q conflicts with -v")?,
153 };
154 let randomize = matches.contains("--randomize");
155 let memory_usage = matches.contains("--memory-usage");
156 let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?;
157 let with_deps: bool = matches.contains("--with-deps");
158 let path = {
159 let mut trailing = matches.free()?;
160 if trailing.len() != 1 {
161 Err("Invalid flags")?;
162 } 160 }
163 trailing.pop().unwrap() 161
164 }; 162 let verbosity = match (
165 163 matches.contains(["-vv", "--spammy"]),
166 analysis_stats::run( 164 matches.contains(["-v", "--verbose"]),
167 verbosity, 165 matches.contains(["-q", "--quiet"]),
168 memory_usage, 166 ) {
169 path.as_ref(), 167 (true, _, true) => Err("Invalid flags: -q conflicts with -vv")?,
170 only.as_ref().map(String::as_ref), 168 (true, _, false) => Verbosity::Spammy,
171 with_deps, 169 (false, false, false) => Verbosity::Normal,
172 randomize, 170 (false, false, true) => Verbosity::Quiet,
173 )?; 171 (false, true, false) => Verbosity::Verbose,
174 } 172 (false, true, true) => Err("Invalid flags: -q conflicts with -v")?,
175 "analysis-bench" => { 173 };
176 if matches.contains(["-h", "--help"]) { 174 let randomize = matches.contains("--randomize");
177 eprintln!( 175 let memory_usage = matches.contains("--memory-usage");
178 "\ 176 let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?;
177 let with_deps: bool = matches.contains("--with-deps");
178 let path = {
179 let mut trailing = matches.free()?;
180 if trailing.len() != 1 {
181 Err("Invalid flags")?;
182 }
183 trailing.pop().unwrap()
184 };
185
186 Command::Stats { verbosity, randomize, memory_usage, only, with_deps, path }
187 }
188 "analysis-bench" => {
189 if matches.contains(["-h", "--help"]) {
190 eprintln!(
191 "\
179ra_cli-analysis-bench 192ra_cli-analysis-bench
180 193
181USAGE: 194USAGE:
@@ -191,29 +204,28 @@ OPTIONS:
191 204
192ARGS: 205ARGS:
193 <PATH> Project to analyse" 206 <PATH> Project to analyse"
194 ); 207 );
195 return Ok(()); 208 return Ok(Command::HelpPrinted);
196 } 209 }
197 210
198 let verbose = matches.contains(["-v", "--verbose"]); 211 let verbose = matches.contains(["-v", "--verbose"]);
199 let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default(); 212 let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default();
200 let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?; 213 let highlight_path: Option<String> = matches.opt_value_from_str("--highlight")?;
201 let complete_path: Option<String> = matches.opt_value_from_str("--complete")?; 214 let complete_path: Option<String> = matches.opt_value_from_str("--complete")?;
202 let goto_def_path: Option<String> = matches.opt_value_from_str("--goto-def")?; 215 let goto_def_path: Option<String> = matches.opt_value_from_str("--goto-def")?;
203 let op = match (highlight_path, complete_path, goto_def_path) { 216 let op = match (highlight_path, complete_path, goto_def_path) {
204 (Some(path), None, None) => analysis_bench::Op::Highlight { path: path.into() }, 217 (Some(path), None, None) => analysis_bench::Op::Highlight { path: path.into() },
205 (None, Some(position), None) => analysis_bench::Op::Complete(position.parse()?), 218 (None, Some(position), None) => analysis_bench::Op::Complete(position.parse()?),
206 (None, None, Some(position)) => analysis_bench::Op::GotoDef(position.parse()?), 219 (None, None, Some(position)) => analysis_bench::Op::GotoDef(position.parse()?),
207 _ => panic!( 220 _ => panic!(
208 "exactly one of `--highlight`, `--complete` or `--goto-def` must be set" 221 "exactly one of `--highlight`, `--complete` or `--goto-def` must be set"
209 ), 222 ),
210 }; 223 };
211 matches.finish().or_else(handle_extra_flags)?; 224 Command::Bench { verbose, path, op }
212 225 }
213 analysis_bench::run(verbose, path.as_ref(), op)?; 226 _ => {
214 } 227 eprintln!(
215 _ => eprintln!( 228 "\
216 "\
217ra-cli 229ra-cli
218 230
219USAGE: 231USAGE:
@@ -228,9 +240,51 @@ SUBCOMMANDS:
228 highlight 240 highlight
229 parse 241 parse
230 symbols" 242 symbols"
231 ), 243 );
244 return Ok(Command::HelpPrinted);
245 }
246 };
247 Ok(command)
248 }
249
250 fn run(self) -> Result<()> {
251 match self {
252 Command::Parse { no_dump } => {
253 let _p = profile("parsing");
254 let file = file()?;
255 if !no_dump {
256 println!("{:#?}", file.syntax());
257 }
258 std::mem::forget(file);
259 }
260 Command::Symbols => {
261 let file = file()?;
262 for s in file_structure(&file) {
263 println!("{:?}", s);
264 }
265 }
266 Command::Highlight { rainbow } => {
267 let (analysis, file_id) = Analysis::from_single_file(read_stdin()?);
268 let html = analysis.highlight_as_html(file_id, rainbow).unwrap();
269 println!("{}", html);
270 }
271 Command::Stats { verbosity, randomize, memory_usage, only, with_deps, path } => {
272 analysis_stats::run(
273 verbosity,
274 memory_usage,
275 path.as_ref(),
276 only.as_ref().map(String::as_ref),
277 with_deps,
278 randomize,
279 )?;
280 }
281 Command::Bench { verbose, path, op } => {
282 analysis_bench::run(verbose, path.as_ref(), op)?;
283 }
284 Command::HelpPrinted => (),
285 }
286 Ok(())
232 } 287 }
233 Ok(())
234} 288}
235 289
236fn handle_extra_flags(e: pico_args::Error) -> Result<()> { 290fn handle_extra_flags(e: pico_args::Error) -> Result<()> {