1use std::str::FromStr;
2
3use clap::Parser;
4use jrsonnet_evaluator::{Result, tla::TlaArg, trace::PathResolver};
5use jrsonnet_stdlib::ContextInitializer;
6
7#[derive(Clone)]
8pub struct ExtStr {
9 pub name: String,
10 pub value: String,
11}
12
13impl FromStr for ExtStr {
38 type Err = &'static str;
39
40 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
41 match s.find('=') {
42 Some(idx) => Ok(Self {
43 name: s[..idx].to_owned(),
44 value: s[idx + 1..].to_owned(),
45 }),
46 None => Ok(Self {
47 name: s.to_owned(),
48 value: std::env::var(s).or(Err("missing env var"))?,
49 }),
50 }
51 }
52}
53
54#[derive(Clone)]
55pub struct ExtFile {
56 pub name: String,
57 pub path: String,
58}
59
60impl FromStr for ExtFile {
61 type Err = String;
62
63 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
64 let Some((name, path)) = s.split_once('=') else {
65 return Err("bad ext-file syntax".to_owned());
66 };
67 Ok(Self {
68 name: name.into(),
69 path: path.into(),
70 })
71 }
72}
73
74#[derive(Parser)]
75#[clap(next_help_heading = "STANDARD LIBRARY")]
76pub struct StdOpts {
77 #[clap(long)]
80 no_stdlib: bool,
81 #[clap(long, short = 'V', name = "name[=var data]", number_of_values = 1)]
87 ext_str: Vec<ExtStr>,
88 #[clap(long, name = "name=var path", number_of_values = 1)]
91 ext_str_file: Vec<ExtFile>,
92 #[clap(long, name = "name[=var source]", number_of_values = 1)]
95 ext_code: Vec<ExtStr>,
96 #[clap(long, name = "name=var code path", number_of_values = 1)]
99 ext_code_file: Vec<ExtFile>,
100}
101impl StdOpts {
102 pub fn context_initializer(&self) -> Result<Option<ContextInitializer>> {
103 if self.no_stdlib {
104 return Ok(None);
105 }
106 let ctx = ContextInitializer::new(PathResolver::new_cwd_fallback());
107 for ext in &self.ext_str {
108 ctx.settings_mut().ext_vars.insert(
109 ext.name.as_str().into(),
110 TlaArg::String(ext.value.as_str().into()),
111 );
112 }
113 for ext in &self.ext_str_file {
114 ctx.settings_mut().ext_vars.insert(
115 ext.name.as_str().into(),
116 TlaArg::ImportStr(ext.path.clone()),
117 );
118 }
119 for ext in &self.ext_code {
120 ctx.settings_mut().ext_vars.insert(
121 ext.name.as_str().into(),
122 TlaArg::InlineCode(ext.value.clone()),
123 );
124 }
125 for ext in &self.ext_code_file {
126 ctx.settings_mut()
127 .ext_vars
128 .insert(ext.name.as_str().into(), TlaArg::Import(ext.path.clone()));
129 }
130 Ok(Some(ctx))
131 }
132}