diff options
Diffstat (limited to 'src/eval/args.rs')
| -rw-r--r-- | src/eval/args.rs | 39 |
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> { |
