1use clap::Clap;2use jsonnet_evaluator::Val;3use std::str::FromStr;45enum Format {6 None,7 Json,8}910impl FromStr for Format {11 type Err = &'static str;12 fn from_str(s: &str) -> Result<Self, Self::Err> {13 Ok(match s {14 "none" => Format::None,15 "json" => Format::Json,16 _ => return Err("no such format"),17 })18 }19}2021#[derive(Clap)]22#[clap(version = "0.1.0", author = "Lach <iam@lach.pw>")]23struct Opts {24 #[clap(long, about = "Disable global std variable")]25 no_stdlib: bool,26 #[clap(long, about = "Add external string")]27 ext_str: Option<Vec<String>>,28 #[clap(long, about = "Add external string from code")]29 ext_code: Option<Vec<String>>,30 #[clap(long, about = "Add TLA")]31 tla_str: Option<Vec<String>>,32 #[clap(long, about = "Add TLA from code")]33 tla_code: Option<Vec<String>>,34 #[clap(long, short = "f", default_value = "json", possible_values = &["none", "json"])]35 format: Format,36 #[clap(about = "File to compile")]37 input: String,38}3940fn main() {41 let opts: Opts = Opts::parse();42 let evaluator = jsonnet_evaluator::EvaluationState::default();43 if !opts.no_stdlib {44 evaluator.add_stdlib();45 }46 evaluator47 .add_file(48 opts.input.clone(),49 String::from_utf8(std::fs::read(opts.input.clone()).unwrap()).unwrap(),50 )51 .unwrap();52 let result = evaluator.evaluate_file(&opts.input);53 match result {54 Ok(mut v) => {55 if let Format::Json = opts.format {56 if opts.no_stdlib {57 evaluator.add_stdlib();58 }59 evaluator.add_global("__tmp__to_json__".to_owned(), v);60 v = evaluator61 .parse_evaluate_raw("std.manifestJsonEx(__tmp__to_json__, \" \")")62 .expect("json serialization");63 }64 match v {65 Val::Str(s) => println!("{}", s),66 Val::Num(n) => println!("{}", n),67 _v => eprintln!(68 "jsonnet output is not a string.\nDid you forgot to set --format, or wrap your data with std.manifestJson?"69 ),70 }71 }72 Err(err) => {73 println!("Error: {:?}", err.0);74 use annotate_snippets::{75 display_list::{DisplayList, FormatOptions},76 snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},77 };78 for item in (err.1).0.iter() {79 let desc = &item.1;80 if (item.0).1.is_none() {81 continue;82 }83 let source = (item.0).1.clone().unwrap();84 let code = evaluator.get_source(&source.0);85 let snippet = Snippet {86 opt: FormatOptions {87 color: true,88 ..Default::default()89 },90 title: Some(Annotation {91 label: Some(&item.1),92 id: None,93 annotation_type: AnnotationType::Error,94 }),95 footer: vec![],96 slices: vec![Slice {97 source: &code,98 line_start: 1,99 origin: Some(&source.0),100 fold: true,101 annotations: vec![SourceAnnotation {102 label: desc,103 annotation_type: AnnotationType::Error,104 range: (source.1, source.2),105 }],106 }],107 };108109 let dl = DisplayList::from(snippet);110 println!("{}", dl);111 }112 }113 }114}