[california] Allow for quotes to escape Quick Add text: Bug #732132



commit 0319071807b2454c776191ae491bd8cfb6350263
Author: Jim Nelson <jim yorba org>
Date:   Fri Aug 15 12:52:14 2014 -0700

    Allow for quotes to escape Quick Add text: Bug #732132

 src/component/component-details-parser.vala |   34 +++++++++++++++-----
 src/tests/tests-quick-add.vala              |   45 +++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 8 deletions(-)
---
diff --git a/src/component/component-details-parser.vala b/src/component/component-details-parser.vala
index 10b42e1..fe57080 100644
--- a/src/component/component-details-parser.vala
+++ b/src/component/component-details-parser.vala
@@ -156,18 +156,36 @@ public class DetailsParser : BaseObject {
         }
         
         // tokenize the string and arrange as a stack for the parser
-        string[] tokenized = String.reduce_whitespace(this.details).split(" ");
-        Gee.LinkedList<Token> list = new Gee.LinkedList<Token>();
-        foreach (string token in tokenized) {
-            if (!String.is_empty(token))
-                list.add(new Token(token));
-        }
-        
-        stack = new Collection.LookaheadStack<Token>(list);
+        stack = new Collection.LookaheadStack<Token>(tokenize());
         
         parse();
     }
     
+    Gee.List<Token> tokenize() {
+        Gee.List<Token> tokens = new Gee.ArrayList<Token>();
+        
+        StringBuilder builder = new StringBuilder();
+        bool in_quotes = false;
+        from_string(details).iterate(ch => {
+            // switch state but include quotes in token
+            if (ch == '"')
+                in_quotes = !in_quotes;
+            
+            if (!ch.isspace() || in_quotes) {
+                builder.append_unichar(ch);
+            } else if (!String.is_empty(builder.str)) {
+                tokens.add(new Token(builder.str));
+                builder = new StringBuilder();
+            }
+        });
+        
+        // get any trailing text
+        if (!String.is_empty(builder.str))
+            tokens.add(new Token(builder.str));
+        
+        return tokens;
+    }
+    
     private void parse() {
         for (;;) {
             Token? token = stack.pop();
diff --git a/src/tests/tests-quick-add.vala b/src/tests/tests-quick-add.vala
index 371cd66..19e6b3e 100644
--- a/src/tests/tests-quick-add.vala
+++ b/src/tests/tests-quick-add.vala
@@ -55,6 +55,9 @@ private class QuickAdd : UnitTest.Harness {
         add_case("time-range-no-meridiem", time_range_no_meridiem);
         add_case("atsign-location", atsign_location);
         add_case("atsign-time", atsign_time);
+        add_case("quoted", quoted);
+        add_case("open-quoted", open_quoted);
+        add_case("quoted-atsign", quoted_atsign);
     }
     
     protected override void setup() throws Error {
@@ -632,6 +635,48 @@ private class QuickAdd : UnitTest.Harness {
             && parser.event.exact_time_span.end_exact_time.minute == 0
             && parser.event.exact_time_span.get_date_span().equal_to(Calendar.System.today.to_date_span());
     }
+    
+    private bool quoted(out string? dump) throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser(
+            "\"Live at Budokon\" at The Roxy 7pm", null);
+        
+        dump = parser.event.source;
+        
+        return parser.event.summary == "\"Live at Budokon\" at The Roxy"
+            && parser.event.location == "The Roxy"
+            && !parser.event.is_all_day
+            && parser.event.exact_time_span.start_exact_time.hour == 19
+            && parser.event.exact_time_span.start_exact_time.minute == 0
+            && parser.event.exact_time_span.end_exact_time.hour == 20
+            && parser.event.exact_time_span.end_exact_time.minute == 0
+            && parser.event.exact_time_span.get_date_span().equal_to(Calendar.System.today.to_date_span());
+    }
+    
+    private bool open_quoted(out string? dump) throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser(
+            "\"Live at Budokon", null);
+        
+        dump = parser.event.source;
+        
+        return parser.event.summary == "\"Live at Budokon"
+            && parser.event.location == null;
+    }
+    
+    private bool quoted_atsign(out string? dump) throws Error {
+        Component.DetailsParser parser = new Component.DetailsParser(
+            "\"Live at Budokon\" @ The Roxy 7pm", null);
+        
+        dump = parser.event.source;
+        
+        return parser.event.summary == "\"Live at Budokon\""
+            && parser.event.location == "The Roxy"
+            && !parser.event.is_all_day
+            && parser.event.exact_time_span.start_exact_time.hour == 19
+            && parser.event.exact_time_span.start_exact_time.minute == 0
+            && parser.event.exact_time_span.end_exact_time.hour == 20
+            && parser.event.exact_time_span.end_exact_time.minute == 0
+            && parser.event.exact_time_span.get_date_span().equal_to(Calendar.System.today.to_date_span());
+    }
 }
 
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]