summaryrefslogtreecommitdiff
path: root/src/eval/args.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval/args.rs')
-rw-r--r--src/eval/args.rs39
1 files changed, 36 insertions, 3 deletions
diff --git a/src/eval/args.rs b/src/eval/args.rs
index d71cc374..b89ee61f 100644
--- a/src/eval/args.rs
+++ b/src/eval/args.rs
@@ -2,7 +2,9 @@
use std::mem;
-use super::*;
+use super::{Convert, RefKey, ValueDict};
+use crate::layout::LayoutContext;
+use crate::syntax::{SpanWith, Spanned};
/// A wrapper around a dictionary value that simplifies argument parsing in
/// functions.
@@ -21,14 +23,44 @@ impl Args {
{
self.0.v.remove(key).and_then(|entry| {
let span = entry.value.span;
- let (t, diag) = T::convert(entry.value);
+ let (result, diag) = T::convert(entry.value);
if let Some(diag) = diag {
ctx.f.diags.push(diag.span_with(span))
}
- t.ok()
+ result.ok()
})
}
+ /// This is the same as [`get`], except that it generates an error about a
+ /// missing argument with the given `name` if the key does not exist.
+ ///
+ /// [`get`]: #method.get
+ pub fn need<'a, K, T>(
+ &mut self,
+ ctx: &mut LayoutContext,
+ key: K,
+ name: &str,
+ ) -> Option<T>
+ where
+ K: Into<RefKey<'a>>,
+ T: Convert,
+ {
+ match self.0.v.remove(key) {
+ Some(entry) => {
+ let span = entry.value.span;
+ let (result, diag) = T::convert(entry.value);
+ if let Some(diag) = diag {
+ ctx.f.diags.push(diag.span_with(span))
+ }
+ result.ok()
+ }
+ None => {
+ ctx.f.diags.push(error!(self.0.span, "missing argument: {}", name));
+ None
+ }
+ }
+ }
+
/// Retrieve and remove the first matching positional argument.
pub fn find<T>(&mut self) -> Option<T>
where
@@ -104,6 +136,7 @@ impl Args {
#[cfg(test)]
mod tests {
+ use super::super::{Dict, SpannedEntry, Value};
use super::*;
fn entry(value: Value) -> SpannedEntry<Value> {