git.delta.rocks / jrsonnet / refs/commits / 0a23a80af017

difftreelog

source

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