Repository: djc/askama
Pull request #283 (2020-01-03 18:41:42)

Support char literals

djc: Great work, thanks! 

Patch:
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index 81f6ac9..9f60847 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -885,6 +885,7 @@ impl<'a> Generator<'a> {
             Expr::BoolLit(s) => self.visit_bool_lit(buf, s),
             Expr::NumLit(s) => self.visit_num_lit(buf, s),
             Expr::StrLit(s) => self.visit_str_lit(buf, s),
+            Expr::CharLit(s) => self.visit_char_lit(buf, s),
             Expr::Var(s) => self.visit_var(buf, s),
             Expr::Path(ref path) => self.visit_path(buf, path),
             Expr::Array(ref elements) => self.visit_array(buf, elements),
@@ -918,6 +919,7 @@ impl<'a> Generator<'a> {
                 expr_buf.write("&");
                 self.visit_str_lit(&mut expr_buf, s)
             }
+            MatchVariant::CharLit(s) => self.visit_char_lit(&mut expr_buf, s),
             MatchVariant::NumLit(s) => self.visit_num_lit(&mut expr_buf, s),
             MatchVariant::Name(s) => {
                 expr_buf.write(s);
@@ -937,6 +939,7 @@ impl<'a> Generator<'a> {
         let wrapped = match *param {
             MatchParameter::NumLit(s) => self.visit_num_lit(&mut expr_buf, s),
             MatchParameter::StrLit(s) => self.visit_str_lit(&mut expr_buf, s),
+            MatchParameter::CharLit(s) => self.visit_char_lit(&mut expr_buf, s),
             MatchParameter::Name(s) => {
                 expr_buf.write(s);
                 DisplayWrap::Unwrapped
@@ -1155,6 +1158,11 @@ impl<'a> Generator<'a> {
         DisplayWrap::Unwrapped
     }
 
+    fn visit_char_lit(&mut self, buf: &mut Buffer, s: &str) -> DisplayWrap {
+        buf.write(&format!("'{}'", s));
+        DisplayWrap::Unwrapped
+    }
+
     fn visit_num_lit(&mut self, buf: &mut Buffer, s: &str) -> DisplayWrap {
         buf.write(s);
         DisplayWrap::Unwrapped
diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs
index e483ff7..91c2d6a 100644
--- a/askama_derive/src/parser.rs
+++ b/askama_derive/src/parser.rs
@@ -15,6 +15,7 @@ pub enum Expr<'a> {
     BoolLit(&'a str),
     NumLit(&'a str),
     StrLit(&'a str),
+    CharLit(&'a str),
     Var(&'a str),
     Path(Vec<&'a str>),
     Array(Vec<Expr<'a>>),
@@ -35,6 +36,7 @@ pub enum MatchVariant<'a> {
     Name(&'a str),
     NumLit(&'a str),
     StrLit(&'a str),
+    CharLit(&'a str),
 }
 
 #[derive(Debug)]
@@ -42,6 +44,7 @@ pub enum MatchParameter<'a> {
     Name(&'a str),
     NumLit(&'a str),
     StrLit(&'a str),
+    CharLit(&'a str),
 }
 
 #[derive(Debug)]
@@ -266,6 +269,24 @@ fn param_str_lit(i: &[u8]) -> IResult<&[u8], MatchParameter> {
     })(i)
 }
 
+fn expr_char_lit(i: &[u8]) -> IResult<&[u8], Expr> {
+    map(delimited(char('\''), take_until("'"), char('\'')), |s| {
+        Expr::CharLit(str::from_utf8(s).unwrap())
+    })(i)
+}
+
+fn variant_char_lit(i: &[u8]) -> IResult<&[u8], MatchVariant> {
+    map(delimited(char('\''), is_not("'"), char('\'')), |s| {
+        MatchVariant::CharLit(str::from_utf8(s).unwrap())
+    })(i)
+}
+
+fn param_char_lit(i: &[u8]) -> IResult<&[u8], MatchParameter> {
+    map(delimited(char('\''), is_not("'"), char('\'')), |s| {
+        MatchParameter::CharLit(str::from_utf8(s).unwrap())
+    })(i)
+}
+
 fn expr_var(i: &[u8]) -> IResult<&[u8], Expr> {
     map(identifier, |s| Expr::Var(s))(i)
 }
@@ -405,6 +426,7 @@ fn expr_single(i: &[u8]) -> IResult<&[u8], Expr> {
         expr_bool_lit,
         expr_num_lit,
         expr_str_lit,
+        expr_char_lit,
         expr_path,
         expr_rust_macro,
         expr_array_lit,
@@ -414,11 +436,17 @@ fn expr_single(i: &[u8]) -> IResult<&[u8], Expr> {
 }
 
 fn match_variant(i: &[u8]) -> IResult<&[u8], MatchVariant> {
-    alt((variant_path, variant_name, variant_num_lit, variant_str_lit))(i)
+    alt((
+        variant_path,
+        variant_name,
+        variant_num_lit,
+        variant_str_lit,
+        variant_char_lit,
+    ))(i)
 }
 
 fn match_parameter(i: &[u8]) -> IResult<&[u8], MatchParameter> {
-    alt((param_name, param_num_lit, param_str_lit))(i)
+    alt((param_name, param_num_lit, param_str_lit, param_char_lit))(i)
 }
 
 fn match_named_parameter(i: &[u8]) -> IResult<&[u8], (&str, Option<MatchParameter>)> {


Test patch:
diff --git a/testing/templates/literals.html b/testing/templates/literals.html
index 9d973bb..b5fb472 100644
--- a/testing/templates/literals.html
+++ b/testing/templates/literals.html
@@ -1,3 +1,4 @@
+{{ 'a' }}
 {{ "a" }}
 {{ true }}
 {{ false }}
diff --git a/testing/templates/match-literal-char.html b/testing/templates/match-literal-char.html
new file mode 100644
index 0000000..2ff255d
--- /dev/null
+++ b/testing/templates/match-literal-char.html
@@ -0,0 +1,8 @@
+{% match item %}
+{% when 'a' %}
+Found literal a
+{% when 'b' %}
+Found literal b
+{% else %}
+Else found {{item}}
+{% endmatch %}
diff --git a/testing/tests/matches.rs b/testing/tests/matches.rs
index 3e6d636..811f3ce 100644
--- a/testing/tests/matches.rs
+++ b/testing/tests/matches.rs
@@ -47,6 +47,21 @@ fn test_match_literal() {
     assert_eq!(s.render().unwrap(), "\n\nElse found qux\n");
 }
 
+#[derive(Template)]
+#[template(path = "match-literal-char.html")]
+struct MatchLitCharTemplate {
+    item: char,
+}
+
+#[test]
+fn test_match_literal_char() {
+    let s = MatchLitCharTemplate { item: 'b' };
+    assert_eq!(s.render().unwrap(), "\n\nFound literal b\n");
+
+    let s = MatchLitCharTemplate { item: 'c' };
+    assert_eq!(s.render().unwrap(), "\n\nElse found c\n");
+}
+
 #[derive(Template)]
 #[template(path = "match-literal-num.html")]
 struct MatchLitNumTemplate {
diff --git a/testing/tests/simple.rs b/testing/tests/simple.rs
index 6dbfcfb..53f1122 100644
--- a/testing/tests/simple.rs
+++ b/testing/tests/simple.rs
@@ -119,7 +119,7 @@ struct LiteralsTemplate {}
 #[test]
 fn test_literals() {
     let s = LiteralsTemplate {};
-    assert_eq!(s.render().unwrap(), "a\ntrue\nfalse");
+    assert_eq!(s.render().unwrap(), "a\na\ntrue\nfalse");
 }
 
 struct Holder {