aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-09-15 11:49:58 +0100
committerAkshay <[email protected]>2021-09-15 11:49:58 +0100
commitc91c2ae1398e4f567ee5e4c50a1da35a9b65919b (patch)
tree71532adbed436fd99e13d81e4ac76a27f82ff7f7
parent2ee7db0b3b6df787c7e62d3614f97a0e45d12a12 (diff)
init cli entrypoint
-rw-r--r--bin/Cargo.toml4
-rw-r--r--bin/src/main.rs81
2 files changed, 84 insertions, 1 deletions
diff --git a/bin/Cargo.toml b/bin/Cargo.toml
index 57cff11..979bd46 100644
--- a/bin/Cargo.toml
+++ b/bin/Cargo.toml
@@ -6,3 +6,7 @@ edition = "2018"
6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 7
8[dependencies] 8[dependencies]
9lib = { path = "../lib" }
10ariadne = "0.1.3"
11anyhow = "1.0"
12rnix = "0.9.0"
diff --git a/bin/src/main.rs b/bin/src/main.rs
index e7a11a9..ae45bfe 100644
--- a/bin/src/main.rs
+++ b/bin/src/main.rs
@@ -1,3 +1,82 @@
1use std::{
2 env, fs,
3 path::{Path, PathBuf},
4};
5
6use anyhow::{Context, Result};
7use ariadne::{Color, Fmt, Label, Report as CliReport, ReportKind as CliReportKind, Source};
8use lib::{Report, LINTS};
9use rnix::WalkEvent;
10
11fn analyze(file: &str) -> Result<Vec<Report>> {
12 let parsed = rnix::parse(file).as_result()?;
13
14 Ok(parsed
15 .node()
16 .preorder_with_tokens()
17 .filter_map(|event| match event {
18 WalkEvent::Enter(child) => LINTS.get(&child.kind()).map(|rules| {
19 rules
20 .iter()
21 .filter_map(|rule| rule.validate(&child))
22 .collect::<Vec<_>>()
23 }),
24 _ => None,
25 })
26 .flatten()
27 .collect())
28}
29
30fn print_report(report: Report, file_src: &str, file_path: &Path) -> Result<()> {
31 let src_id = file_path.to_str().unwrap_or("<unknown>");
32 let offset = report
33 .diagnostics
34 .iter()
35 .map(|d| d.at.start().into())
36 .min()
37 .unwrap_or(0usize);
38 report
39 .diagnostics
40 .iter()
41 .fold(
42 CliReport::build(CliReportKind::Warning, src_id, offset),
43 |cli_report, diagnostic| {
44 let range = {
45 let at = diagnostic.at;
46 at.start().into()..at.end().into()
47 };
48 cli_report.with_label(
49 Label::new((src_id, range))
50 .with_message(diagnostic.message.as_str().fg(Color::Yellow)),
51 )
52 },
53 )
54 .finish()
55 .print((src_id, Source::from(file_src)))
56 .context("failed to print report to stdout")
57}
58
59fn _main() -> Result<()> {
60 let args = env::args();
61 for (file_src, file_path, reports) in args
62 .map(|s| PathBuf::from(&s))
63 .filter(|p| p.is_file())
64 .filter_map(|path| {
65 let s = fs::read_to_string(&path).ok()?;
66 analyze(&s)
67 .map(|analysis_result| (s, path, analysis_result))
68 .ok()
69 })
70 {
71 for r in reports {
72 print_report(r, &file_src, &file_path)?
73 }
74 }
75 Ok(())
76}
1fn main() { 77fn main() {
2 println!("Hello, world!"); 78 match _main() {
79 Err(e) => eprintln!("{}", e),
80 _ => {}
81 }
3} 82}