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