Skip to content

Commit

Permalink
add support for printf and call
Browse files Browse the repository at this point in the history
resolve #2
  • Loading branch information
fiji-flo committed Dec 10, 2017
1 parent e1f4a76 commit 10da6e5
Show file tree
Hide file tree
Showing 6 changed files with 736 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "gtmpl"
version = "0.2.1"
version = "0.2.2"
authors = ["Florian Merz <flomerz@gmail.com>"]
description = "The Golang Templating Language for Rust"
license = "MIT"
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

```toml
[dependencies]
gtmpl = "0.2.0"
gtmpl = "0.2.2"
```

* [gtmpl at crates.io](https://crates.io/crate/gtmpl)
Expand All @@ -24,7 +24,8 @@ This is work in progress. Currently the following features are not supported:

* complex numbers
* the following functions have not been implemented:
* `html`, `js`, `call` and `printf`
* `html`, `js`
* `printf` is not yet fully stable, but should support all *sane* input

## Usage

Expand Down
73 changes: 73 additions & 0 deletions src/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extern crate percent_encoding;
use self::percent_encoding::{DEFAULT_ENCODE_SET, utf8_percent_encode};

use utils::is_true;
use printf::sprintf;

lazy_static! {
/// Map of all builtin function.
Expand All @@ -29,7 +30,9 @@ lazy_static! {
m.insert("urlquery".to_owned(), urlquery as Func);
m.insert("print".to_owned(), print as Func);
m.insert("println".to_owned(), println as Func);
m.insert("printf".to_owned(), printf as Func);
m.insert("index".to_owned(), index as Func);
m.insert("call".to_owned(), call as Func);
m
};
}
Expand Down Expand Up @@ -227,6 +230,45 @@ pub fn len(args: &[Arc<Any>]) -> Result<Arc<Any>, String> {
Ok(varc!(len))
}

/// Returns the result of calling the first argument, which
/// must be a function, with the remaining arguments as parameters.
///
/// # Example
/// ```
/// #[macro_use]
/// extern crate gtmpl;
/// extern crate gtmpl_value;
/// use gtmpl_value::Function;
/// use gtmpl::{template, Value};
///
/// fn main() {
/// gtmpl_fn!(
/// fn add(a: u64, b: u64) -> Result<u64, String> {
/// Ok(a + b)
/// });
/// let equal = template(r#"{{ call . 1 2 }}"#, Value::Function(Function { f: add }));
/// assert_eq!(&equal.unwrap(), "3");
/// }
/// ```
pub fn call(args: &[Arc<Any>]) -> Result<Arc<Any>, String> {
let vals: Vec<&Value> = args.iter()
.map(|arg| {
arg.downcast_ref::<Value>().ok_or_else(|| {
String::from("print requires arguemnts of type Value")
})
})
.collect::<Result<Vec<_>, String>>()?;
if vals.is_empty() {
Err(String::from("call requires at least on argument"))
} else if let Value::Function(ref f) = *vals[0] {
(f.f)(&args[1..])
} else {
Err(String::from(
"call requires the first argument to be a function",
))
}
}

/// An implementation of golang's fmt.Sprint
///
/// Golang's Sprint formats using the default formats for its operands and returns the
Expand Down Expand Up @@ -309,6 +351,37 @@ pub fn println(args: &[Arc<Any>]) -> Result<Arc<Any>, String> {
Ok(varc!(s))
}

/// An implementation of golang's fmt.Sprintf
/// Limitations:
/// - float:
/// * `g`, `G`, and `b` are weired and not implement yet
/// - pretty sure there are more
///
/// # Example
/// ```
/// use gtmpl::template;
/// let equal = template(r#"{{ printf "%v %s %v" "Hello" . "!" }}"#, "world");
/// assert_eq!(&equal.unwrap(), "Hello world !");
/// ```
pub fn printf(args: &[Arc<Any>]) -> Result<Arc<Any>, String> {
let vals: Vec<&Value> = args.iter()
.map(|arg| {
arg.downcast_ref::<Value>().ok_or_else(|| {
String::from("print requires arguemnts of type Value")
})
})
.collect::<Result<Vec<_>, String>>()?;
if vals.is_empty() {
return Err("printf requires at least one argument".to_owned());
}
if let Value::String(ref s) = *vals[0] {
let s = sprintf(s, &vals[1..])?;
Ok(varc!(s))
} else {
Err("printf requires a format string".to_owned())
}
}

/// Returns the result of indexing its first argument by the
/// following arguments. Thus "index x 1 2 3" is, in Go syntax,
/// x[1][2][3]. Each indexed item must be a map, slice or array.
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub mod funcs;
mod template;
mod exec;
mod utils;
mod print_verb;
mod printf;

#[doc(inline)]
pub use template::Template;
Expand Down

0 comments on commit 10da6e5

Please sign in to comment.