git.delta.rocks / jrsonnet / refs/heads / master

difftreelog

source

crates/jrsonnet-cli/src/stdlib.rs3.4 KiBsourcehistory
1use std::str::FromStr;23use clap::Parser;4use jrsonnet_evaluator::{Result, tla::TlaArg, trace::PathResolver};5use jrsonnet_stdlib::ContextInitializer;67#[derive(Clone)]8pub struct ExtStr {9	pub name: String,10	pub value: String,11}1213/// Parses a string like `name=<value>`, or `name` and reads value from env variable.14/// With no value it will be read from env variable.15/// If env variable is not found then it will be an error.16/// Value can contain `=` symbol.17///18/// ```19/// use std::str::FromStr;20/// use jrsonnet_cli::ExtStr;21///22/// let ext = ExtStr::from_str("name=value").unwrap();23/// assert_eq!(ext.name, "name");24/// assert_eq!(ext.value, "value");25///26/// let ext = ExtStr::from_str("name=value=with=equals").unwrap();27/// assert_eq!(ext.name, "name");28/// assert_eq!(ext.value, "value=with=equals");29/// ```30///31impl FromStr for ExtStr {32	type Err = &'static str;3334	fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {35		match s.find('=') {36			Some(idx) => Ok(Self {37				name: s[..idx].to_owned(),38				value: s[idx + 1..].to_owned(),39			}),40			None => Ok(Self {41				name: s.to_owned(),42				value: std::env::var(s).or(Err("missing env var"))?,43			}),44		}45	}46}4748#[derive(Clone)]49pub struct ExtFile {50	pub name: String,51	pub path: String,52}5354impl FromStr for ExtFile {55	type Err = String;5657	fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {58		let Some((name, path)) = s.split_once('=') else {59			return Err("bad ext-file syntax".to_owned());60		};61		Ok(Self {62			name: name.into(),63			path: path.into(),64		})65	}66}6768#[derive(Parser)]69#[clap(next_help_heading = "STANDARD LIBRARY")]70pub struct StdOpts {71	/// Disable standard library.72	/// By default standard library will be available via global `std` variable.73	#[clap(long)]74	no_stdlib: bool,75	/// Add string external variable.76	/// External variables are globally available so it is preferred77	/// to use top level arguments whenever it's possible.78	/// If [=data] is not set then it will be read from `name` env variable.79	/// Can be accessed from code via `std.extVar("name")`.80	#[clap(long, short = 'V', name = "name[=var data]", number_of_values = 1)]81	ext_str: Vec<ExtStr>,82	/// Read string external variable from file.83	/// See also `--ext-str`84	#[clap(long, name = "name=var path", number_of_values = 1)]85	ext_str_file: Vec<ExtFile>,86	/// Add external variable from code.87	/// See also `--ext-str`88	#[clap(long, name = "name[=var source]", number_of_values = 1)]89	ext_code: Vec<ExtStr>,90	/// Read string external variable from file.91	/// See also `--ext-str`92	#[clap(long, name = "name=var code path", number_of_values = 1)]93	ext_code_file: Vec<ExtFile>,94}95impl StdOpts {96	pub fn context_initializer(&self) -> Result<Option<ContextInitializer>> {97		if self.no_stdlib {98			return Ok(None);99		}100		let ctx = ContextInitializer::new(PathResolver::new_cwd_fallback());101		for ext in &self.ext_str {102			ctx.settings_mut().ext_vars.insert(103				ext.name.as_str().into(),104				TlaArg::String(ext.value.as_str().into()),105			);106		}107		for ext in &self.ext_str_file {108			ctx.settings_mut().ext_vars.insert(109				ext.name.as_str().into(),110				TlaArg::ImportStr(ext.path.clone()),111			);112		}113		for ext in &self.ext_code {114			ctx.settings_mut().ext_vars.insert(115				ext.name.as_str().into(),116				TlaArg::InlineCode(ext.value.clone()),117			);118		}119		for ext in &self.ext_code_file {120			ctx.settings_mut()121				.ext_vars122				.insert(ext.name.as_str().into(), TlaArg::Import(ext.path.clone()));123		}124		Ok(Some(ctx))125	}126}