aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock8
-rw-r--r--crates/ra_cli/Cargo.toml2
-rw-r--r--crates/ra_cli/src/help.rs96
-rw-r--r--crates/ra_cli/src/main.rs186
4 files changed, 213 insertions, 79 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9092a87d3..f4b5d12a3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -838,6 +838,11 @@ dependencies = [
838] 838]
839 839
840[[package]] 840[[package]]
841name = "pico-args"
842version = "0.2.0"
843source = "registry+https://github.com/rust-lang/crates.io-index"
844
845[[package]]
841name = "ppv-lite86" 846name = "ppv-lite86"
842version = "0.2.5" 847version = "0.2.5"
843source = "registry+https://github.com/rust-lang/crates.io-index" 848source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -930,9 +935,9 @@ dependencies = [
930name = "ra_cli" 935name = "ra_cli"
931version = "0.1.0" 936version = "0.1.0"
932dependencies = [ 937dependencies = [
933 "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
934 "flexi_logger 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", 938 "flexi_logger 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)",
935 "indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 939 "indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
940 "pico-args 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
936 "ra_batch 0.1.0", 941 "ra_batch 0.1.0",
937 "ra_db 0.1.0", 942 "ra_db 0.1.0",
938 "ra_hir 0.1.0", 943 "ra_hir 0.1.0",
@@ -1873,6 +1878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1873"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" 1878"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5"
1874"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1879"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
1875"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" 1880"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
1881"checksum pico-args 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2fce25154205cf4360b456fd7d48994afe20663b77e3bd3d0a353a2fccf7f22c"
1876"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" 1882"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
1877"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8" 1883"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8"
1878"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95" 1884"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95"
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml
index 205dd223b..d42ac3ad4 100644
--- a/crates/ra_cli/Cargo.toml
+++ b/crates/ra_cli/Cargo.toml
@@ -6,7 +6,7 @@ authors = ["rust-analyzer developers"]
6publish = false 6publish = false
7 7
8[dependencies] 8[dependencies]
9clap = { version = "2.32.0", default-features = false } 9pico-args = "0.2.0"
10flexi_logger = "0.14.0" 10flexi_logger = "0.14.0"
11indicatif = "0.11.0" 11indicatif = "0.11.0"
12 12
diff --git a/crates/ra_cli/src/help.rs b/crates/ra_cli/src/help.rs
new file mode 100644
index 000000000..bf31472ac
--- /dev/null
+++ b/crates/ra_cli/src/help.rs
@@ -0,0 +1,96 @@
1pub fn print_global_help() {
2 println!(
3 "ra-cli
4
5USAGE:
6 ra_cli <SUBCOMMAND>
7
8FLAGS:
9 -h, --help Prints help information
10
11SUBCOMMANDS:
12 analysis-bench
13 analysis-stats
14 highlight
15 parse
16 symbols"
17 )
18}
19
20pub fn print_analysis_bench_help() {
21 println!(
22 "ra_cli-analysis-bench
23
24USAGE:
25 ra_cli analysis-bench [FLAGS] [OPTIONS] [PATH]
26
27FLAGS:
28 -h, --help Prints help information
29 -v, --verbose
30
31OPTIONS:
32 --complete <PATH:LINE:COLUMN> Compute completions at this location
33 --highlight <PATH> Hightlight this file
34
35ARGS:
36 <PATH> Project to analyse"
37 )
38}
39
40pub fn print_analysis_stats_help() {
41 println!(
42 "ra-cli-analysis-stats
43
44USAGE:
45 ra_cli analysis-stats [FLAGS] [OPTIONS] [PATH]
46
47FLAGS:
48 -h, --help Prints help information
49 --memory-usage
50 -v, --verbose
51
52OPTIONS:
53 -o <ONLY>
54
55ARGS:
56 <PATH>"
57 )
58}
59
60pub fn print_highlight_help() {
61 println!(
62 "ra-cli-highlight
63
64USAGE:
65 ra_cli highlight [FLAGS]
66
67FLAGS:
68 -h, --help Prints help information
69 -r, --rainbow"
70 )
71}
72
73pub fn print_symbols_help() {
74 println!(
75 "ra-cli-symbols
76
77USAGE:
78 ra_cli highlight [FLAGS]
79
80FLAGS:
81 -h, --help Prints help inforamtion"
82 )
83}
84
85pub fn print_parse_help() {
86 println!(
87 "ra-cli-parse
88
89USAGE:
90 ra_cli parse [FLAGS]
91
92FLAGS:
93 -h, --help Prints help inforamtion
94 --no-dump"
95 )
96}
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index de8191ca3..9e6f869c1 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -1,10 +1,11 @@
1mod analysis_stats; 1mod analysis_stats;
2mod analysis_bench; 2mod analysis_bench;
3mod help;
3 4
4use std::{error::Error, io::Read}; 5use std::{error::Error, fmt::Write, io::Read};
5 6
6use clap::{App, Arg, SubCommand};
7use flexi_logger::Logger; 7use flexi_logger::Logger;
8use pico_args::Arguments;
8use ra_ide_api::{file_structure, Analysis}; 9use ra_ide_api::{file_structure, Analysis};
9use ra_prof::profile; 10use ra_prof::profile;
10use ra_syntax::{AstNode, SourceFile}; 11use ra_syntax::{AstNode, SourceFile};
@@ -13,93 +14,124 @@ type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
13 14
14fn main() -> Result<()> { 15fn 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 = std::env::args_os().nth(1);
18 .subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump"))) 19 if subcommand.is_none() {
19 .subcommand(SubCommand::with_name("symbols")) 20 help::print_global_help();
20 .subcommand( 21 return Ok(());
21 SubCommand::with_name("highlight") 22 }
22 .arg(Arg::with_name("rainbow").short("r").long("rainbow")), 23 let subcommand = subcommand.unwrap();
23 ) 24 let mut args: Vec<_> = std::env::args_os().collect();
24 .subcommand( 25 let mut matches = Arguments::from_vec(args.drain(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 help::print_parse_help();
30 ) 31 return Ok(());
31 .subcommand( 32 } else {
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 let _p = profile("parsing");
36 .long("highlight") 37 let file = file()?;
37 .takes_value(true) 38 if !no_dump {
38 .conflicts_with("complete") 39 println!("{:#?}", file.syntax());
39 .value_name("PATH") 40 }
40 .help("highlight this file"), 41 std::mem::forget(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");
56 let file = file()?;
57 if !matches.is_present("no-dump") {
58 println!("{:#?}", file.syntax());
59 } 42 }
60 std::mem::forget(file);
61 } 43 }
62 ("symbols", _) => { 44 "symbols" => {
63 let file = file()?; 45 if matches.contains(["-h", "--help"]) {
64 for s in file_structure(&file) { 46 help::print_symbols_help();
65 println!("{:?}", s); 47 return Ok(());
48 } else {
49 matches.finish().or_else(handle_extra_flags)?;
50 let file = file()?;
51 for s in file_structure(&file) {
52 println!("{:?}", s);
53 }
66 } 54 }
67 } 55 }
68 ("highlight", Some(matches)) => { 56 "highlight" => {
69 let (analysis, file_id) = Analysis::from_single_file(read_stdin()?); 57 if matches.contains(["-h", "--help"]) {
70 let html = analysis.highlight_as_html(file_id, matches.is_present("rainbow")).unwrap(); 58 help::print_highlight_help();
71 println!("{}", html); 59 return Ok(());
60 } else {
61 let rainbow_opt = matches.contains(["-r", "--rainbow"]);
62 matches.finish().or_else(handle_extra_flags)?;
63 let (analysis, file_id) = Analysis::from_single_file(read_stdin()?);
64 let html = analysis.highlight_as_html(file_id, rainbow_opt).unwrap();
65 println!("{}", html);
66 }
72 } 67 }
73 ("analysis-stats", Some(matches)) => { 68 "analysis-stats" => {
74 let verbose = matches.is_present("verbose"); 69 if matches.contains(["-h", "--help"]) {
75 let memory_usage = matches.is_present("memory-usage"); 70 help::print_analysis_stats_help();
76 let path = matches.value_of("path").unwrap_or(""); 71 return Ok(());
77 let only = matches.value_of("only"); 72 } else {
78 analysis_stats::run(verbose, memory_usage, path.as_ref(), only)?; 73 let verbose = matches.contains(["-v", "--verbose"]);
74 let memory_usage = matches.contains("--memory-usage");
75 let path = matches.value_from_str("--path")?.unwrap_or("".to_string());
76 let only = matches.value_from_str(["-o", "--only"])?.map(|v: String| v.to_owned());
77 matches.finish().or_else(handle_extra_flags)?;
78 analysis_stats::run(
79 verbose,
80 memory_usage,
81 path.as_ref(),
82 only.as_ref().map(String::as_ref),
83 )?;
84 }
79 } 85 }
80 ("analysis-bench", Some(matches)) => { 86 "analysis-bench" => {
81 let verbose = matches.is_present("verbose"); 87 if matches.contains(["-h", "--help"]) {
82 let path = matches.value_of("path").unwrap_or(""); 88 help::print_analysis_bench_help();
83 let op = if let Some(path) = matches.value_of("highlight") { 89 return Ok(());
84 analysis_bench::Op::Highlight { path: path.into() }
85 } else if let Some(path_line_col) = matches.value_of("complete") {
86 let (path_line, column) = rsplit_at_char(path_line_col, ':')?;
87 let (path, line) = rsplit_at_char(path_line, ':')?;
88 analysis_bench::Op::Complete {
89 path: path.into(),
90 line: line.parse()?,
91 column: column.parse()?,
92 }
93 } else { 90 } else {
94 panic!("either --highlight or --complete must be set") 91 let verbose = matches.contains(["-v", "--verbose"]);
95 }; 92 let path = matches.value_from_str("--path")?.unwrap_or("".to_string());
96 analysis_bench::run(verbose, path.as_ref(), op)?; 93 let highlight_path = matches.value_from_str("--highlight")?;
94 let complete_path = matches.value_from_str("--complete")?;
95 if highlight_path.is_some() && complete_path.is_some() {
96 panic!("either --highlight or --complete must be set, not both")
97 }
98 let op = if let Some(path) = highlight_path {
99 let path: String = path;
100 analysis_bench::Op::Highlight { path: path.into() }
101 } else if let Some(path_line_col) = complete_path {
102 let path_line_col: String = path_line_col;
103 let (path_line, column) = rsplit_at_char(path_line_col.as_str(), ':')?;
104 let (path, line) = rsplit_at_char(path_line, ':')?;
105 analysis_bench::Op::Complete {
106 path: path.into(),
107 line: line.parse()?,
108 column: column.parse()?,
109 }
110 } else {
111 panic!("either --highlight or --complete must be set")
112 };
113 matches.finish().or_else(handle_extra_flags)?;
114 analysis_bench::run(verbose, path.as_ref(), op)?;
115 }
97 } 116 }
98 _ => unreachable!(), 117 _ => help::print_global_help(),
99 } 118 }
100 Ok(()) 119 Ok(())
101} 120}
102 121
122fn handle_extra_flags(e: pico_args::Error) -> Result<()> {
123 if let pico_args::Error::UnusedArgsLeft(flags) = e {
124 let mut invalid_flags = String::new();
125 for flag in flags {
126 write!(&mut invalid_flags, "{}, ", flag).expect("Error on write");
127 }
128 let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2);
129 Err(format!("Invalid flags: {}", invalid_flags).into())
130 } else {
131 Err(e.to_string().into())
132 }
133}
134
103fn file() -> Result<SourceFile> { 135fn file() -> Result<SourceFile> {
104 let text = read_stdin()?; 136 let text = read_stdin()?;
105 Ok(SourceFile::parse(&text).tree()) 137 Ok(SourceFile::parse(&text).tree())