Merge lp:~mefrio-g/maya/lp-1382271 into lp:~elementary-apps/maya/trunk

Proposed by Mario Guerriero
Status: Merged
Approved by: Danielle Foré
Approved revision: 845
Merged at revision: 844
Proposed branch: lp:~mefrio-g/maya/lp-1382271
Merge into: lp:~elementary-apps/maya/trunk
Diff against target: 1426 lines (+1336/-0)
10 files modified
src/CMakeLists.txt (+5/-0)
src/EventEdition/EventDialog.vala (+24/-0)
src/EventEdition/GuestsPanel.vala (+5/-0)
src/EventEdition/InfoPanel.vala (+49/-0)
src/EventEdition/LocationPanel.vala (+5/-0)
src/EventParser/EventParser.vala (+28/-0)
src/EventParser/EventParserHandler.vala (+59/-0)
src/EventParser/ParsedEvent.vala (+183/-0)
src/EventParser/Parsers/ParserDe.vala (+399/-0)
src/EventParser/Parsers/ParserEn.vala (+579/-0)
To merge this branch: bzr merge lp:~mefrio-g/maya/lp-1382271
Reviewer Review Type Date Requested Status
Danielle Foré Approve
Review via email: mp+278904@code.launchpad.net

Commit message

Add natural language parsing to event title entry

Description of the change

This branch include an event parser from natural language. Right now it contains an english parser and a beginning implemtation of a german parser too. It will work only if your system locale is set to english or german.

To test just try to add a new event to maya and in the add event dialog's title entry type something like: "Rock concert in opera house tomorrow at 2" and hit ENTER.

You can find more info about the parser engine here: https://github.com/marioguerriero/event-parser

To post a comment you must log in.
Revision history for this message
Casper Christiansen (fault) wrote :

I'd just like to point out that the repo you forked didn't have any license as far as I can see, which is making me doubt the legality of forking and slapping on a license. Hopefully someone with more knowledge on the subject can chime in.

Perhaps contacting the original author to get his written permission is the best cause of action before merging.

Revision history for this message
Mario Guerriero (mefrio-g) wrote :

Well, I was skeptical on that point. By the way I could not found any contact information about him on Github so I just forked one his publicly shared repo and gave him credits. He is mentioned in all the files he contributed to and his name is both in the README.md and AUTHORS files.

If someone knows him and can me any informatian on how to contact him I would contact him.

Revision history for this message
Danielle Foré (danrabbit) wrote :

I think since his intention was to merge into Maya that it's fairly safe to assume that it would fall under Maya's license (GPL). If we're able to contact the original author and he wants something else, I'm sure we can accommodate his wishes.

Revision history for this message
Danielle Foré (danrabbit) :
review: Approve
Revision history for this message
RabbitBot (rabbitbot-a) wrote :

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Revision history for this message
Danielle Foré (danrabbit) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/CMakeLists.txt'
2--- src/CMakeLists.txt 2014-12-31 16:11:57 +0000
3+++ src/CMakeLists.txt 2015-11-29 20:16:21 +0000
4@@ -10,6 +10,11 @@
5 EventEdition/LocationPanel.vala
6 EventEdition/ReminderPanel.vala
7 EventEdition/RepeatPanel.vala
8+ EventParser/EventParser.vala
9+ EventParser/EventParserHandler.vala
10+ EventParser/ParsedEvent.vala
11+ EventParser/Parsers/ParserDe.vala
12+ EventParser/Parsers/ParserEn.vala
13 Grid/CalendarView.vala
14 Grid/GridDay.vala
15 Grid/Grid.vala
16
17=== modified file 'src/EventEdition/EventDialog.vala'
18--- src/EventEdition/EventDialog.vala 2015-01-17 00:03:47 +0000
19+++ src/EventEdition/EventDialog.vala 2015-11-29 20:16:21 +0000
20@@ -126,6 +126,30 @@
21 }
22 });
23
24+ var handler = new Maya.Services.EventParserHandler ();
25+ var parser = handler.get_parser (handler.get_locale ());
26+ if (handler.get_locale ().contains (parser.get_language ())) {
27+ // If there is handler for the current locale then...
28+ info_panel.nl_parsing_enabled = true;
29+ bool event_parsed = false;
30+ info_panel.parse_event.connect ((ev_str) => {
31+ if (!event_parsed) {
32+ var ev = parser.parse_source (ev_str);
33+ info_panel.title = ev.title;
34+ info_panel.from_date = ev.from;
35+ info_panel.to_date = ev.to;
36+ info_panel.from_time = ev.from;
37+ info_panel.to_time = ev.to;
38+ info_panel.all_day = ev.all_day;
39+ guests_panel.guests = ev.participants;
40+ location_panel.location = ev.location;
41+ event_parsed = true;
42+ }
43+ else
44+ save_dialog ();
45+ });
46+ }
47+
48 stack.add_named (info_panel, "infopanel");
49 stack.add_named (location_panel, "locationpanel");
50 stack.add_named (guests_panel, "guestspanel");
51
52=== modified file 'src/EventEdition/GuestsPanel.vala'
53--- src/EventEdition/GuestsPanel.vala 2015-05-28 16:30:42 +0000
54+++ src/EventEdition/GuestsPanel.vala 2015-11-29 20:16:21 +0000
55@@ -26,6 +26,11 @@
56 private Gee.ArrayList<unowned iCal.Property> attendees;
57 private Gtk.ListStore guest_store;
58
59+ public string guests {
60+ get { return guest_entry.get_text (); }
61+ set { guest_entry.set_text (value); }
62+ }
63+
64 private enum COLUMNS {
65 ICON = 0,
66 NAME,
67
68=== modified file 'src/EventEdition/InfoPanel.vala'
69--- src/EventEdition/InfoPanel.vala 2015-10-23 19:39:14 +0000
70+++ src/EventEdition/InfoPanel.vala 2015-11-29 20:16:21 +0000
71@@ -30,6 +30,40 @@
72
73 private EventDialog parent_dialog;
74
75+
76+ public string title {
77+ get { return title_entry.get_text (); }
78+ set { title_entry.set_text (value); }
79+ }
80+
81+ public DateTime from_date {
82+ get { return from_date_picker.date; }
83+ set { from_date_picker.date = value; }
84+ }
85+
86+ public DateTime to_date {
87+ get { return to_date_picker.date; }
88+ set { to_date_picker.date = value; }
89+ }
90+
91+ public DateTime from_time {
92+ get { return from_time_picker.time; }
93+ set { from_time_picker.time = value; }
94+ }
95+
96+ public DateTime to_time {
97+ get { return to_time_picker.time; }
98+ set { to_time_picker.time = value; }
99+ }
100+
101+ public bool all_day {
102+ get { return allday_switch.get_active (); }
103+ set { allday_switch.set_active (value); }
104+ }
105+
106+ public bool nl_parsing_enabled = false;
107+
108+ public signal void parse_event (string event_str);
109 public signal void valid_event (bool is_valid);
110
111 public InfoPanel (EventDialog parent_dialog) {
112@@ -74,6 +108,21 @@
113 title_entry = new Gtk.Entry ();
114 title_entry.placeholder_text = _("Name of Event");
115 title_entry.changed.connect (on_title_entry_modified);
116+ title_entry.activate.connect (() => {
117+ parse_event (title_entry.get_text ());
118+ title_entry.secondary_icon_name = null;
119+ title_entry.secondary_icon_tooltip_text = null;
120+ });
121+ title_entry.changed.connect (() => {
122+ if (title_entry.get_text ().length > 0 && nl_parsing_enabled) {
123+ title_entry.secondary_icon_name = "go-jump-symbolic";
124+ title_entry.secondary_icon_tooltip_text = _("Press enter to parse event");
125+ }
126+ else {
127+ title_entry.secondary_icon_name = null;
128+ title_entry.secondary_icon_tooltip_text = null;
129+ }
130+ });
131
132 var calendar_label = Maya.View.EventDialog.make_label (_("Calendar:"));
133 calendar_button = new Maya.View.Widgets.CalendarButton ();
134
135=== modified file 'src/EventEdition/LocationPanel.vala'
136--- src/EventEdition/LocationPanel.vala 2014-12-29 15:13:35 +0000
137+++ src/EventEdition/LocationPanel.vala 2015-11-29 20:16:21 +0000
138@@ -30,6 +30,11 @@
139 private bool map_selected = false;
140 private GLib.Cancellable search_cancellable;
141
142+ public string location {
143+ get { return location_entry.get_text (); }
144+ set { location_entry.set_text (value); }
145+ }
146+
147 public LocationPanel (EventDialog parent_dialog) {
148 this.parent_dialog = parent_dialog;
149
150
151=== added directory 'src/EventParser'
152=== added file 'src/EventParser/EventParser.vala'
153--- src/EventParser/EventParser.vala 1970-01-01 00:00:00 +0000
154+++ src/EventParser/EventParser.vala 2015-11-29 20:16:21 +0000
155@@ -0,0 +1,28 @@
156+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
157+/***
158+ BEGIN LICENSE
159+
160+ Copyright (C) 2015 Mario Guerriero <marioguerriero33@gmail.com>
161+ This program is free software: you can redistribute it and/or modify it
162+ under the terms of the GNU Lesser General Public License version 3, as published
163+ by the Free Software Foundation.
164+
165+ This program is distributed in the hope that it will be useful, but
166+ WITHOUT ANY WARRANTY; without even the implied warranties of
167+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
168+ PURPOSE. See the GNU General Public License for more details.
169+
170+ You should have received a copy of the GNU General Public License along
171+ with this program. If not, see <http://www.gnu.org/licenses/>
172+
173+ END LICENSE
174+***/
175+
176+namespace Maya.Services {
177+
178+public interface EventParser : GLib.Object {
179+ public abstract ParsedEvent parse_source (string source);
180+ public abstract string get_language ();
181+}
182+
183+}
184\ No newline at end of file
185
186=== added file 'src/EventParser/EventParserHandler.vala'
187--- src/EventParser/EventParserHandler.vala 1970-01-01 00:00:00 +0000
188+++ src/EventParser/EventParserHandler.vala 2015-11-29 20:16:21 +0000
189@@ -0,0 +1,59 @@
190+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
191+/***
192+ BEGIN LICENSE
193+
194+ Copyright (C) 2015 Mario Guerriero <marioguerriero33@gmail.com>
195+ This program is free software: you can redistribute it and/or modify it
196+ under the terms of the GNU Lesser General Public License version 3, as published
197+ by the Free Software Foundation.
198+
199+ This program is distributed in the hope that it will be useful, but
200+ WITHOUT ANY WARRANTY; without even the implied warranties of
201+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
202+ PURPOSE. See the GNU General Public License for more details.
203+
204+ You should have received a copy of the GNU General Public License along
205+ with this program. If not, see <http://www.gnu.org/licenses/>
206+
207+ END LICENSE
208+***/
209+
210+namespace Maya.Services {
211+
212+public class EventParserHandler : GLib.Object {
213+
214+ public const string FALLBACK_LANG = "en";
215+
216+ private Gee.HashMap<string, EventParser> handlers;
217+
218+ public EventParserHandler (string? lang = null) {
219+ handlers = new Gee.HashMap<string, EventParser> ();
220+
221+ if (lang == null)
222+ lang = get_locale ();
223+
224+ // Grant at least the fallback parser
225+ register_handler (FALLBACK_LANG, new ParserEn ());
226+
227+ // Register other default parsers
228+ var parser = new ParserDe ();
229+ register_handler (parser.get_language (), parser); // de
230+
231+ }
232+
233+ public void register_handler (string lang, EventParser parser) {
234+ handlers.set (lang, parser);
235+ }
236+
237+ public EventParser get_parser (string lang) {
238+ if (!handlers.has_key (lang))
239+ return handlers.get (FALLBACK_LANG);
240+ return handlers.get (lang);
241+ }
242+
243+ public unowned string? get_locale () {
244+ return Environment.get_variable ("LANGUAGE");
245+ }
246+}
247+
248+}
249
250=== added file 'src/EventParser/ParsedEvent.vala'
251--- src/EventParser/ParsedEvent.vala 1970-01-01 00:00:00 +0000
252+++ src/EventParser/ParsedEvent.vala 2015-11-29 20:16:21 +0000
253@@ -0,0 +1,183 @@
254+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
255+/***
256+ BEGIN LICENSE
257+
258+ Copyright (C) 2015 Mario Guerriero <marioguerriero33@gmail.com>
259+ pantor
260+ This program is free software: you can redistribute it and/or modify it
261+ under the terms of the GNU Lesser General Public License version 3, as published
262+ by the Free Software Foundation.
263+
264+ This program is distributed in the hope that it will be useful, but
265+ WITHOUT ANY WARRANTY; without even the implied warranties of
266+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
267+ PURPOSE. See the GNU General Public License for more details.
268+
269+ You should have received a copy of the GNU General Public License along
270+ with this program. If not, see <http://www.gnu.org/licenses/>
271+
272+ END LICENSE
273+***/
274+
275+namespace Maya.Services {
276+
277+public class ParsedEvent : GLib.Object {
278+
279+ public string title;
280+ public string location;
281+ public string participants;
282+ public DateTime from;
283+ public DateTime to;
284+ public bool all_day;
285+
286+ public ParsedEvent (string _title = "", DateTime? _from = null, DateTime? _to = null, string _location = "", bool _all_day = false, string _participants = "") {
287+ this.title = _title;
288+ this.location = _location;
289+ this.participants = _participants;
290+ this.from = _from;
291+ this.to = _to;
292+ this.all_day = _all_day;
293+ }
294+
295+ public void set_length_to_minutes (int minutes) {
296+ this.to = this.from.add_minutes (minutes);
297+ }
298+
299+ public void set_length_to_hours (int hours) {
300+ this.to = this.from.add_hours (hours);
301+ }
302+
303+ public void set_length_to_days (int days) {
304+ this.to = this.from.add_days (days);
305+ }
306+
307+ public void set_length_to_weeks (int weeks) {
308+ this.to = this.from.add_days (7 * weeks);
309+ }
310+
311+ public void from_set_second (int second) {
312+ this.from = this.from.add_seconds (second - this.from.get_second ());
313+ }
314+
315+ public void to_set_second (int second) {
316+ this.to = this.to.add_seconds (second - this.to.get_second ());
317+ }
318+
319+ public void from_set_minute (int minute) {
320+ this.from = this.from.add_minutes (minute - this.from.get_minute ());
321+ }
322+
323+ public void to_set_minute (int minute) {
324+ this.to = this.to.add_minutes (minute - this.to.get_minute ());
325+ }
326+
327+ private int hour_from_half (int hour, string half) {
328+ if (hour > 12)
329+ return hour;
330+
331+ if (half == "pm")
332+ return hour + 12;
333+
334+ if (half == "p")
335+ return hour + 12;
336+
337+ if (half == "") {
338+ if (hour < 8) {
339+ hour += 12;
340+ }
341+ }
342+
343+ return hour;
344+ }
345+
346+ public void from_set_hour (int hour, string half = "") {
347+ hour = hour_from_half (hour, half);
348+ this.from = this.from.add_hours (hour - this.from.get_hour ());
349+ }
350+
351+ public void to_set_hour (int hour, string half = "") {
352+ hour = hour_from_half (hour, half);
353+ this.to = this.to.add_hours (hour - this.to.get_hour ());
354+ }
355+
356+ public void from_set_day (int day) {
357+ if (day > 0)
358+ this.from = this.from.add_days (day - this.from.get_day_of_month ());
359+ }
360+
361+ public void to_set_day (int day) {
362+ if (day > 0)
363+ this.to = this.to.add_days (day - this.to.get_day_of_month ());
364+ }
365+
366+ public void from_set_month (int month) {
367+ if (month > 0)
368+ this.from = this.from.add_months (month - this.from.get_month ());
369+ }
370+
371+ public void to_set_month (int month) {
372+ if (month > 0)
373+ this.to = this.to.add_months (month - this.to.get_month ());
374+ }
375+
376+ public void from_set_year (int year) {
377+ if (year > 0)
378+ this.from = this.from.add_years (year - this.from.get_year ());
379+ }
380+
381+ public void to_set_year (int year) {
382+ if (year > 0)
383+ this.to = this.to.add_years (year - this.to.get_year ());
384+ }
385+
386+
387+
388+ public void set_all_day () {
389+ this.from = this.from.add_hours (-this.from.get_hour () ).add_minutes (-this.from.get_minute ());
390+ this.to = this.to.add_hours (-this.to.get_hour ()).add_minutes (-this.to.get_minute ());
391+ this.all_day = true;
392+ }
393+
394+ public void unset_all_day () {
395+ this.set_length_to_hours (1);
396+ this.all_day = false;
397+ }
398+
399+ public void set_one_entire_day () {
400+ this.from = this.from.add_hours (-this.from.get_hour ()).add_minutes (-this.from.get_minute ());
401+ this.to = this.from;
402+ this.all_day = true;
403+ }
404+
405+
406+
407+ public void if_elapsed_delay_to_next_day (DateTime simulated_dt) {
408+ if (this.from.compare (simulated_dt) < 0) {
409+ this.from = this.from.add_days (1);
410+ this.to = this.to.add_days (1);
411+ }
412+ }
413+
414+ public void if_elapsed_delay_to_next_week (DateTime simulated_dt) {
415+ if (this.from.compare (simulated_dt) < 0) {
416+ this.from = this. from.add_days (7);
417+ this.to = this.to.add_days (7);
418+ }
419+ }
420+
421+ public void if_elapsed_delay_to_next_month (DateTime simulated_dt) {
422+ if (this.from.compare (simulated_dt) < 0) {
423+ this.from = this.from.add_months (1);
424+ this.to = this.to.add_months (1);
425+ }
426+ }
427+
428+ public void if_elapsed_delay_to_next_year (DateTime simulated_dt) {
429+ if (this.from.compare (simulated_dt) < 0) {
430+ this.from = this.from.add_years (1);
431+ this.to = this.to.add_years (1);
432+ }
433+ }
434+}
435+
436+}
437\ No newline at end of file
438
439=== added directory 'src/EventParser/Parsers'
440=== added file 'src/EventParser/Parsers/ParserDe.vala'
441--- src/EventParser/Parsers/ParserDe.vala 1970-01-01 00:00:00 +0000
442+++ src/EventParser/Parsers/ParserDe.vala 2015-11-29 20:16:21 +0000
443@@ -0,0 +1,399 @@
444+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
445+/***
446+ BEGIN LICENSE
447+
448+ Copyright (C) 2015 Mario Guerriero <marioguerriero33@gmail.com>
449+ pantor
450+ This program is free software: you can redistribute it and/or modify it
451+ under the terms of the GNU Lesser General Public License version 3, as published
452+ by the Free Software Foundation.
453+
454+ This program is distributed in the hope that it will be useful, but
455+ WITHOUT ANY WARRANTY; without even the implied warranties of
456+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
457+ PURPOSE. See the GNU General Public License for more details.
458+
459+ You should have received a copy of the GNU General Public License along
460+ with this program. If not, see <http://www.gnu.org/licenses/>
461+
462+ END LICENSE
463+***/
464+
465+namespace Maya.Services {
466+
467+public class ParserDe : GLib.Object, EventParser {
468+
469+ public DateTime simulated_dt;
470+
471+ public string source;
472+ private string remaining_source;
473+
474+
475+ string[,] months = {
476+ {"januar", "1"},
477+ {"februar", "2"},
478+ {"märz", "3"},
479+ {"april", "4"},
480+ {"mai", "5"},
481+ {"juni", "6"},
482+ {"juli", "7"},
483+ {"august", "8"},
484+ {"september", "9"},
485+ {"oktober", "10"},
486+ {"november", "11"},
487+ {"dezember", "12"}
488+ };
489+ string[,] weekdays = {
490+ {"montag", "1"},
491+ {"dienstag", "2"},
492+ {"mittwoch", "3"},
493+ {"donnerstag", "4"},
494+ {"freitag", "5"},
495+ {"samstag", "6"},
496+ {"sonntag", "7"}
497+ };
498+
499+ string months_regex;
500+ string weekdays_regex;
501+
502+ struct String_event { bool matched; string matched_string; int pos; int length; Array<string> p; }
503+
504+ delegate void transcribe_analysis (String_event data);
505+
506+ public ParserDe (DateTime _simulated_dt = new DateTime.now_local ()) {
507+ this.simulated_dt = _simulated_dt;
508+
509+ this.source = "";
510+ this.remaining_source = "";
511+
512+ this.months_regex = "";
513+ for (int i = 0; i < 12; i++)
514+ this.months_regex += months[i, 0] + "|";
515+ this.months_regex = this.months_regex[0:-1];
516+
517+ this.weekdays_regex = "";
518+ for (int i = 0; i < 7; i++)
519+ this.weekdays_regex += weekdays[i, 0] + "|";
520+ this.weekdays_regex = this.weekdays_regex[0:-1];
521+ }
522+
523+
524+ int get_number_of_month (string entry) {
525+ for (int i = 0; i < 12; i++) {
526+ if (entry.down () == months[i, 0])
527+ return int.parse (months[i, 1]);
528+ }
529+ return -1;
530+ }
531+
532+ int get_number_of_weekday (string entry) {
533+ for (int i = 0; i < 12; i++) {
534+ if (entry.down () == weekdays[i, 0])
535+ return int.parse (weekdays[i, 1]);
536+ }
537+ return -1;
538+ }
539+
540+
541+ // finds regex "pattern" in string source
542+ String_event complete_string (string pattern) {
543+ Regex regex;
544+ MatchInfo match_info;
545+ try {
546+ regex = new Regex (pattern, RegexCompileFlags.CASELESS);
547+ var is_matched = regex.match (this.remaining_source, 0, out match_info);
548+ if (!is_matched)
549+ return String_event () { matched = false };
550+ } catch {
551+ return String_event () { matched = false };
552+ }
553+
554+ var matched_string = match_info.fetch (0);
555+ var pos = this.remaining_source.index_of (matched_string);
556+ var length = matched_string.length;
557+
558+ var p = new Array<string> ();
559+
560+ while (match_info.matches ()) {
561+ for (var i = 0; i < 4; i++)
562+ p.append_val (match_info.fetch_named (@"p$(i + 1)"));
563+
564+ try {
565+ match_info.next ();
566+ } catch (GLib.RegexError exc) {
567+ // TODO
568+ }
569+ }
570+
571+ return String_event () { matched = true, pos = pos, length = length, matched_string = matched_string, p = p };
572+ }
573+
574+ void analyze_pattern (string pattern, transcribe_analysis del) {
575+ String_event data = complete_string ("\\b" + pattern + "\\b");
576+ if (data.matched) {
577+ this.remaining_source = this.remaining_source.splice (data.pos, data.pos + data.length);
578+ del (data);
579+ }
580+ }
581+
582+
583+ public ParsedEvent parse_source (string _source) {
584+ this.source = _source;
585+ this.remaining_source = this.source;
586+
587+
588+ var event = new ParsedEvent ();
589+ event.from = this.simulated_dt.add_hours (1);
590+ event.from_set_minute (0);
591+ event.from_set_second (0);
592+ event.set_length_to_hours (1);
593+
594+ // --- Date ---
595+
596+ analyze_pattern ("vorgestern", (data) => {
597+ event.from = event.from.add_days (-2);
598+ event.set_one_entire_day ();
599+ });
600+
601+ analyze_pattern ("gestern", (data) => {
602+ event.from = event.from.add_days (-1);
603+ event.set_one_entire_day ();
604+ });
605+
606+ analyze_pattern ("(ab )?morgen", (data) => {
607+ event.from = event.from.add_days(1);
608+ event.set_one_entire_day();
609+ });
610+
611+ analyze_pattern ("(ab )?übermorgen", (data) => {
612+ event.from = event.from.add_days (2);
613+ event.set_one_entire_day ();
614+ });
615+
616+ analyze_pattern ("(den ganzen tag|ganztägig)", (data) => {
617+ event.set_one_entire_day ();
618+ });
619+
620+ analyze_pattern ("vor (?<p1>\\d+) tagen", (data) => {
621+ int days = int.parse ( data.p.index(0) );
622+ event.from = event.from.add_days (-days);
623+ event.set_one_entire_day ();
624+ });
625+
626+ analyze_pattern ("in (?<p1>\\d+) tagen", (data) => {
627+ int days = int.parse (data.p.index(0));
628+ event.from = event.from.add_days (days);
629+ event.set_one_entire_day();
630+ });
631+
632+ analyze_pattern (@"diesen (?<p1>$weekdays_regex)", (data) => {
633+ int weekday = get_number_of_weekday (data.p.index (0));
634+ int add_days = (weekday - this.simulated_dt.get_day_of_week () + 7 ) % 7;
635+ event.from = event.from.add_days (add_days);
636+
637+ event.set_one_entire_day ();
638+ });
639+
640+ analyze_pattern (@"nächsten (?<p1>$weekdays_regex)", (data) => {
641+ int weekday = get_number_of_weekday (data.p.index (0));
642+ int add_days = (weekday - this.simulated_dt.get_day_of_week () + 7 ) % 7;
643+ event.from = event.from.add_days (add_days);
644+
645+ event.set_one_entire_day ();
646+ });
647+
648+ analyze_pattern (@"übernächsten (?<p1>$weekdays_regex)", (data) => {
649+ int weekday = get_number_of_weekday (data.p.index(0));
650+ int add_days = (weekday - this.simulated_dt.get_day_of_week () + 7 ) % 7;
651+ event.from = event.from.add_weeks (1);
652+ event.from = event.from.add_days (add_days);
653+
654+ event.set_one_entire_day ();
655+ });
656+
657+ analyze_pattern ("am (?<p1>\\d+).(?<p2>\\d+)(.(?<p3>\\d+))?", (data) => {
658+ int day = int.parse (data.p.index (0));
659+ int month = int.parse (data.p.index(1));
660+
661+ event.from_set_day (day);
662+ event.set_one_entire_day ();
663+
664+ event.from_set_month (month);
665+ event.to_set_month (month);
666+
667+ if (data.p.index (2) != null ) {
668+ int year = int.parse (data.p.index (2));
669+ event.from_set_year (year);
670+
671+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
672+ }
673+
674+ event.if_elapsed_delay_to_next_month (this.simulated_dt);
675+ });
676+
677+ analyze_pattern (@"vom (?<p1>\\d+). bis (?<p2>\\d+). ((?<p3>$months_regex))?", (data) => {
678+ int day_1 = int.parse (data.p.index (0));
679+ int day_2 = int.parse (data.p.index (1));
680+
681+ event.from_set_day (day_1);
682+ event.to_set_day (day_2);
683+ event.set_all_day ();
684+
685+ if (data.p.index (2) != null) {
686+ int month = get_number_of_month (data.p.index (2));
687+ event.from_set_month (month);
688+ event.to_set_month (month);
689+
690+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
691+ }
692+
693+ event.if_elapsed_delay_to_next_month (this.simulated_dt);
694+ });
695+
696+ analyze_pattern (@"am (?<p1>\\d+)(.)?( (?<p2>$months_regex))?", (data) => {
697+ int day = int.parse (data.p.index (0));
698+ int month = get_number_of_month (data.p.index (1));
699+
700+ event.from_set_day (day);
701+ event.from_set_month (month);
702+ event.set_one_entire_day ();
703+
704+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
705+ });
706+
707+ analyze_pattern ("heiligabend", (data) => {
708+ event.from_set_month (12);
709+ event.from_set_day (24);
710+ event.set_one_entire_day ();
711+
712+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
713+ });
714+
715+ // --- Time ---
716+
717+ analyze_pattern ("früh", (data) => {
718+ event.from_set_hour (9);
719+ event.set_length_to_hours (1);
720+ event.all_day = false;
721+ });
722+
723+ analyze_pattern ("vormittags", (data) => {
724+ event.from_set_hour (11);
725+ event.set_length_to_hours (1);
726+ event.all_day = false;
727+ });
728+
729+ analyze_pattern ("mittag(s?)", (data) => {
730+ event.from_set_hour (12);
731+ event.set_length_to_hours (1);
732+ event.all_day = false;
733+ });
734+
735+ analyze_pattern ("nachmittags", (data) => {
736+ event.from_set_hour (15);
737+ event.set_length_to_hours (1);
738+ event.all_day = false;
739+ });
740+
741+ analyze_pattern ("abends", (data) => {
742+ event.from_set_hour (18);
743+ event.set_length_to_hours (1);
744+ event.all_day = false;
745+ });
746+
747+ analyze_pattern ("spät", (data) => {
748+ event.from_set_hour (19);
749+ event.set_length_to_hours (3);
750+ event.all_day = false;
751+ });
752+
753+ analyze_pattern ("(um|ab) (?<p1>\\d+)(:(?<p2>\\d+))?( (uhr|h))?", (data) => {
754+ int hour = int.parse (data.p.index (0));
755+ event.from_set_hour (hour);
756+
757+ if (data.p.index (1) != null) {
758+ int minute_1 = int.parse (data.p.index (1));
759+ event.from_set_minute (minute_1);
760+ }
761+
762+ event.set_length_to_hours (1);
763+ event.all_day = false;
764+ });
765+
766+ analyze_pattern ("von (?<p1>\\d+)(:(?<p3>\\d+))? bis (?<p2>\\d+)(:(?<p4>\\d+))?( uhr)?", (data) => {
767+ int hour_1 = int.parse (data.p.index (0));
768+ int hour_2 = int.parse (data.p.index (1));
769+
770+ event.from_set_hour (hour_1);
771+ event.to_set_hour (hour_2);
772+
773+ if (data.p.index (2) != null) {
774+ int minute_1 = int.parse (data.p.index (2));
775+ event.from_set_minute (minute_1);
776+ }
777+ if (data.p.index (3) != null) {
778+ int minute_2 = int.parse (data.p.index (3));
779+ event.to_set_minute (minute_2);
780+ }
781+ event.all_day = false;
782+ });
783+
784+ analyze_pattern ("(?<p1>\\d+)(:(?<p2>\\d+))? (uhr|h)", (data) => {
785+ int hour = int.parse (data.p.index (0));
786+ event.from_set_hour (hour);
787+
788+ if (data.p.index(1) != null) {
789+ int minute_1 = int.parse (data.p.index (1));
790+ event.from_set_minute (minute_1);
791+ }
792+
793+ event.set_length_to_hours (1);
794+ event.all_day = false;
795+ });
796+
797+ analyze_pattern ("für (?<p1>\\d+)(\\s?min| Minuten)", (data) => {
798+ int minutes = int.parse (data.p.index (0));
799+ event.set_length_to_minutes (minutes);
800+ });
801+
802+ analyze_pattern ("für (?<p1>\\d+)(\\s?h| Stunden)", (data) => {
803+ int hours = int.parse (data.p.index (0));
804+ event.set_length_to_hours (hours);
805+ });
806+
807+ analyze_pattern ("für (?<p1>\\d+)(\\s?d| Tage)", (data) => {
808+ int days = int.parse (data.p.index (0));
809+ event.set_length_to_days (days);
810+ });
811+
812+ analyze_pattern ("für (?<p1>\\d+) Wochen", (data) => {
813+ int weeks = int.parse (data.p.index (0));
814+ event.set_length_to_weeks (weeks);
815+ });
816+
817+ // --- Repetition ---
818+
819+ // --- Persons ---
820+
821+ // --- Location ----
822+ analyze_pattern ("(im|in dem) (?<p1>(\\w\\s?)+)", (data) => {
823+ event.location = data.p.index (0);
824+ });
825+
826+ analyze_pattern ("in( der)? (?<p1>[a-z]+)", (data) => {
827+ event.location = data.p.index (0);
828+ });
829+
830+ // --- Name ---
831+
832+ event.title = this.remaining_source.strip ();
833+
834+ return event;
835+ }
836+
837+ public string get_language () {
838+ return "de";
839+ }
840+}
841+
842+}
843
844=== added file 'src/EventParser/Parsers/ParserEn.vala'
845--- src/EventParser/Parsers/ParserEn.vala 1970-01-01 00:00:00 +0000
846+++ src/EventParser/Parsers/ParserEn.vala 2015-11-29 20:16:21 +0000
847@@ -0,0 +1,579 @@
848+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
849+/***
850+ BEGIN LICENSE
851+
852+ Copyright (C) 2015 Mario Guerriero <marioguerriero33@gmail.com>
853+ pantor
854+ This program is free software: you can redistribute it and/or modify it
855+ under the terms of the GNU Lesser General Public License version 3, as published
856+ by the Free Software Foundation.
857+
858+ This program is distributed in the hope that it will be useful, but
859+ WITHOUT ANY WARRANTY; without even the implied warranties of
860+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
861+ PURPOSE. See the GNU General Public License for more details.
862+
863+ You should have received a copy of the GNU General Public License along
864+ with this program. If not, see <http://www.gnu.org/licenses/>
865+
866+ END LICENSE
867+***/
868+
869+namespace Maya.Services {
870+
871+public class ParserEn : GLib.Object, EventParser {
872+
873+ public DateTime simulated_dt;
874+
875+ public string source;
876+ private string remaining_source;
877+
878+
879+ string[,] months = {
880+ {"january", "1"},
881+ {"february", "2"},
882+ {"march", "3"},
883+ {"april", "4"},
884+ {"may", "5"},
885+ {"june", "6"},
886+ {"july", "7"},
887+ {"august", "8"},
888+ {"september", "9"},
889+ {"october", "10"},
890+ {"november", "11"},
891+ {"december", "12"}
892+ };
893+ string[,] weekdays = {
894+ {"monday", "1"},
895+ {"tuesday", "2"},
896+ {"wednesday", "3"},
897+ {"thursday", "4"},
898+ {"thu", "4"},
899+ {"friday", "5"},
900+ {"saturday", "6"},
901+ {"sunday", "7"}
902+ };
903+ string[,] number_words = {
904+ {"one", "1"},
905+ {"two", "2"},
906+ {"three", "3"},
907+ {"four", "4"},
908+ {"five", "5"},
909+ {"six", "6"},
910+ {"seven", "7"},
911+ {"eight", "8"},
912+ {"nine", "9"},
913+ {"ten", "10"},
914+ {"eleven", "11"},
915+ {"twelve", "12"}
916+ };
917+
918+ string months_regex;
919+ string weekdays_regex;
920+ string number_words_regex;
921+
922+
923+
924+ struct String_event { bool matched; string matched_string; int pos; int length; Array<string> p; }
925+
926+ delegate void transcribe_analysis (String_event data);
927+
928+
929+
930+ public ParserEn (DateTime _simulated_dt = new DateTime.now_local ()) {
931+ this.simulated_dt = _simulated_dt;
932+
933+ this.source = "";
934+ this.remaining_source = "";
935+
936+ this.months_regex = "(";
937+ for (int i = 0; i < 12; i++)
938+ this.months_regex += months[i, 0] + "|";
939+ this.months_regex = this.months_regex[0:-1] + ")";
940+
941+ this.weekdays_regex = "(";
942+ for (int i = 0; i < 7; i++)
943+ this.weekdays_regex += weekdays[i, 0] + "|";
944+ this.weekdays_regex = this.weekdays_regex[0:-1] + ")";
945+
946+ this.number_words_regex = "(";
947+ for (int i = 0; i < 7; i++)
948+ this.number_words_regex += number_words[i, 0] + "|";
949+ this.number_words_regex = this.number_words_regex[0:-1] + ")";
950+ }
951+
952+
953+ int get_number_of_month (string entry) {
954+ for (int i = 0; i < 12; i++) {
955+ if (entry.down () == months[i, 0])
956+ return int.parse (months[i, 1]);
957+ }
958+ return -1;
959+ }
960+
961+ int get_number_of_weekday (string entry) {
962+ for (int i = 0; i < 12; i++) {
963+ if (entry.down () == weekdays[i, 0])
964+ return int.parse (weekdays[i, 1]);
965+ }
966+ return -1;
967+ }
968+
969+ /*int get_number_of_word (string entry) {
970+ for (int i = 0; i < 12; i++) {
971+ if (entry.down () == number_words[i, 0])
972+ return int.parse (number_words[i, 1]);
973+ }
974+ return -1;
975+ }*/
976+
977+ // finds regex "pattern" in string source
978+ String_event complete_string (string pattern) {
979+ Regex regex;
980+ MatchInfo match_info;
981+ try {
982+ regex = new Regex (pattern, RegexCompileFlags.CASELESS);
983+ var is_matched = regex.match (this.remaining_source, 0, out match_info);
984+ if (!is_matched)
985+ return String_event () { matched = false };
986+ } catch {
987+ return String_event () { matched = false };
988+ }
989+
990+ var matched_string = match_info.fetch (0);
991+ var pos = this.remaining_source.index_of (matched_string);
992+ var length = matched_string.length;
993+
994+ var p = new Array<string> ();
995+
996+ while (match_info.matches ()) {
997+ for (var i = 0; i < 6; i++)
998+ p.append_val (match_info.fetch_named (@"p$(i + 1)"));
999+
1000+ try {
1001+ match_info.next ();
1002+ } catch (GLib.RegexError exc) {
1003+ // TODO
1004+ }
1005+ }
1006+
1007+ return String_event () { matched = true, pos = pos, length = length, matched_string = matched_string, p = p };
1008+ }
1009+
1010+ void analyze_pattern (string pattern, transcribe_analysis del, bool delete = true) {
1011+ String_event data = complete_string ("\\b" + pattern + "\\b");
1012+ if (data.matched) {
1013+ if (delete)
1014+ this.remaining_source = this.remaining_source.splice (data.pos, data.pos + data.length);
1015+
1016+ del (data);
1017+ }
1018+ }
1019+
1020+
1021+ public ParsedEvent parse_source (string _source) {
1022+ this.source = _source;
1023+ this.remaining_source = this.source;
1024+
1025+
1026+ var event = new ParsedEvent ();
1027+ event.from = this.simulated_dt.add_hours (1);
1028+ event.from_set_minute (0);
1029+ event.from_set_second (0);
1030+ event.set_length_to_hours (1);
1031+
1032+ // --- Date ---
1033+
1034+ analyze_pattern ("two days ago", (data) => {
1035+ event.from = event.from.add_days (-2);
1036+ event.set_one_entire_day ();
1037+ });
1038+
1039+ analyze_pattern ("yesterday", (data) => {
1040+ event.from = event.from.add_days (-1);
1041+ event.set_one_entire_day ();
1042+ });
1043+
1044+ analyze_pattern ("today", (data) => {
1045+ event.set_one_entire_day ();
1046+ });
1047+
1048+ analyze_pattern ("tomorrow", (data) => {
1049+ event.from = event.from.add_days (1);
1050+ event.set_one_entire_day ();
1051+ });
1052+
1053+ analyze_pattern ("this weekend", (data) => {
1054+ int add_days = (6 - this.simulated_dt.get_day_of_week () + 7) % 7;
1055+ event.from = event.from.add_days (add_days);
1056+ event.to = event.from.add_days (1);
1057+ event.set_all_day ();
1058+ });
1059+
1060+ analyze_pattern ("all day", (data) => {
1061+ event.set_one_entire_day ();
1062+ });
1063+
1064+ analyze_pattern ("the whole day", (data) => {
1065+ event.set_one_entire_day ();
1066+ });
1067+
1068+ analyze_pattern ("next week", (data) => {
1069+ event.from = event.from.add_days (7);
1070+ event.set_all_day ();
1071+ });
1072+
1073+ analyze_pattern ("next month", (data) => {
1074+ event.from = event.from.add_months (1);
1075+ event.set_all_day ();
1076+ });
1077+
1078+ analyze_pattern ("(?<p1>\\d+) days ago", (data) => {
1079+ int days = int.parse(data.p.index (0));
1080+ event.from = event.from.add_days (-days);
1081+ event.set_one_entire_day ();
1082+ });
1083+
1084+ analyze_pattern ("in (?<p1>\\d+) days", (data) => {
1085+ int days = int.parse (data.p.index (0));
1086+ event.from = event.from.add_days (days);
1087+ event.set_one_entire_day ();
1088+ });
1089+
1090+ analyze_pattern ("in (?<p1>\\d+) weeks", (data) => {
1091+ int weeks = int.parse (data.p.index (0));
1092+ event.from = event.from.add_weeks (weeks);
1093+ event.set_one_entire_day ();
1094+ });
1095+
1096+ analyze_pattern (@"(next|on) (?<p1>$weekdays_regex)", (data) => {
1097+ int weekday = get_number_of_weekday (data.p.index (0));
1098+ int add_days = (weekday - this.simulated_dt.get_day_of_week () + 7) % 7;
1099+ event.from = event.from.add_days (add_days);
1100+
1101+ event.set_one_entire_day ();
1102+ });
1103+
1104+ analyze_pattern (@"(this )?(?<p1>$weekdays_regex)( to (?<p2>$weekdays_regex))?", (data) => {
1105+ int weekday_1 = get_number_of_weekday (data.p.index (0));
1106+ int add_days_1 = (weekday_1 - this.simulated_dt.get_day_of_week () + 7) % 7;
1107+
1108+ event.from = event.from.add_days (add_days_1);
1109+ event.set_all_day ();
1110+
1111+ if (data.p.index (1) != null) {
1112+ int weekday_2 = get_number_of_weekday (data.p.index (1));
1113+ int add_days_2 = (weekday_2 - weekday_1 + 7) % 7;
1114+
1115+ event.to = event.from.add_days (add_days_2);
1116+ }
1117+ });
1118+
1119+ analyze_pattern (@"on ((?<p1>\\d{2,4})/)?(?<p2>\\d{1,2})/(?<p3>\\d{1,2})(st|nd|rd|th)?", (data) => {
1120+ int day = int.parse (data.p.index (2));
1121+ int month = int.parse (data.p.index (1));
1122+
1123+ event.from_set_day (day);
1124+ event.from_set_month (month);
1125+ event.set_one_entire_day ();
1126+
1127+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
1128+
1129+ if (data.p.index (0) != null) {
1130+ int year = int.parse (data.p.index (0));
1131+ event.from_set_year (year);
1132+ }
1133+ });
1134+
1135+ analyze_pattern (@"on (?<p1>\\d{0,1})(st|nd|rd|th)? (?<p2>$months_regex)( (?<p3>\\d{2,4}))?", (data) => {
1136+ int day = int.parse (data.p.index (0));
1137+ int month = get_number_of_month (data.p.index (1));
1138+
1139+ event.from_set_day (day);
1140+ event.from_set_month (month);
1141+ event.set_one_entire_day ();
1142+
1143+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
1144+
1145+ if (data.p.index (2) != null) {
1146+ int year = int.parse (data.p.index (2));
1147+ event.from_set_year (year);
1148+ }
1149+ });
1150+
1151+ analyze_pattern (@"on (?<p1>$months_regex)(,)? (?<p2>\\d{1,2})(st|nd|rd|th)?( (?<p3>\\d{2,4}))?", (data) => {
1152+ int day = int.parse (data.p.index (1));
1153+ int month = get_number_of_month (data.p.index (0));
1154+
1155+ event.from_set_day (day);
1156+ event.from_set_month (month);
1157+ event.set_one_entire_day ();
1158+
1159+ if (data.p.index (2) != null) {
1160+ int year = int.parse (data.p.index (2));
1161+ event.from_set_year (year);
1162+ }
1163+
1164+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
1165+ });
1166+
1167+ analyze_pattern (@"from (?<p1>\\d{1,2})(.)? to (?<p2>\\d{1,2}). ((?<p3>$months_regex))?", (data) => {
1168+ int day_1 = int.parse (data.p.index (0));
1169+ int day_2 = int.parse (data.p.index (1));
1170+
1171+ event.from_set_day (day_1);
1172+ event.to_set_day (day_2);
1173+ event.set_all_day ();
1174+
1175+ if (data.p.index (2) != null) {
1176+ int month = get_number_of_month (data.p.index (2));
1177+ event.from_set_month (month);
1178+ event.to_set_month (month);
1179+
1180+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
1181+ }
1182+
1183+ event.if_elapsed_delay_to_next_month (this.simulated_dt);
1184+ });
1185+
1186+ analyze_pattern (@"from (?<p1>\\d{1,2})/(?<p2>\\d{1,2}) - ((?<p3>\\d{1,2})/)?(?<p4>\\d{1,2})", (data) => {
1187+ int day_1 = int.parse (data.p.index (1));
1188+ int day_2 = int.parse (data.p.index (3));
1189+ int month_1 = int.parse (data.p.index (0));
1190+ int month_2 = int.parse (data.p.index (2));
1191+
1192+ if (month_2 == 0)
1193+ month_2 = month_1;
1194+
1195+ event.from_set_day (day_1);
1196+ event.to_set_day( day_2);
1197+ event.from_set_month (month_1);
1198+ event.to_set_month (month_2);
1199+ event.set_all_day ();
1200+
1201+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
1202+ });
1203+
1204+ analyze_pattern (@"from (?<p1>$months_regex) (?<p2>\\d{1,2})(st|nd|rd|th)? - (?<p3>\\d{1,2})(st|nd|rd|th)?", (data) => {
1205+ int day_1 = int.parse (data.p.index (1));
1206+ int day_2 = int.parse (data.p.index (2));
1207+ int month_1 = get_number_of_month (data.p.index (0));
1208+
1209+ event.from_set_day (day_1);
1210+ event.to_set_day (day_2);
1211+ event.from_set_month (month_1);
1212+ event.to_set_month (month_1);
1213+
1214+ event.set_all_day ();
1215+
1216+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
1217+ });
1218+
1219+ analyze_pattern ("in a month", (data) => {
1220+ event.from = event.from.add_months (1);
1221+ event.set_one_entire_day ();
1222+ });
1223+
1224+ analyze_pattern ("christmas eve", (data) => {
1225+ event.from_set_month (12);
1226+ event.from_set_day (24);
1227+ event.set_one_entire_day ();
1228+
1229+ event.if_elapsed_delay_to_next_year (this.simulated_dt);
1230+ });
1231+
1232+
1233+ // --- Time ---
1234+
1235+ analyze_pattern ("breakfast", (data) => {
1236+ event.from_set_hour (8);
1237+ event.set_length_to_hours (1);
1238+ event.all_day = false;
1239+ }, false);
1240+
1241+ analyze_pattern ("lunch", (data) => {
1242+ event.from_set_hour (13);
1243+ event.set_length_to_hours (1);
1244+ event.all_day = false;
1245+ }, false);
1246+
1247+ analyze_pattern ("dinner", (data) => {
1248+ event.from_set_hour (19);
1249+ event.set_length_to_hours (1);
1250+ event.all_day = false;
1251+ }, false);
1252+
1253+ analyze_pattern ("early", (data) => {
1254+ event.from_set_hour (9);
1255+ event.set_length_to_hours (1);
1256+ event.all_day = false;
1257+ });
1258+
1259+ analyze_pattern ("(this )?morning", (data) => {
1260+ event.from_set_hour (11);
1261+ event.set_length_to_hours (1);
1262+ event.all_day = false;
1263+ });
1264+
1265+ analyze_pattern ("(at |this )?noon", (data) => {
1266+ event.from_set_hour (12);
1267+ event.set_length_to_hours (1);
1268+ event.all_day = false;
1269+ });
1270+
1271+ analyze_pattern ("(this )?afternoon", (data) => {
1272+ event.from_set_hour (15);
1273+ event.set_length_to_hours (1);
1274+ event.all_day = false;
1275+ });
1276+
1277+ analyze_pattern ("(this )?evening", (data) => {
1278+ event.from_set_hour (18);
1279+ event.set_length_to_hours (1);
1280+ event.all_day = false;
1281+ });
1282+
1283+ analyze_pattern ("late", (data) => {
1284+ event.from_set_hour (19);
1285+ event.set_length_to_hours (3);
1286+ event.all_day = false;
1287+ });
1288+
1289+ analyze_pattern ("(?<p1>\\d{1,2})?(?<p2>(am|pm|p))?(to |-| - )(?<p3>\\d{1,2})?(?<p4>(am|pm|p))?", (data) => {
1290+ int hour_1 = int.parse (data.p.index (0));
1291+ int hour_2 = int.parse (data.p.index (2));
1292+
1293+ string half_1 = "";
1294+ if (data.p.index (1) != null)
1295+ half_1 = data.p.index (1);
1296+
1297+ string half_2 = "";
1298+ if (data.p.index (3) != null)
1299+ half_2 = data.p.index (3);
1300+
1301+ event.from_set_hour (hour_1, half_1);
1302+ event.to_set_hour (hour_2, half_2);
1303+
1304+ event.all_day = false;
1305+ });
1306+
1307+ analyze_pattern ("(at |@ ?)(?<p1>\\d{1,2})(:(?<p2>\\d{1,2}))?(?<p3>(am|pm|p))?", (data) => {
1308+ int hour = int.parse (data.p.index(0));
1309+
1310+ if (data.p.index (1) != null) {
1311+ int minute_1 = int.parse(data.p.index (1));
1312+ event.from_set_minute (minute_1);
1313+ }
1314+
1315+ string half = "";
1316+ if (data.p.index (2) != null)
1317+ half = data.p.index (2);
1318+
1319+ event.from_set_hour (hour, half);
1320+
1321+ event.set_length_to_hours (1);
1322+ event.all_day = false;
1323+ });
1324+
1325+ analyze_pattern ("(at |@)(?<p1>\\d{4})", (data) => {
1326+ int hour = int.parse (data.p.index (0));
1327+
1328+ if (data.p.index (1) != null) {
1329+ int minute_1 = int.parse (data.p.index (1));
1330+ event.from_set_minute (minute_1);
1331+ }
1332+
1333+ string half = "";
1334+ if (data.p.index (2) != null)
1335+ half = data.p.index (2);
1336+ event.from_set_hour (hour, half);
1337+
1338+ event.set_length_to_hours (1);
1339+ event.all_day = false;
1340+ });
1341+
1342+ analyze_pattern ("from (?<p1>\\d{1,2})(:(?<p3>\\d{1,2}))?(?<p5>(am|pm|p)?) to (?<p2>\\d{1,2})(:(?<p4>\\d{1,2}))?(?<p6>(am|pm|p)?)", (data) => {
1343+ int hour_1 = int.parse (data.p.index (0));
1344+ int hour_2 = int.parse (data.p.index (1));
1345+
1346+ string half_1 = "";
1347+ if (data.p.index (4) != null)
1348+ half_1 = data.p.index (4);
1349+ event.from_set_hour (hour_1, half_1);
1350+
1351+ string half_2 = "";
1352+ if (data.p.index (5) != null)
1353+ half_2 = data.p.index (5);
1354+ event.to_set_hour (hour_2, half_2);
1355+
1356+ if (data.p.index (2) != null) {
1357+ int minute_1 = int.parse (data.p.index (2));
1358+ event.from_set_minute (minute_1);
1359+ }
1360+ if (data.p.index (3) != null) {
1361+ int minute_2 = int.parse (data.p.index (3));
1362+ event.to_set_minute (minute_2);
1363+ }
1364+ event.all_day = false;
1365+ });
1366+
1367+ analyze_pattern ("(?<p1>\\d{1,2})(:(?<p2>\\d{1,2}))? (o'clock|h)", (data) => {
1368+ int hour = int.parse (data.p.index (0));
1369+ event.from_set_hour (hour);
1370+
1371+ if (data.p.index (1) != null) {
1372+ int minute_1 = int.parse (data.p.index (1));
1373+ event.from_set_minute (minute_1);
1374+ }
1375+
1376+ event.set_length_to_hours (1);
1377+ event.all_day = false;
1378+ });
1379+
1380+ analyze_pattern ("for (?<p1>\\d+)(\\s?min| minutes)", (data) => {
1381+ int minutes = int.parse (data.p.index (0));
1382+ event.set_length_to_minutes (minutes);
1383+ });
1384+
1385+ analyze_pattern ("for (?<p1>\\d+)(\\s?h| hours)", (data) => {
1386+ int hours = int.parse (data.p.index(0));
1387+ event.set_length_to_hours (hours);
1388+ });
1389+
1390+ analyze_pattern ("for (?<p1>\\d+)(\\s?d| days)", (data) => {
1391+ int days = int.parse (data.p.index (0));
1392+ event.set_length_to_days (days);
1393+ });
1394+
1395+ analyze_pattern ("for (?<p1>\\d+) weeks", (data) => {
1396+ int weeks = int.parse (data.p.index (0));
1397+ event.set_length_to_weeks(weeks);
1398+ });
1399+
1400+ // --- Repetition ---
1401+
1402+ // --- Persons ---
1403+ analyze_pattern ("(with)( the)? (?<p1>(\\w\\s?)+)", (data) => {
1404+ for (int i = 0; i < data.p.length ; i++)
1405+ event.participants += data.p.index (i);
1406+ });
1407+
1408+ // --- Location ----
1409+ analyze_pattern ("(at|in)(the)? (?<p1>(\\w\\s?)+)", (data) => {
1410+ event.location = data.p.index (0);
1411+ });
1412+
1413+ // --- Name ---
1414+ event.title = this.remaining_source.strip ();
1415+ // event.title = event.title.strip();
1416+ // Strip ,.: from title
1417+
1418+ return event;
1419+ }
1420+
1421+ public string get_language () {
1422+ return EventParserHandler.FALLBACK_LANG;
1423+ }
1424+}
1425+
1426+}

Subscribers

People subscribed via source and target branches