use crate::common::*; use target; use Function::*; pub(crate) enum Function { Nullary(fn(&FunctionContext) -> Result), Unary(fn(&FunctionContext, &str) -> Result), Binary(fn(&FunctionContext, &str, &str) -> Result), } lazy_static! { pub(crate) static ref TABLE: BTreeMap<&'static str, Function> = vec![ ("arch", Nullary(arch)), ("os", Nullary(os)), ("os_family", Nullary(os_family)), ("justfile_directory", Nullary(justfile_directory)), ("justfile", Nullary(justfile)), ("invocation_directory", Nullary(invocation_directory)), ("env_var", Unary(env_var)), ("env_var_or_default", Binary(env_var_or_default)), ] .into_iter() .collect(); } impl Function { pub(crate) fn argc(&self) -> usize { match *self { Nullary(_) => 0, Unary(_) => 1, Binary(_) => 2, } } } fn arch(_context: &FunctionContext) -> Result { Ok(target::arch().to_string()) } fn os(_context: &FunctionContext) -> Result { Ok(target::os().to_string()) } fn os_family(_context: &FunctionContext) -> Result { Ok(target::os_family().to_string()) } fn invocation_directory(context: &FunctionContext) -> Result { Platform::to_shell_path( &context.search.working_directory, context.invocation_directory, ) .map_err(|e| format!("Error getting shell path: {}", e)) } fn justfile(context: &FunctionContext) -> Result { context .search .justfile .to_str() .map(str::to_owned) .ok_or_else(|| { format!( "Justfile path is not valid unicode: {}", context.search.justfile.to_string_lossy() ) }) } fn justfile_directory(context: &FunctionContext) -> Result { let justfile_directory = context.search.justfile.parent().ok_or_else(|| { format!( "Could not resolve justfile directory. Justfile `{}` had no parent.", context.search.justfile.display() ) })?; justfile_directory .to_str() .map(str::to_owned) .ok_or_else(|| { format!( "Justfile directory is not valid unicode: {}", justfile_directory.to_string_lossy() ) }) } fn env_var(context: &FunctionContext, key: &str) -> Result { use std::env::VarError::*; if let Some(value) = context.dotenv.get(key) { return Ok(value.clone()); } match env::var(key) { Err(NotPresent) => Err(format!("environment variable `{}` not present", key)), Err(NotUnicode(os_string)) => Err(format!( "environment variable `{}` not unicode: {:?}", key, os_string )), Ok(value) => Ok(value), } } fn env_var_or_default( context: &FunctionContext, key: &str, default: &str, ) -> Result { if let Some(value) = context.dotenv.get(key) { return Ok(value.clone()); } use std::env::VarError::*; match env::var(key) { Err(NotPresent) => Ok(default.to_string()), Err(NotUnicode(os_string)) => Err(format!( "environment variable `{}` not unicode: {:?}", key, os_string )), Ok(value) => Ok(value), } }