Skip to content

Commit 1140a83

Browse files
bors[bot]Geobert Quach
and
Geobert Quach
authored
Merge #1806
1806: refactor(args): Switch to pico-args r=matklad a=Geobert Fixes #1768 Co-authored-by: Geobert Quach <[email protected]>
2 parents 753a569 + aa894ac commit 1140a83

File tree

7 files changed

+297
-114
lines changed

7 files changed

+297
-114
lines changed

Cargo.lock

Lines changed: 8 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ra_cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ authors = ["rust-analyzer developers"]
66
publish = false
77

88
[dependencies]
9-
clap = { version = "2.32.0", default-features = false }
9+
pico-args = "0.2.0"
1010
flexi_logger = "0.14.0"
1111
indicatif = "0.11.0"
1212

crates/ra_cli/src/help.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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";

crates/ra_cli/src/main.rs

Lines changed: 85 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
mod analysis_stats;
22
mod analysis_bench;
3+
mod help;
34

4-
use std::{error::Error, io::Read};
5+
use std::{error::Error, fmt::Write, io::Read};
56

6-
use clap::{App, Arg, SubCommand};
77
use flexi_logger::Logger;
8+
use pico_args::Arguments;
89
use ra_ide_api::{file_structure, Analysis};
910
use ra_prof::profile;
1011
use ra_syntax::{AstNode, SourceFile};
@@ -13,77 +14,89 @@ type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
1314

1415
fn main() -> Result<()> {
1516
Logger::with_env().start()?;
16-
let matches = App::new("ra-cli")
17-
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
18-
.subcommand(SubCommand::with_name("parse").arg(Arg::with_name("no-dump").long("--no-dump")))
19-
.subcommand(SubCommand::with_name("symbols"))
20-
.subcommand(
21-
SubCommand::with_name("highlight")
22-
.arg(Arg::with_name("rainbow").short("r").long("rainbow")),
23-
)
24-
.subcommand(
25-
SubCommand::with_name("analysis-stats")
26-
.arg(Arg::with_name("verbose").short("v").long("verbose"))
27-
.arg(Arg::with_name("memory-usage").long("memory-usage"))
28-
.arg(Arg::with_name("only").short("o").takes_value(true))
29-
.arg(Arg::with_name("path")),
30-
)
31-
.subcommand(
32-
SubCommand::with_name("analysis-bench")
33-
.arg(Arg::with_name("verbose").short("v").long("verbose"))
34-
.arg(
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)) => {
17+
18+
let subcommand = match std::env::args_os().nth(1) {
19+
None => {
20+
eprintln!("{}", help::GLOBAL_HELP);
21+
return Ok(());
22+
}
23+
Some(s) => s,
24+
};
25+
let mut matches = Arguments::from_vec(std::env::args_os().skip(2).collect());
26+
27+
match &*subcommand.to_string_lossy() {
28+
"parse" => {
29+
if matches.contains(["-h", "--help"]) {
30+
eprintln!("{}", help::PARSE_HELP);
31+
return Ok(());
32+
}
33+
let no_dump = matches.contains("--no-dump");
34+
matches.finish().or_else(handle_extra_flags)?;
35+
5536
let _p = profile("parsing");
5637
let file = file()?;
57-
if !matches.is_present("no-dump") {
38+
if !no_dump {
5839
println!("{:#?}", file.syntax());
5940
}
6041
std::mem::forget(file);
6142
}
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)?;
6349
let file = file()?;
6450
for s in file_structure(&file) {
6551
println!("{:?}", s);
6652
}
6753
}
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)?;
6961
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();
7163
println!("{}", html);
7264
}
73-
("analysis-stats", Some(matches)) => {
74-
let verbose = matches.is_present("verbose");
75-
let memory_usage = matches.is_present("memory-usage");
76-
let path = matches.value_of("path").unwrap_or("");
77-
let only = matches.value_of("only");
78-
analysis_stats::run(verbose, memory_usage, path.as_ref(), only)?;
65+
"analysis-stats" => {
66+
if matches.contains(["-h", "--help"]) {
67+
eprintln!("{}", help::ANALYSIS_STATS_HELP);
68+
return Ok(());
69+
}
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+
)?;
7981
}
80-
("analysis-bench", Some(matches)) => {
81-
let verbose = matches.is_present("verbose");
82-
let path = matches.value_of("path").unwrap_or("");
83-
let op = if let Some(path) = matches.value_of("highlight") {
82+
"analysis-bench" => {
83+
if matches.contains(["-h", "--help"]) {
84+
eprintln!("{}", help::ANALYSIS_BENCH_HELP);
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;
8496
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, ':')?;
97+
} else if let Some(path_line_col) = complete_path {
98+
let path_line_col: String = path_line_col;
99+
let (path_line, column) = rsplit_at_char(path_line_col.as_str(), ':')?;
87100
let (path, line) = rsplit_at_char(path_line, ':')?;
88101
analysis_bench::Op::Complete {
89102
path: path.into(),
@@ -93,13 +106,27 @@ fn main() -> Result<()> {
93106
} else {
94107
panic!("either --highlight or --complete must be set")
95108
};
109+
matches.finish().or_else(handle_extra_flags)?;
96110
analysis_bench::run(verbose, path.as_ref(), op)?;
97111
}
98-
_ => unreachable!(),
112+
_ => eprintln!("{}", help::GLOBAL_HELP),
99113
}
100114
Ok(())
101115
}
102116

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+
103130
fn file() -> Result<SourceFile> {
104131
let text = read_stdin()?;
105132
Ok(SourceFile::parse(&text).tree())

crates/ra_tools/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ publish = false
88
[dependencies]
99
walkdir = "2.1.3"
1010
itertools = "0.8.0"
11-
clap = { version = "2.32.0", default-features = false }
11+
pico-args = "0.2.0"
1212
quote = "1.0.2"
1313
proc-macro2 = "1.0.1"
1414
ron = "0.5.1"

0 commit comments

Comments
 (0)