diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-10 18:37:21 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-10 18:37:21 +0100 |
commit | 1140a83c1b393cdcd18e42d5d816fd8be348b059 (patch) | |
tree | e2cd3ed0feabb81b4a51b1150542c5d7da920679 /crates/ra_cli/src | |
parent | 753a569c79c5a4a1dd7624028cc85fa9590da53d (diff) | |
parent | aa894ace1fc4600dbc94bccb05532154ee2288d8 (diff) |
Merge #1806
1806: refactor(args): Switch to pico-args r=matklad a=Geobert
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/1768
Co-authored-by: Geobert Quach <[email protected]>
Diffstat (limited to 'crates/ra_cli/src')
-rw-r--r-- | crates/ra_cli/src/help.rs | 72 | ||||
-rw-r--r-- | crates/ra_cli/src/main.rs | 143 |
2 files changed, 157 insertions, 58 deletions
diff --git a/crates/ra_cli/src/help.rs b/crates/ra_cli/src/help.rs new file mode 100644 index 000000000..5171578f0 --- /dev/null +++ b/crates/ra_cli/src/help.rs | |||
@@ -0,0 +1,72 @@ | |||
1 | pub const GLOBAL_HELP: &str = "ra-cli | ||
2 | |||
3 | USAGE: | ||
4 | ra_cli <SUBCOMMAND> | ||
5 | |||
6 | FLAGS: | ||
7 | -h, --help Prints help information | ||
8 | |||
9 | SUBCOMMANDS: | ||
10 | analysis-bench | ||
11 | analysis-stats | ||
12 | highlight | ||
13 | parse | ||
14 | symbols"; | ||
15 | |||
16 | pub const ANALYSIS_BENCH_HELP: &str = "ra_cli-analysis-bench | ||
17 | |||
18 | USAGE: | ||
19 | ra_cli analysis-bench [FLAGS] [OPTIONS] [PATH] | ||
20 | |||
21 | FLAGS: | ||
22 | -h, --help Prints help information | ||
23 | -v, --verbose | ||
24 | |||
25 | OPTIONS: | ||
26 | --complete <PATH:LINE:COLUMN> Compute completions at this location | ||
27 | --highlight <PATH> Hightlight this file | ||
28 | |||
29 | ARGS: | ||
30 | <PATH> Project to analyse"; | ||
31 | |||
32 | pub const ANALYSIS_STATS_HELP: &str = "ra-cli-analysis-stats | ||
33 | |||
34 | USAGE: | ||
35 | ra_cli analysis-stats [FLAGS] [OPTIONS] [PATH] | ||
36 | |||
37 | FLAGS: | ||
38 | -h, --help Prints help information | ||
39 | --memory-usage | ||
40 | -v, --verbose | ||
41 | |||
42 | OPTIONS: | ||
43 | -o <ONLY> | ||
44 | |||
45 | ARGS: | ||
46 | <PATH>"; | ||
47 | |||
48 | pub const HIGHLIGHT_HELP: &str = "ra-cli-highlight | ||
49 | |||
50 | USAGE: | ||
51 | ra_cli highlight [FLAGS] | ||
52 | |||
53 | FLAGS: | ||
54 | -h, --help Prints help information | ||
55 | -r, --rainbow"; | ||
56 | |||
57 | pub const SYMBOLS_HELP: &str = "ra-cli-symbols | ||
58 | |||
59 | USAGE: | ||
60 | ra_cli highlight [FLAGS] | ||
61 | |||
62 | FLAGS: | ||
63 | -h, --help Prints help inforamtion"; | ||
64 | |||
65 | pub const PARSE_HELP: &str = "ra-cli-parse | ||
66 | |||
67 | USAGE: | ||
68 | ra_cli parse [FLAGS] | ||
69 | |||
70 | FLAGS: | ||
71 | -h, --help Prints help inforamtion | ||
72 | --no-dump"; | ||
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs index de8191ca3..e6334cf56 100644 --- a/crates/ra_cli/src/main.rs +++ b/crates/ra_cli/src/main.rs | |||
@@ -1,10 +1,11 @@ | |||
1 | mod analysis_stats; | 1 | mod analysis_stats; |
2 | mod analysis_bench; | 2 | mod analysis_bench; |
3 | mod help; | ||
3 | 4 | ||
4 | use std::{error::Error, io::Read}; | 5 | use std::{error::Error, fmt::Write, io::Read}; |
5 | 6 | ||
6 | use clap::{App, Arg, SubCommand}; | ||
7 | use flexi_logger::Logger; | 7 | use flexi_logger::Logger; |
8 | use pico_args::Arguments; | ||
8 | use ra_ide_api::{file_structure, Analysis}; | 9 | use ra_ide_api::{file_structure, Analysis}; |
9 | use ra_prof::profile; | 10 | use ra_prof::profile; |
10 | use ra_syntax::{AstNode, SourceFile}; | 11 | use ra_syntax::{AstNode, SourceFile}; |
@@ -13,77 +14,89 @@ type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>; | |||
13 | 14 | ||
14 | fn main() -> Result<()> { | 15 | fn main() -> Result<()> { |
15 | Logger::with_env().start()?; | 16 | Logger::with_env().start()?; |
16 | let matches = App::new("ra-cli") | 17 | |
17 | .setting(clap::AppSettings::SubcommandRequiredElseHelp) | 18 | let subcommand = match std::env::args_os().nth(1) { |
18 | .subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump"))) | 19 | None => { |
19 | .subcommand(SubCommand::with_name("symbols")) | 20 | eprintln!("{}", help::GLOBAL_HELP); |
20 | .subcommand( | 21 | return Ok(()); |
21 | SubCommand::with_name("highlight") | 22 | } |
22 | .arg(Arg::with_name("rainbow").short("r").long("rainbow")), | 23 | Some(s) => s, |
23 | ) | 24 | }; |
24 | .subcommand( | 25 | let mut matches = Arguments::from_vec(std::env::args_os().skip(2).collect()); |
25 | SubCommand::with_name("analysis-stats") | 26 | |
26 | .arg(Arg::with_name("verbose").short("v").long("verbose")) | 27 | match &*subcommand.to_string_lossy() { |
27 | .arg(Arg::with_name("memory-usage").long("memory-usage")) | 28 | "parse" => { |
28 | .arg(Arg::with_name("only").short("o").takes_value(true)) | 29 | if matches.contains(["-h", "--help"]) { |
29 | .arg(Arg::with_name("path")), | 30 | eprintln!("{}", help::PARSE_HELP); |
30 | ) | 31 | return Ok(()); |
31 | .subcommand( | 32 | } |
32 | SubCommand::with_name("analysis-bench") | 33 | let no_dump = matches.contains("--no-dump"); |
33 | .arg(Arg::with_name("verbose").short("v").long("verbose")) | 34 | matches.finish().or_else(handle_extra_flags)?; |
34 | .arg( | 35 | |
35 | Arg::with_name("highlight") | ||
36 | .long("highlight") | ||
37 | .takes_value(true) | ||
38 | .conflicts_with("complete") | ||
39 | .value_name("PATH") | ||
40 | .help("highlight this file"), | ||
41 | ) | ||
42 | .arg( | ||
43 | Arg::with_name("complete") | ||
44 | .long("complete") | ||
45 | .takes_value(true) | ||
46 | .conflicts_with("highlight") | ||
47 | .value_name("PATH:LINE:COLUMN") | ||
48 | .help("compute completions at this location"), | ||
49 | ) | ||
50 | .arg(Arg::with_name("path").value_name("PATH").help("project to analyze")), | ||
51 | ) | ||
52 | .get_matches(); | ||
53 | match matches.subcommand() { | ||
54 | ("parse", Some(matches)) => { | ||
55 | let _p = profile("parsing"); | 36 | let _p = profile("parsing"); |
56 | let file = file()?; | 37 | let file = file()?; |
57 | if !matches.is_present("no-dump") { | 38 | if !no_dump { |
58 | println!("{:#?}", file.syntax()); | 39 | println!("{:#?}", file.syntax()); |
59 | } | 40 | } |
60 | std::mem::forget(file); | 41 | std::mem::forget(file); |
61 | } | 42 | } |
62 | ("symbols", _) => { | 43 | "symbols" => { |
44 | if matches.contains(["-h", "--help"]) { | ||
45 | eprintln!("{}", help::SYMBOLS_HELP); | ||
46 | return Ok(()); | ||
47 | } | ||
48 | matches.finish().or_else(handle_extra_flags)?; | ||
63 | let file = file()?; | 49 | let file = file()?; |
64 | for s in file_structure(&file) { | 50 | for s in file_structure(&file) { |
65 | println!("{:?}", s); | 51 | println!("{:?}", s); |
66 | } | 52 | } |
67 | } | 53 | } |
68 | ("highlight", Some(matches)) => { | 54 | "highlight" => { |
55 | if matches.contains(["-h", "--help"]) { | ||
56 | eprintln!("{}", help::HIGHLIGHT_HELP); | ||
57 | return Ok(()); | ||
58 | } | ||
59 | let rainbow_opt = matches.contains(["-r", "--rainbow"]); | ||
60 | matches.finish().or_else(handle_extra_flags)?; | ||
69 | let (analysis, file_id) = Analysis::from_single_file(read_stdin()?); | 61 | let (analysis, file_id) = Analysis::from_single_file(read_stdin()?); |
70 | let html = analysis.highlight_as_html(file_id, matches.is_present("rainbow")).unwrap(); | 62 | let html = analysis.highlight_as_html(file_id, rainbow_opt).unwrap(); |
71 | println!("{}", html); | 63 | println!("{}", html); |
72 | } | 64 | } |
73 | ("analysis-stats", Some(matches)) => { | 65 | "analysis-stats" => { |
74 | let verbose = matches.is_present("verbose"); | 66 | if matches.contains(["-h", "--help"]) { |
75 | let memory_usage = matches.is_present("memory-usage"); | 67 | eprintln!("{}", help::ANALYSIS_STATS_HELP); |
76 | let path = matches.value_of("path").unwrap_or(""); | 68 | return Ok(()); |
77 | let only = matches.value_of("only"); | 69 | } |
78 | analysis_stats::run(verbose, memory_usage, path.as_ref(), only)?; | 70 | let verbose = matches.contains(["-v", "--verbose"]); |
71 | let memory_usage = matches.contains("--memory-usage"); | ||
72 | let path: String = matches.value_from_str("--path")?.unwrap_or_default(); | ||
73 | let only = matches.value_from_str(["-o", "--only"])?.map(|v: String| v.to_owned()); | ||
74 | matches.finish().or_else(handle_extra_flags)?; | ||
75 | analysis_stats::run( | ||
76 | verbose, | ||
77 | memory_usage, | ||
78 | path.as_ref(), | ||
79 | only.as_ref().map(String::as_ref), | ||
80 | )?; | ||
79 | } | 81 | } |
80 | ("analysis-bench", Some(matches)) => { | 82 | "analysis-bench" => { |
81 | let verbose = matches.is_present("verbose"); | 83 | if matches.contains(["-h", "--help"]) { |
82 | let path = matches.value_of("path").unwrap_or(""); | 84 | eprintln!("{}", help::ANALYSIS_BENCH_HELP); |
83 | let op = if let Some(path) = matches.value_of("highlight") { | 85 | return Ok(()); |
86 | } | ||
87 | let verbose = matches.contains(["-v", "--verbose"]); | ||
88 | let path: String = matches.value_from_str("--path")?.unwrap_or_default(); | ||
89 | let highlight_path = matches.value_from_str("--highlight")?; | ||
90 | let complete_path = matches.value_from_str("--complete")?; | ||
91 | if highlight_path.is_some() && complete_path.is_some() { | ||
92 | panic!("either --highlight or --complete must be set, not both") | ||
93 | } | ||
94 | let op = if let Some(path) = highlight_path { | ||
95 | let path: String = path; | ||
84 | analysis_bench::Op::Highlight { path: path.into() } | 96 | analysis_bench::Op::Highlight { path: path.into() } |
85 | } else if let Some(path_line_col) = matches.value_of("complete") { | 97 | } else if let Some(path_line_col) = complete_path { |
86 | let (path_line, column) = rsplit_at_char(path_line_col, ':')?; | 98 | let path_line_col: String = path_line_col; |
99 | let (path_line, column) = rsplit_at_char(path_line_col.as_str(), ':')?; | ||
87 | let (path, line) = rsplit_at_char(path_line, ':')?; | 100 | let (path, line) = rsplit_at_char(path_line, ':')?; |
88 | analysis_bench::Op::Complete { | 101 | analysis_bench::Op::Complete { |
89 | path: path.into(), | 102 | path: path.into(), |
@@ -93,13 +106,27 @@ fn main() -> Result<()> { | |||
93 | } else { | 106 | } else { |
94 | panic!("either --highlight or --complete must be set") | 107 | panic!("either --highlight or --complete must be set") |
95 | }; | 108 | }; |
109 | matches.finish().or_else(handle_extra_flags)?; | ||
96 | analysis_bench::run(verbose, path.as_ref(), op)?; | 110 | analysis_bench::run(verbose, path.as_ref(), op)?; |
97 | } | 111 | } |
98 | _ => unreachable!(), | 112 | _ => eprintln!("{}", help::GLOBAL_HELP), |
99 | } | 113 | } |
100 | Ok(()) | 114 | Ok(()) |
101 | } | 115 | } |
102 | 116 | ||
117 | fn handle_extra_flags(e: pico_args::Error) -> Result<()> { | ||
118 | if let pico_args::Error::UnusedArgsLeft(flags) = e { | ||
119 | let mut invalid_flags = String::new(); | ||
120 | for flag in flags { | ||
121 | write!(&mut invalid_flags, "{}, ", flag)?; | ||
122 | } | ||
123 | let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2); | ||
124 | Err(format!("Invalid flags: {}", invalid_flags).into()) | ||
125 | } else { | ||
126 | Err(e.to_string().into()) | ||
127 | } | ||
128 | } | ||
129 | |||
103 | fn file() -> Result<SourceFile> { | 130 | fn file() -> Result<SourceFile> { |
104 | let text = read_stdin()?; | 131 | let text = read_stdin()?; |
105 | Ok(SourceFile::parse(&text).tree()) | 132 | Ok(SourceFile::parse(&text).tree()) |