diff options
Diffstat (limited to 'crates/ra_cli/src')
-rw-r--r-- | crates/ra_cli/src/main.rs | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs new file mode 100644 index 000000000..96e5b718c --- /dev/null +++ b/crates/ra_cli/src/main.rs | |||
@@ -0,0 +1,97 @@ | |||
1 | extern crate clap; | ||
2 | #[macro_use] | ||
3 | extern crate failure; | ||
4 | extern crate ra_syntax; | ||
5 | extern crate ra_editor; | ||
6 | extern crate tools; | ||
7 | |||
8 | use std::{ | ||
9 | fs, io::Read, path::Path, | ||
10 | time::Instant | ||
11 | }; | ||
12 | use clap::{App, Arg, SubCommand}; | ||
13 | use tools::collect_tests; | ||
14 | use ra_syntax::File; | ||
15 | use ra_editor::{syntax_tree, file_structure}; | ||
16 | |||
17 | type Result<T> = ::std::result::Result<T, failure::Error>; | ||
18 | |||
19 | fn main() -> Result<()> { | ||
20 | let matches = App::new("ra-cli") | ||
21 | .setting(clap::AppSettings::SubcommandRequiredElseHelp) | ||
22 | .subcommand( | ||
23 | SubCommand::with_name("render-test") | ||
24 | .arg( | ||
25 | Arg::with_name("line") | ||
26 | .long("--line") | ||
27 | .required(true) | ||
28 | .takes_value(true), | ||
29 | ) | ||
30 | .arg( | ||
31 | Arg::with_name("file") | ||
32 | .long("--file") | ||
33 | .required(true) | ||
34 | .takes_value(true), | ||
35 | ), | ||
36 | ) | ||
37 | .subcommand( | ||
38 | SubCommand::with_name("parse") | ||
39 | .arg(Arg::with_name("no-dump").long("--no-dump")) | ||
40 | ) | ||
41 | .subcommand(SubCommand::with_name("symbols")) | ||
42 | .get_matches(); | ||
43 | match matches.subcommand() { | ||
44 | ("parse", Some(matches)) => { | ||
45 | let start = Instant::now(); | ||
46 | let file = file()?; | ||
47 | let elapsed = start.elapsed(); | ||
48 | if !matches.is_present("no-dump") { | ||
49 | println!("{}", syntax_tree(&file)); | ||
50 | } | ||
51 | eprintln!("parsing: {:?}", elapsed); | ||
52 | ::std::mem::forget(file); | ||
53 | } | ||
54 | ("symbols", _) => { | ||
55 | let file = file()?; | ||
56 | for s in file_structure(&file) { | ||
57 | println!("{:?}", s); | ||
58 | } | ||
59 | } | ||
60 | ("render-test", Some(matches)) => { | ||
61 | let file = matches.value_of("file").unwrap(); | ||
62 | let file = Path::new(file); | ||
63 | let line: usize = matches.value_of("line").unwrap().parse()?; | ||
64 | let line = line - 1; | ||
65 | let (test, tree) = render_test(file, line)?; | ||
66 | println!("{}\n{}", test, tree); | ||
67 | } | ||
68 | _ => unreachable!(), | ||
69 | } | ||
70 | Ok(()) | ||
71 | } | ||
72 | |||
73 | fn file() -> Result<File> { | ||
74 | let text = read_stdin()?; | ||
75 | Ok(File::parse(&text)) | ||
76 | } | ||
77 | |||
78 | fn read_stdin() -> Result<String> { | ||
79 | let mut buff = String::new(); | ||
80 | ::std::io::stdin().read_to_string(&mut buff)?; | ||
81 | Ok(buff) | ||
82 | } | ||
83 | |||
84 | fn render_test(file: &Path, line: usize) -> Result<(String, String)> { | ||
85 | let text = fs::read_to_string(file)?; | ||
86 | let tests = collect_tests(&text); | ||
87 | let test = tests.into_iter().find(|(start_line, t)| { | ||
88 | *start_line <= line && line <= *start_line + t.text.lines().count() | ||
89 | }); | ||
90 | let test = match test { | ||
91 | None => bail!("No test found at line {} at {}", line, file.display()), | ||
92 | Some((_start_line, test)) => test, | ||
93 | }; | ||
94 | let file = File::parse(&test.text); | ||
95 | let tree = syntax_tree(&file); | ||
96 | Ok((test.text, tree)) | ||
97 | } | ||