diff options
-rw-r--r-- | src/makefile/functions.rs | 150 |
1 files changed, 63 insertions, 87 deletions
diff --git a/src/makefile/functions.rs b/src/makefile/functions.rs index abd1abb..f35708b 100644 --- a/src/makefile/functions.rs +++ b/src/makefile/functions.rs @@ -1,4 +1,6 @@ use std::cell::RefCell; +use std::env; +use std::process::{Command, Stdio}; use std::rc::Rc; use eyre::{bail, Result}; @@ -52,19 +54,19 @@ pub fn expand_call( // foreach "foreach" => { assert_eq!(args.len(), 3); - foreach::foreach(macros, &args[0], &args[1], &args[2]) + foreach(macros, &args[0], &args[1], &args[2]) } // call "call" => { assert!(!args.is_empty()); - call::call(macros, args.iter()) + call(macros, args.iter()) } // eval "eval" => { assert_eq!(args.len(), 1); - let should_eval = eval::eval(macros, &args[0])?; + let should_eval = eval(macros, &args[0])?; if let Some(to_eval) = to_eval { to_eval.borrow_mut().push(should_eval); } else { @@ -75,13 +77,13 @@ pub fn expand_call( "origin" => { assert_eq!(args.len(), 1); - origin::origin(macros, &args[0]) + origin(macros, &args[0]) } // shell "shell" => { assert_eq!(args.len(), 1); - shell::shell(macros, &args[0]) + shell(macros, &args[0]) } // fallback @@ -239,98 +241,72 @@ mod conditional { } } -// foreach -mod foreach { - use super::*; - - pub fn foreach( - macros: &MacroSet, - var: &TokenString, - list: &TokenString, - text: &TokenString, - ) -> Result<String> { - let var = macros.expand(var)?; - let list = macros.expand(list)?; - let words = list.split_whitespace(); - - let mut macros = macros.with_overlay(); - let results = words - .map(|word| { - macros.set(var.clone(), MacroSource::File, TokenString::text(word)); - macros.expand(text) - }) - .collect::<Result<Vec<_>, _>>()?; - Ok(results.join(" ")) - } +pub fn foreach( + macros: &MacroSet, + var: &TokenString, + list: &TokenString, + text: &TokenString, +) -> Result<String> { + let var = macros.expand(var)?; + let list = macros.expand(list)?; + let words = list.split_whitespace(); + + let mut macros = macros.with_overlay(); + let results = words + .map(|word| { + macros.set(var.clone(), MacroSource::File, TokenString::text(word)); + macros.expand(text) + }) + .collect::<Result<Vec<_>, _>>()?; + Ok(results.join(" ")) } -// call -mod call { - use super::*; +pub fn call<'a>(macros: &MacroSet, args: impl Iterator<Item = &'a TokenString>) -> Result<String> { + let args = args + .map(|arg| macros.expand(arg)) + .collect::<Result<Vec<_>, _>>()?; + let function = args[0].clone(); + // TODO if function is a builtin, call the builtin instead - pub fn call<'a>( - macros: &MacroSet, - args: impl Iterator<Item = &'a TokenString>, - ) -> Result<String> { - let args = args - .map(|arg| macros.expand(arg)) - .collect::<Result<Vec<_>, _>>()?; - let function = args[0].clone(); - - let mut macros = macros.with_overlay(); - for (i, x) in args.into_iter().enumerate() { - macros.set(i.to_string(), MacroSource::File, TokenString::text(x)); - } - macros.expand(&TokenString::r#macro(function)) + let mut macros = macros.with_overlay(); + for (i, x) in args.into_iter().enumerate() { + macros.set(i.to_string(), MacroSource::File, TokenString::text(x)); } + macros.expand(&TokenString::r#macro(function)) } -mod eval { - use super::*; - - pub fn eval(macros: &MacroSet, arg: &TokenString) -> Result<String> { - macros.expand(arg) - } +// TODO consider bringing eval logic in here since we put the Vec in MacroSet IIRC +pub fn eval(macros: &MacroSet, arg: &TokenString) -> Result<String> { + macros.expand(arg) } -mod origin { - use super::*; - - pub fn origin(macros: &MacroSet, variable: &TokenString) -> Result<String> { - let variable = macros.expand(variable)?; - Ok(macros.origin(&variable).to_owned()) - } +pub fn origin(macros: &MacroSet, variable: &TokenString) -> Result<String> { + let variable = macros.expand(variable)?; + Ok(macros.origin(&variable).to_owned()) } -mod shell { - use super::*; - - use std::env; - use std::process::{Command, Stdio}; - - pub fn shell(macros: &MacroSet, command: &TokenString) -> Result<String> { - // TODO bring this in from command_line - let command = macros.expand(command)?; - let (program, args) = if cfg!(windows) { - let cmd = env::var("COMSPEC").unwrap_or_else(|_| "cmd.exe".into()); - let args = vec!["/c", &command]; - (cmd, args) - } else { - let sh = env::var("SHELL").unwrap_or_else(|_| "/bin/sh".into()); - let args = vec!["-e", "-c", &command]; - (sh, args) - }; - let result = Command::new(program) - .args(args) - .stderr(Stdio::inherit()) - .output()?; - let status = result.status; - // TODO set .SHELLSTATUS - Ok(String::from_utf8(result.stdout)? - .replace("\r\n", "\n") - .trim_end_matches('\n') - .replace("\n", " ")) - } +pub fn shell(macros: &MacroSet, command: &TokenString) -> Result<String> { + // TODO bring this in from command_line + let command = macros.expand(command)?; + let (program, args) = if cfg!(windows) { + let cmd = env::var("COMSPEC").unwrap_or_else(|_| "cmd.exe".into()); + let args = vec!["/c", &command]; + (cmd, args) + } else { + let sh = env::var("SHELL").unwrap_or_else(|_| "/bin/sh".into()); + let args = vec!["-e", "-c", &command]; + (sh, args) + }; + let result = Command::new(program) + .args(args) + .stderr(Stdio::inherit()) + .output()?; + let status = result.status; + // TODO set .SHELLSTATUS + Ok(String::from_utf8(result.stdout)? + .replace("\r\n", "\n") + .trim_end_matches('\n') + .replace("\n", " ")) } #[cfg(test)] |