summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/macro_processor/macro_processor.rs123
-rw-r--r--src/skaldpress/main.rs9
2 files changed, 127 insertions, 5 deletions
diff --git a/src/macro_processor/macro_processor.rs b/src/macro_processor/macro_processor.rs
index 2e8675f..b36783b 100644
--- a/src/macro_processor/macro_processor.rs
+++ b/src/macro_processor/macro_processor.rs
@@ -38,6 +38,12 @@ fn smp_builtin_define(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 1 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 1"),
+ ));
return Ok(macro_name.to_string());
}
let arg0 = smp.process_input(&args[0])?;
@@ -57,6 +63,12 @@ fn smp_builtin_ifdef(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 2 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 2"),
+ ));
return Ok(macro_name.to_string());
}
// We need to expand the first argument here as well, but we need to make the parser
@@ -77,6 +89,12 @@ fn smp_builtin_ifndef(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 2 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 2"),
+ ));
return Ok(macro_name.to_string());
}
// We need to expand the first argument here as well, but we need to make the parser
@@ -97,6 +115,12 @@ fn smp_builtin_ifeq(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 3 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 3"),
+ ));
return Ok(macro_name.to_string());
}
let arg0 = smp.process_input(&args[0])?;
@@ -117,6 +141,12 @@ fn smp_builtin_ifneq(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 3 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 3"),
+ ));
return Ok(macro_name.to_string());
}
let arg0 = smp.process_input(&args[0])?;
@@ -137,6 +167,12 @@ fn smp_builtin_include(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 1 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 1"),
+ ));
return Ok(macro_name.to_string());
}
let arg0 = smp.process_input(&args[0])?;
@@ -151,6 +187,12 @@ fn smp_builtin_include_verbatim(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 1 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 1"),
+ ));
return Ok(macro_name.to_string());
}
let arg0 = smp.process_input(&args[0])?;
@@ -164,6 +206,12 @@ fn smp_builtin_shell(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 1 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 1"),
+ ));
return Ok(macro_name.to_string());
}
let arg0 = smp.process_input(&args[0])?;
@@ -171,7 +219,15 @@ fn smp_builtin_shell(
match res {
Ok(output) => String::from_utf8(output.stdout)
.map_err(|e| SMPError::ShellCommandError(1, Box::new(e))),
- Err(_) => Ok(String::new()),
+ Err(e) => {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Error running shell command ({})", e),
+ ));
+ Ok(String::new())
+ }
}
}
@@ -182,6 +238,12 @@ fn smp_builtin_expr(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 1 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 1"),
+ ));
return Ok(macro_name.to_string());
}
@@ -189,11 +251,20 @@ fn smp_builtin_expr(
*arg = smp.process_input(&arg)?;
}
- let res = Command::new("expr").args(args).output();
+ let args = args.to_vec();
+ let res = Command::new("expr").args(args.clone()).output();
match res {
Ok(output) => String::from_utf8(output.stdout)
.map_err(|e| SMPError::ShellCommandError(1, Box::new(e))),
- Err(_) => Ok(String::new()),
+ Err(e) => {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ &args,
+ format!("Error running shell command ({})", e),
+ ));
+ Ok(String::new())
+ }
}
}
@@ -225,11 +296,27 @@ fn smp_builtin_format_time(
args: &mut [String],
) -> Result<String, SMPError> {
if args.len() < 2 {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Wrong number of arguments, expected at least 2"),
+ ));
return Ok(macro_name.to_string());
}
let timestamp = smp.process_input(&args[1])?;
- let dt = chrono::DateTime::parse_from_rfc3339(&timestamp)
- .map_err(|_| SMPError::UnknownError(87, None))?;
+ let dt = match chrono::DateTime::parse_from_rfc3339(&timestamp) {
+ Ok(dt) => dt,
+ Err(e) => {
+ smp.warnings
+ .push(MacroProcessorWarning::from_macro_invocation(
+ macro_name,
+ args,
+ format!("Could not parse datetime {} ({})", timestamp, e),
+ ));
+ return Ok(timestamp);
+ }
+ };
Ok(format!("{}", dt.format(&args[0])))
}
@@ -258,6 +345,29 @@ enum ParserState {
DNL,
}
+#[derive(Clone, Debug)]
+pub struct MacroProcessorWarning {
+ pub description: String,
+}
+
+impl MacroProcessorWarning {
+ pub fn new(description: String) -> Self {
+ MacroProcessorWarning { description }
+ }
+
+ pub fn from_macro_invocation(macro_name: &str, args: &[String], description: String) -> Self {
+ let mut desc = format!("{}(", macro_name);
+ for (i, arg) in args.iter().enumerate() {
+ desc.push_str(arg);
+ if i < (args.len() - 1) {
+ desc.push(',');
+ }
+ }
+ desc.push_str(&format!(") -> {}", description));
+ MacroProcessorWarning { description: desc }
+ }
+}
+
/// Defines a MacroProcessor object, with it's associated state
/// the state mostly includes the defined macros
#[derive(Clone)]
@@ -266,6 +376,8 @@ pub struct MacroProcessor {
pub macros: HashMap<String, MacroType>,
/// All macro invocations that has happened
pub macro_invocations: Vec<(String, Vec<String>)>,
+ /// Emitted warnings
+ pub warnings: Vec<MacroProcessorWarning>,
}
impl MacroProcessor {
@@ -273,6 +385,7 @@ impl MacroProcessor {
let mut smp = Self {
macros: HashMap::new(),
macro_invocations: Vec::new(),
+ warnings: Vec::new(),
};
smp.define_builtins();
smp
diff --git a/src/skaldpress/main.rs b/src/skaldpress/main.rs
index a4d40ee..9d68bac 100644
--- a/src/skaldpress/main.rs
+++ b/src/skaldpress/main.rs
@@ -113,6 +113,7 @@ fn sp_all_tagged_by(
"template",
&mut [args[1].clone(), file.content.clone()],
)?);
+ print_warnings(&smp_local);
}
Ok(out)
}
@@ -196,6 +197,12 @@ fn needs_recompilation(macro_processor: &MacroProcessor) -> bool {
false
}
+fn print_warnings(macro_processor: &MacroProcessor) {
+ for warning in &macro_processor.warnings {
+ println!(" \x1b[33m{}\x1b[0m", warning.description);
+ }
+}
+
/// Will attempt to compile a specific file, potentially storing some state about the file
fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, SkaldpressError> {
let extension = file_path.extension().unwrap_or(std::ffi::OsStr::new(""));
@@ -252,6 +259,7 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres
let file_content = macro_processor
.process_input(&file_content)
.map_err(|e| SkaldpressError::SMPError(SP_COMPILE_FILE_MACRO_PROCESS_ERROR, e))?;
+ print_warnings(&macro_processor);
return Ok(CompiledFile {
content: file_content,
metadata: map,
@@ -270,6 +278,7 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres
let (content, template_extension) =
wrap_template(&mut macro_processor, &template_file, &file_content, opts)?;
+ print_warnings(&macro_processor);
Ok(CompiledFile {
content,
metadata: map,