diff --git a/astrid/.classpath b/astrid/.classpath
index 40651759a..9900acf07 100644
--- a/astrid/.classpath
+++ b/astrid/.classpath
@@ -28,5 +28,7 @@
+
+
diff --git a/astrid/astrid.launch b/astrid/astrid.launch
index 7b969a0ea..cb174a74d 100644
--- a/astrid/astrid.launch
+++ b/astrid/astrid.launch
@@ -6,7 +6,7 @@
-
+
diff --git a/astrid/libs/jchronic-0.2.3.jar b/astrid/libs/jchronic-0.2.3.jar
new file mode 100644
index 000000000..c0f15a32a
Binary files /dev/null and b/astrid/libs/jchronic-0.2.3.jar differ
diff --git a/astrid/src/com/todoroo/astrid/service/TaskService.java b/astrid/src/com/todoroo/astrid/service/TaskService.java
index 41cb563c4..2bf937ec4 100644
--- a/astrid/src/com/todoroo/astrid/service/TaskService.java
+++ b/astrid/src/com/todoroo/astrid/service/TaskService.java
@@ -1,8 +1,6 @@
package com.todoroo.astrid.service;
import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import org.weloveastrid.rmilk.data.MilkTaskFields;
@@ -27,9 +25,10 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gcal.GCalHelper;
import com.todoroo.astrid.gtasks.GtasksMetadata;
import com.todoroo.astrid.opencrx.OpencrxCoreUtils;
-import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.producteev.sync.ProducteevTask;
import com.todoroo.astrid.tags.TagService;
+import com.todoroo.astrid.utility.TitleParser;
+
/**
* Service layer for {@link Task}-centered activities.
@@ -350,37 +349,11 @@ public class TaskService {
@SuppressWarnings("nls")
public static void parseQuickAddMarkup(Task task, ArrayList tags) {
String title = task.getValue(Task.TITLE);
+ TitleParser parse = new TitleParser(task, tags);
- Pattern tagPattern = Pattern.compile("(\\s|^)#([^\\s]+)");
- Pattern contextPattern = Pattern.compile("(\\s|^)(@[^\\s]+)");
- Pattern importancePattern = Pattern.compile("(\\s|^)!(\\d)(\\s|$)");
- while(true) {
- Matcher m = tagPattern.matcher(title);
- if(m.find()) {
- tags.add(m.group(2));
- } else {
- m = contextPattern.matcher(title);
- if(m.find()) {
- tags.add(m.group(2));
- } else {
- m = importancePattern.matcher(title);
- if(m.find()) {
- int value = Integer.parseInt(m.group(2));
- // not in producteev world: !1 to !4 => importance 3 to 0
- int importance = Math.max(Task.IMPORTANCE_MOST, Task.IMPORTANCE_LEAST + 1 - value);
- // in the producteev world, !1 to !4 => importance 4 to 1
- if(ProducteevUtilities.INSTANCE.isLoggedIn() || OpencrxCoreUtils.INSTANCE.isLoggedIn())
- importance++;
-
- task.setValue(Task.IMPORTANCE, importance);
- } else
- break;
- }
- }
- title = title.substring(0, m.start()) + title.substring(m.end());
- }
- task.setValue(Task.TITLE, title.trim());
}
+
+
}
diff --git a/astrid/src/com/todoroo/astrid/utility/TitleParser.java b/astrid/src/com/todoroo/astrid/utility/TitleParser.java
new file mode 100644
index 000000000..29fa8ddea
--- /dev/null
+++ b/astrid/src/com/todoroo/astrid/utility/TitleParser.java
@@ -0,0 +1,257 @@
+package com.todoroo.astrid.utility;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.mdimension.jchronic.Chronic;
+import com.todoroo.astrid.data.Task;
+
+
+public class TitleParser {
+
+ HashMap results;
+ Task task;
+ ArrayList tags;
+
+ public TitleParser(Task task, ArrayList tags){
+ this.task = task;
+ this.tags = tags;
+ runAllHelpers();
+ }
+
+ public Task getTask(){
+ return task;
+ }
+
+ private void runAllHelpers(){
+ priorityListHelper(task, results, tags);
+ dayHelper(task, results, tags);
+ dateHelper(task, results, tags);
+ timeHelper(task, results, tags);
+ repeatHelper(task, results, tags);
+ }
+
+ private static int str_to_priority(String priority_str) {
+ int priority = Task.IMPORTANCE_DO_OR_DIE;
+ if (priority_str.equals ("0") || priority_str.equals ("!0"))
+ priority = Task.IMPORTANCE_NONE;
+ if (priority_str.equals ("!") || priority_str.equals ("!1"))
+ priority = Task.IMPORTANCE_SHOULD_DO;
+ if (priority_str.equals("!!") || priority_str.equals ("!2"))
+ priority = Task.IMPORTANCE_MUST_DO;
+ return priority;
+ }
+
+ private static void priorityListHelper(Task task, HashMap map, ArrayList tags) {
+ String inputText = task.getValue(Task.TITLE);
+
+ Pattern importancePattern = Pattern.compile("(.*)(^|[^\\w!])(!+|0|!\\d)($|[^\\w!])(.*)");
+ Pattern tagPattern = Pattern.compile("(\\s|^)#([^\\s]+)");
+ Pattern contextPattern = Pattern.compile("(\\s|^)(@[^\\s]+)");
+
+ while(true) {
+ Matcher m = tagPattern.matcher(inputText);
+ if(m.find()) {
+ tags.add(m.group(2));
+ } else {
+ m = contextPattern.matcher(inputText);
+ if(m.find()) {
+ tags.add(m.group(2));
+ }else{
+ m = importancePattern.matcher(inputText);
+ if(m.find()) {
+ map.put("title", m.group(1)); //make task list without !!
+
+ map.put("priority", str_to_priority(m.group(3)));
+ task.setValue(Task.IMPORTANCE, str_to_priority(m.group(3)));
+
+ } else
+ break;
+ }
+ }
+ inputText = inputText.substring(0, m.start()) + inputText.substring(m.end());
+ }
+ task.setValue(Task.TITLE, inputText.trim());
+ }
+
+ private static void dayHelper(Task task, HashMap map, ArrayList tags) {
+ String inputText = task.getValue(Task.TITLE);
+ String[] dates = {
+ "(?i)\\b(today)\\b",
+ "(?i)\\b(tomorrow)\\b",
+ "(?i)\\b(mon(day\\b|\\.))",
+ "(?i)\\b(tues(day\\b|\\.))",
+ "(?i)\\b(wed(nesday\\b|\\.))",
+ "(?i)\\b(thurs(day\\b|\\.))",
+ "(?i)\\b(fri(day\\b|\\.))",
+ "(?i)\\b(sat(urday\\b|\\.))",
+ "(?i)\\b(sun(day\\b|\\.))",
+ "(?i)\\b(next (month|week|year))\\b" };
+
+ for (String date : dates){
+ Pattern pattern = Pattern.compile(date);
+ Matcher m = pattern.matcher(inputText);
+
+ if (m.find()) {
+ Calendar cal = Chronic.parse(m.group(0)).getBeginCalendar();
+ map.put("date", cal);
+ long time = cal.getTime().getTime();
+ task.setValue(Task.DUE_DATE, time);
+
+ }
+ }
+ }
+
+ private static void dateHelper(Task task, HashMap map, ArrayList tags) {
+ String inputText = task.getValue(Task.TITLE);
+ String ds = "3[0-1]|[0-2]?[0-9]";
+ String[] dates = {
+ "\\b(1?[1-9](\\/|-)(3[0-1]|[0-2]?[0-9])($|\\s|\\/|-))",
+ "\\b(jan(uary)?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(feb(ruary)?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(mar(ch)?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(apr(il)?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(may)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(june?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(july?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(aug(ust)?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(sep(tember)?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(oct(ober)?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(nov(ember)?)(\\s(3[0-1]|[0-2]?[0-9]))?",
+ "\\b(dec(ember)?)(\\s(3[0-1]|[0-2]?[0-9]))?"
+ };
+ for (String date:dates) {
+ Pattern pattern = Pattern.compile(date);
+ Matcher m = pattern.matcher(inputText);
+ //if (m.find()) {
+ if (m.find() && map.get("day")== null){
+ Calendar cal = Chronic.parse(m.group(0)).getBeginCalendar();
+ Calendar today = Calendar.getInstance();
+ if (today.get(Calendar.MONTH) - cal.get(Calendar.MONTH) > 1){ //if more than a month in the past
+ cal.set(cal.get(Calendar.YEAR)+1, cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));
+ }
+ map.put("day", cal);
+ }
+ }
+ }
+ private static void timeHelper(Task task, HashMap map, ArrayList tags) {
+ String inputText = task.getValue(Task.TITLE);
+ String[] times = {
+ //[time] am/pm
+ "(?i)\\b((i?)\\d.* ?[ap]\\.?m\\.?)\\b",
+ //army time
+ "(?i)\\b([0-2]?[0-9]:[0-5][0-9])\\b",
+ //at [int]
+ "(?i)\\bat ([01]?\\d)($|\\D($|\\D))",
+ //[int] o'clock
+ "(?i)\\b([01]?\\d ?o'? ?clock)\\b"
+ };
+ for (String time:times){
+ Pattern pattern = Pattern.compile(time);
+ Matcher m = pattern.matcher(inputText);
+ if (m.find()){
+ map.put("time", Chronic.parse(m.group(1)).getBeginCalendar());
+ }
+ }
+ HashMap dayTimes = new HashMap();
+ dayTimes.put("(?i)\\bafternoon\\b", "15:00");
+ dayTimes.put("(?i)\\bevening\b" , "19:00");
+ dayTimes.put("(?i)\\bnight\\b" , "19:00");
+ dayTimes.put("(?i)\\bmidnight\\b" , "0:00");
+ dayTimes.put("(?i)\\bnoon\\b" , "12:00");
+
+ for (String dayTime: dayTimes.keySet()){
+ Pattern pattern = Pattern.compile(dayTime);
+ Matcher m = pattern.matcher(inputText);
+ if (m.find() && map.get("time")==null){
+ String dtime = dayTimes.get(dayTime);
+ map.put("time", Chronic.parse(dtime).getBeginCalendar());
+
+ }
+ }
+
+ HashMap mealTimes = new HashMap();
+ mealTimes.put("(?i)\\bbreakfast\\b", "8:00");
+ mealTimes.put("(?i)\\blunch\\b", "12:00");
+ mealTimes.put("(?i)\\bsupper\\b" ,"18:00");
+ mealTimes.put("(?i)\\bdinner\b","18:00");
+ mealTimes.put("(?i)\\bbrunch\b", "10:00");
+
+ for (String mealTime:mealTimes.keySet()){
+ Pattern pattern = Pattern.compile(mealTime);
+ Matcher m = pattern.matcher(inputText);
+ if (m.find() && map.get("time")==null){
+ String mtime = mealTimes.get(mealTime);
+ map.put("time", Chronic.parse(mtime).getBeginCalendar());
+ }
+ }
+ }
+
+
+ private static void repeatHelper(Task task, HashMap map, ArrayList tags) {
+ String inputText = task.getValue(Task.TITLE);
+ HashMap repeatTimes = new HashMap();
+ repeatTimes.put("(?i)\\bevery \\w{0,6} ?days?\\b" , "day");
+ repeatTimes.put("(?i)\\bevery \\w{0,6} ?weeks?\\b", "week");
+ repeatTimes.put("(?i)\\bevery \\w{0,6} ?(mon|tues|wednes|thurs|fri|satur|sun)days?\b/i","week");
+ repeatTimes.put("(?i)\\bevery \\w{0,6} ?months?\\b", "month");
+ repeatTimes.put("(?i)\\bevery \\w{0,6} ?years?\\b", "year");
+
+ HashMap repeatTimesIntervalOne = new HashMap();
+ //pre-determined intervals of 1
+ repeatTimesIntervalOne.put( "(?i)\\bdaily\\b" , "day");
+ repeatTimesIntervalOne.put( "(?i)\\bweekly\\b" , "week");
+ repeatTimesIntervalOne.put( "(?i)\\bmonthly\\b" ,"month");
+ repeatTimesIntervalOne.put( "(?i)\\byearly\\b" , "year");
+
+ for (String repeatTime:repeatTimes.keySet()){
+ Pattern pattern = Pattern.compile(repeatTime);
+ Matcher m = pattern.matcher(inputText);
+ if (m.find() && map.get("time")==null){
+ String rtime = repeatTimes.get(repeatTime);
+ map.put("freq", rtime);
+ map.put("interval",findInterval(inputText));
+ map.put("repeats", true);
+ }
+ }
+
+ for (String repeatTimeIntervalOne:repeatTimesIntervalOne.keySet()){
+ Pattern pattern = Pattern.compile(repeatTimeIntervalOne);
+ Matcher m = pattern.matcher(inputText);
+ if (m.find() && map.get("time")==null){
+ String rtime = repeatTimesIntervalOne.get(repeatTimeIntervalOne);
+ map.put("freq", rtime);
+ map.put("interval", 1);
+ map.put("repeats", true);
+ }
+ }
+ }
+
+ private static int findInterval(String inputText) {
+ HashMap words_to_num = new HashMap();
+ String[] words = new String[] {
+ "one", "two", "three", "four", "five", "six",
+ "seven", "eight", "nine", "ten", "eleven", "twelve"
+ };
+ for(int i = 0; i < words.length; i++) {
+ words_to_num.put(words[i], i+1);
+ words_to_num.put(Integer.toString(i + 1), i + 1);
+ }
+ words_to_num.put("other" , 2);
+
+ Pattern pattern = Pattern.compile("\\bevery (\\w*)\\b");
+ int interval = 1;
+ Matcher m = pattern.matcher(inputText);
+ if (m.find() && m.group(1)!=null){
+ String interval_str = m.group(1);
+ if (words_to_num.containsKey(interval_str))
+ interval = words_to_num.get(interval_str);
+ }
+ return interval;
+ }
+
+}
+
diff --git a/tests/.settings/org.eclipse.jdt.ui.prefs b/tests/.settings/org.eclipse.jdt.ui.prefs
index 29fddf385..662739807 100644
--- a/tests/.settings/org.eclipse.jdt.ui.prefs
+++ b/tests/.settings/org.eclipse.jdt.ui.prefs
@@ -1,4 +1,4 @@
-#Tue Mar 08 14:08:11 PST 2011
+#Tue Jan 10 16:28:27 PST 2012
cleanup.add_default_serial_version_id=true
cleanup.add_generated_serial_version_id=false
cleanup.add_missing_annotations=true