mhc 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/bin/mhc +66 -3
- data/emacs/Cask +1 -1
- data/emacs/mhc-date.el +1 -1
- data/emacs/mhc-day.el +1 -1
- data/emacs/mhc-db.el +57 -38
- data/emacs/mhc-draft.el +36 -22
- data/emacs/mhc-face.el +1 -1
- data/emacs/mhc-header.el +20 -1
- data/emacs/mhc-minibuf.el +12 -7
- data/emacs/mhc-parse.el +1 -1
- data/emacs/mhc-process.el +26 -9
- data/emacs/mhc-ps.el +1 -1
- data/emacs/mhc-schedule.el +5 -2
- data/emacs/mhc-summary.el +31 -12
- data/emacs/mhc-vars.el +15 -2
- data/emacs/mhc.el +50 -24
- data/lib/mhc.rb +3 -1
- data/lib/mhc/builder.rb +5 -1
- data/lib/mhc/calendar.rb +5 -1
- data/lib/mhc/command/cache.rb +5 -4
- data/lib/mhc/converter.rb +3 -2
- data/lib/mhc/datastore.rb +52 -13
- data/lib/mhc/date_enumerator.rb +2 -2
- data/lib/mhc/event.rb +42 -21
- data/lib/mhc/formatter.rb +17 -312
- data/lib/mhc/formatter/base.rb +125 -0
- data/lib/mhc/formatter/emacs.rb +47 -0
- data/lib/mhc/formatter/howm.rb +35 -0
- data/lib/mhc/formatter/icalendar.rb +17 -0
- data/lib/mhc/formatter/json.rb +27 -0
- data/lib/mhc/formatter/mail.rb +20 -0
- data/lib/mhc/formatter/org_table.rb +24 -0
- data/lib/mhc/formatter/symbolic_expression.rb +42 -0
- data/lib/mhc/formatter/text.rb +29 -0
- data/lib/mhc/occurrence.rb +27 -5
- data/lib/mhc/occurrence_enumerator.rb +1 -1
- data/lib/mhc/property_value.rb +6 -0
- data/lib/mhc/property_value/date.rb +23 -14
- data/lib/mhc/property_value/date_time.rb +19 -0
- data/lib/mhc/property_value/integer.rb +5 -1
- data/lib/mhc/property_value/list.rb +7 -6
- data/lib/mhc/property_value/period.rb +3 -1
- data/lib/mhc/property_value/range.rb +1 -1
- data/lib/mhc/property_value/time.rb +8 -1
- data/lib/mhc/version.rb +1 -1
- data/spec/mhc_spec.rb +83 -0
- metadata +13 -3
data/emacs/mhc-ps.el
CHANGED
data/emacs/mhc-schedule.el
CHANGED
@@ -142,7 +142,10 @@
|
|
142
142
|
|
143
143
|
|
144
144
|
(defun mhc-schedule-subject-as-string (schedule)
|
145
|
-
(
|
145
|
+
(let ((subject (mhc-schedule-subject schedule)))
|
146
|
+
(if (eq (length subject) 0)
|
147
|
+
"(no subject)"
|
148
|
+
subject)))
|
146
149
|
|
147
150
|
|
148
151
|
(defun mhc-schedule-categories-as-string (schedule)
|
@@ -199,4 +202,4 @@
|
|
199
202
|
;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
200
203
|
;; OF THE POSSIBILITY OF SUCH DAMAGE.
|
201
204
|
|
202
|
-
;;; mhc-schedule.el ends here
|
205
|
+
;;; mhc-schedule.el ends here
|
data/emacs/mhc-summary.el
CHANGED
@@ -171,6 +171,8 @@ which are replaced by the given information:
|
|
171
171
|
'face mhc-tmp-day-face)
|
172
172
|
(?/ (if mhc-tmp-first "/" " ")
|
173
173
|
'face mhc-tmp-day-face)
|
174
|
+
(?- (if mhc-tmp-first "-" " ")
|
175
|
+
'face mhc-tmp-day-face)
|
174
176
|
(?S " " 'face mhc-tmp-day-face)
|
175
177
|
(?M (mhc-summary/line-month-string)
|
176
178
|
'face mhc-tmp-day-face)
|
@@ -182,7 +184,8 @@ which are replaced by the given information:
|
|
182
184
|
(make-string 5 ? )
|
183
185
|
(format "%02d:%02d" (/ mhc-tmp-begin 60) (% mhc-tmp-begin 60)))
|
184
186
|
'face 'mhc-summary-face-time)
|
185
|
-
(?e (if (null mhc-tmp-end)
|
187
|
+
(?e (if (or (null mhc-tmp-end)
|
188
|
+
(and mhc-tmp-begin (= mhc-tmp-end mhc-tmp-begin)))
|
186
189
|
(make-string 6 ? )
|
187
190
|
(format "-%02d:%02d" (/ mhc-tmp-end 60) (% mhc-tmp-end 60)))
|
188
191
|
'face 'mhc-summary-face-time)
|
@@ -498,10 +501,10 @@ If BANNER is set, it is printed on the horizontal line."
|
|
498
501
|
|
499
502
|
|
500
503
|
(defun mhc-summary/line-subject-string ()
|
501
|
-
(if mhc-tmp-
|
502
|
-
(
|
503
|
-
|
504
|
-
|
504
|
+
(if mhc-tmp-schedule
|
505
|
+
(if mhc-tmp-private
|
506
|
+
mhc-summary-string-secret
|
507
|
+
(mhc-schedule-subject-as-string mhc-tmp-schedule))))
|
505
508
|
|
506
509
|
(defun mhc-summary/line-location-string ()
|
507
510
|
(let ((location (mhc-schedule-location mhc-tmp-schedule)))
|
@@ -661,20 +664,36 @@ If BANNER is set, it is printed on the horizontal line."
|
|
661
664
|
(defun mhc-summary-buffer-p (&optional buffer)
|
662
665
|
(if buffer
|
663
666
|
(set-buffer buffer))
|
664
|
-
mhc-summary-
|
667
|
+
(eq major-mode 'mhc-summary-mode))
|
665
668
|
|
666
|
-
(defun mhc-summary-current-date ()
|
669
|
+
(defun mhc-summary-current-date (&optional p)
|
667
670
|
(when (mhc-summary-buffer-p)
|
668
|
-
(let ((
|
671
|
+
(let* ((pos (or p (point)))
|
672
|
+
(dayinfo (get-text-property pos 'mhc-dayinfo)))
|
669
673
|
(or (and dayinfo (mhc-day-date dayinfo))
|
670
674
|
(save-excursion
|
671
675
|
(end-of-line)
|
672
|
-
(while (and (
|
676
|
+
(while (and (>= pos (point-min))
|
673
677
|
(null dayinfo))
|
674
|
-
(or (setq dayinfo (get-text-property
|
675
|
-
(
|
678
|
+
(or (setq dayinfo (get-text-property pos 'mhc-dayinfo))
|
679
|
+
(setq pos (- pos 1))))
|
676
680
|
(and dayinfo (mhc-day-date dayinfo)))))))
|
677
681
|
|
682
|
+
(defun mhc-summary-region-date ()
|
683
|
+
(when (region-active-p)
|
684
|
+
(let* ((p (region-beginning))
|
685
|
+
dayinfo
|
686
|
+
(datelist ()))
|
687
|
+
(progn
|
688
|
+
(while (<= p (region-end))
|
689
|
+
(and (setq dayinfo (mhc-summary-current-date p))
|
690
|
+
(setq datelist (cons dayinfo datelist)))
|
691
|
+
(setq p (next-single-property-change p 'mhc-dayinfo)))
|
692
|
+
(setq datelist (reverse (delete-dups datelist)))
|
693
|
+
(if (< 1 (length datelist))
|
694
|
+
(cons (car datelist) (car (last datelist)))
|
695
|
+
(car datelist))))))
|
696
|
+
|
678
697
|
(defvar mhc-summary-buffer-current-date-month nil
|
679
698
|
"Indicate summary buffer's month. It is also used by mhc-summary-buffer-p")
|
680
699
|
(make-variable-buffer-local 'mhc-summary-buffer-current-date-month)
|
@@ -782,4 +801,4 @@ If BANNER is set, it is printed on the horizontal line."
|
|
782
801
|
;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
783
802
|
;; OF THE POSSIBILITY OF SUCH DAMAGE.
|
784
803
|
|
785
|
-
;;; mhc-summary.el ends here
|
804
|
+
;;; mhc-summary.el ends here
|
data/emacs/mhc-vars.el
CHANGED
@@ -13,11 +13,12 @@
|
|
13
13
|
|
14
14
|
;;; Code:
|
15
15
|
(require 'mhc-compat)
|
16
|
-
|
16
|
+
|
17
|
+
(autoload 'mhc-process-send-command "mhc-process")
|
17
18
|
|
18
19
|
|
19
20
|
;;; Constants:
|
20
|
-
(defconst mhc-version "mhc 1.
|
21
|
+
(defconst mhc-version "mhc 1.2.0") ;; MHC_VERSION
|
21
22
|
|
22
23
|
|
23
24
|
;;; Configration Variables:
|
@@ -25,6 +26,18 @@
|
|
25
26
|
"Various sorts of MH Calender."
|
26
27
|
:group 'mail)
|
27
28
|
|
29
|
+
(defcustom mhc-program-name "mhc"
|
30
|
+
"Program name of MHC."
|
31
|
+
:group 'mhc
|
32
|
+
:type 'string)
|
33
|
+
|
34
|
+
(defcustom mhc-ruby-program-name (when (eq system-type 'windows-nt) "ruby")
|
35
|
+
"When non-nil, specify ruby program name.
|
36
|
+
Nil means MHC script is called directly."
|
37
|
+
:group 'mhc
|
38
|
+
:type '(choice (const :tag "Call script directly" nil)
|
39
|
+
string))
|
40
|
+
|
28
41
|
(defcustom mhc-start-day-of-week 0
|
29
42
|
"*Day of the week as the start of the week."
|
30
43
|
:group 'mhc
|
data/emacs/mhc.el
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
;; Description: Message Harmonized Calendaring system.
|
4
4
|
;; Author: Yoshinari Nomura <nom@quickhack.net>
|
5
5
|
;; Created: 1994-07-04
|
6
|
-
;; Version: 1.
|
6
|
+
;; Version: 1.2.0
|
7
7
|
;; Keywords: calendar
|
8
8
|
;; URL: http://www.quickhack.net/mhc
|
9
9
|
;; Package-Requires: ((calfw "20150703"))
|
@@ -190,8 +190,8 @@
|
|
190
190
|
Field names using by MHC.
|
191
191
|
|
192
192
|
X-SC-Category:
|
193
|
-
Space-seperated Keywords.
|
194
|
-
You can also indicate keywords by typing '\\[mhc-rescan-month]', '\\[mhc-goto-this-month]', '\\[mhc-goto-month]', '\\[mhc-goto-date]' with
|
193
|
+
Space-seperated Keywords. You can set default category to scan.
|
194
|
+
You can also indicate keywords by typing '\\[mhc-rescan-month]', '\\[mhc-goto-this-month]', '\\[mhc-goto-month]', '\\[mhc-goto-date]' with \\[universal-argument].
|
195
195
|
"
|
196
196
|
(interactive "P")
|
197
197
|
(make-local-variable 'mhc-mode)
|
@@ -371,10 +371,15 @@ If HIDE-PRIVATE, priavate schedules are suppressed."
|
|
371
371
|
(if mhc-default-hide-private-schedules
|
372
372
|
(not current-prefix-arg)
|
373
373
|
current-prefix-arg)))
|
374
|
-
(mhc-
|
375
|
-
|
376
|
-
|
377
|
-
|
374
|
+
(let ((name (if (and (mhc-summary-buffer-p)
|
375
|
+
(not (string-match
|
376
|
+
"^[0-9][0-9][0-9][0-9]-[0-9][0-9]$" (buffer-name))))
|
377
|
+
(buffer-name))))
|
378
|
+
(mhc-scan-month date
|
379
|
+
'mhc-mua
|
380
|
+
mhc-default-category-predicate-sexp
|
381
|
+
hide-private
|
382
|
+
name)))
|
378
383
|
|
379
384
|
(defvar mhc-goto-date-func 'mhc-goto-date-calendar)
|
380
385
|
; or mhc-goto-date-summary
|
@@ -524,21 +529,22 @@ SCOPE is one of:
|
|
524
529
|
((eq scope 'wide)
|
525
530
|
(mhc-date-ww-last (mhc-date++ edge-date) mhc-start-day-of-week)))))
|
526
531
|
|
527
|
-
(defun mhc-scan-month (date mailer category-predicate secret)
|
532
|
+
(defun mhc-scan-month (date mailer category-predicate secret &optional name)
|
528
533
|
"Make summary buffer for a month indicated by DATE.
|
529
534
|
DATE can be any date of the target month.
|
530
535
|
If MAILER is 'direct, insert scanned result into current buffer.
|
531
536
|
CATEGORY-PREDICATE must be a function that can take one mhc-schedule
|
532
537
|
argument and return a boolean value indicates opacity of the article.
|
533
538
|
If SECRET is non-nil, hide articles those categories are
|
534
|
-
listed in ``mhc-category-as-private''.
|
539
|
+
listed in ``mhc-category-as-private''.
|
540
|
+
If optional NAME is non-nil, created smmary buffer has the name."
|
535
541
|
(let* ((from (mhc-date-mm-first date))
|
536
542
|
(to (mhc-date-mm-last date))
|
537
543
|
(today (mhc-date-now))
|
538
544
|
;; need three months for mini-calendar
|
539
545
|
(dayinfo-list (mhc-db-scan (mhc-date-mm-- from) (mhc-date-mm++ to))))
|
540
546
|
(unless (eq 'direct mailer)
|
541
|
-
(mhc-summary-generate-buffer date)
|
547
|
+
(mhc-summary-generate-buffer (or name date))
|
542
548
|
(setq mhc-summary-buffer-current-date-month
|
543
549
|
(mhc-date-mm-first date)))
|
544
550
|
(when mhc-use-wide-scope
|
@@ -614,7 +620,7 @@ Returns t if the importation was succeeded."
|
|
614
620
|
(list (get-buffer (read-buffer "Import buffer: "
|
615
621
|
(current-buffer))))))
|
616
622
|
(let ((draft-buffer (generate-new-buffer mhc-draft-buffer-name))
|
617
|
-
(current-date (or (mhc-summary-current-date) (mhc-calendar-get-date) (mhc-date-now)))
|
623
|
+
(current-date (or (mhc-summary-region-date) (mhc-summary-current-date) (mhc-calendar-get-date) (mhc-date-now)))
|
618
624
|
(succeed t)
|
619
625
|
msgp date time subject location category recurrence-tag priority alarm)
|
620
626
|
(and (called-interactively-p 'interactive)
|
@@ -629,9 +635,9 @@ Returns t if the importation was succeeded."
|
|
629
635
|
(mhc-header-narrowing
|
630
636
|
(setq msgp (or (mhc-header-get-value "from")
|
631
637
|
(mhc-header-get-value "x-sc-subject")))
|
632
|
-
(mhc-header-
|
638
|
+
(mhc-header-distill-header
|
633
639
|
(concat "^\\("
|
634
|
-
(mhc-regexp-opt mhc-draft-
|
640
|
+
(mhc-regexp-opt mhc-draft-import-header-list)
|
635
641
|
"\\)")
|
636
642
|
'regexp))
|
637
643
|
(mhc-highlight-message)
|
@@ -808,15 +814,35 @@ the default action of this command is changed to the latter."
|
|
808
814
|
(mhc-window-pop)))
|
809
815
|
|
810
816
|
(defun mhc-import-from-region (beg end)
|
811
|
-
"
|
817
|
+
"Create new schedule draft from region BEG END."
|
812
818
|
(interactive "r")
|
813
|
-
(
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
819
|
+
(mhc-import-from-string (buffer-substring beg end)))
|
820
|
+
|
821
|
+
(defun mhc-import-from-clipboard ()
|
822
|
+
"Create new schedule draft from clipboard text."
|
823
|
+
(interactive)
|
824
|
+
(mhc-import-from-string (current-kill 0)))
|
825
|
+
|
826
|
+
(defun mhc-import-from-string (string)
|
827
|
+
"Create new schedule draft from STRING."
|
828
|
+
(with-temp-buffer
|
829
|
+
(yank 1)
|
830
|
+
(goto-char (point-min))
|
831
|
+
(insert "X-SC-Subject: \n"
|
832
|
+
"X-SC-Location: \n"
|
833
|
+
"X-SC-Day: \n"
|
834
|
+
"X-SC-Time: \n"
|
835
|
+
"X-SC-Category: \n"
|
836
|
+
"X-SC-Priority: \n"
|
837
|
+
"X-SC-Recurrence-Tag: \n"
|
838
|
+
"X-SC-Cond: \n"
|
839
|
+
"X-SC-Duration: \n"
|
840
|
+
"X-SC-Alarm: \n"
|
841
|
+
"X-SC-Record-Id: \n"
|
842
|
+
"X-SC-Sequence: 0\n"
|
843
|
+
"\n"
|
844
|
+
string)
|
845
|
+
(mhc-import)))
|
820
846
|
|
821
847
|
(defun mhc-delete ()
|
822
848
|
"Delete the current schedule."
|
@@ -871,11 +897,11 @@ the default action of this command is changed to the latter."
|
|
871
897
|
("x-sc-time" . ,time-list)
|
872
898
|
("x-sc-day" . ,date-list)))))
|
873
899
|
|
874
|
-
(defun mhc-reuse-copy ()
|
900
|
+
(defun mhc-reuse-copy (&optional filename)
|
875
901
|
"Copy current schedule to template."
|
876
902
|
(interactive)
|
877
|
-
(let ((file (mhc-summary-filename))
|
878
|
-
|
903
|
+
(let* ((file (or filename (mhc-summary-filename)))
|
904
|
+
(record (mhc-parse-file file)))
|
879
905
|
(if (and (stringp file) (file-exists-p file))
|
880
906
|
(with-temp-buffer
|
881
907
|
(mhc-insert-file-contents-as-coding-system
|
data/lib/mhc.rb
CHANGED
@@ -5,7 +5,7 @@ require "kconv"
|
|
5
5
|
## Monkey patch to the original RiCal https://github.com/rubyredrick/ri_cal
|
6
6
|
## delived from:
|
7
7
|
## git clone https://github.com/yoshinari-nomura/ri_cal.git
|
8
|
-
## git diff 369a4ee..
|
8
|
+
## git diff 369a4ee..cdb1f75
|
9
9
|
##
|
10
10
|
module RiCal
|
11
11
|
class Component #:nodoc:
|
@@ -47,6 +47,8 @@ module RiCal
|
|
47
47
|
result = {"VALUE" => "DATE"}.merge(params)
|
48
48
|
when DateTime
|
49
49
|
result = {"VALUE" => "DATE-TIME"}.merge(params)
|
50
|
+
when Period
|
51
|
+
result = {"VALUE" => "PERIOD"}.merge(params)
|
50
52
|
end
|
51
53
|
|
52
54
|
if has_local_timezone?
|
data/lib/mhc/builder.rb
CHANGED
@@ -11,6 +11,10 @@ module Mhc
|
|
11
11
|
@config = Mhc::Config.create_from_file(config) if config.is_a?(String)
|
12
12
|
end
|
13
13
|
|
14
|
+
def datastore
|
15
|
+
Mhc::DataStore.new(@config.general.repository)
|
16
|
+
end
|
17
|
+
|
14
18
|
def calendar(calendar_name)
|
15
19
|
calendar = @config.calendars[calendar_name]
|
16
20
|
raise Mhc::ConfigurationError, "calendar '#{calendar_name}' not found" unless calendar
|
@@ -23,7 +27,7 @@ module Mhc
|
|
23
27
|
when "lastnote"
|
24
28
|
db = Mhc::LastNote::Client.new(calendar.name)
|
25
29
|
when "mhc"
|
26
|
-
db = Mhc::Calendar.new(
|
30
|
+
db = Mhc::Calendar.new(self.datastore, calendar.modifiers, &calendar.filter)
|
27
31
|
end
|
28
32
|
return db
|
29
33
|
end
|
data/lib/mhc/calendar.rb
CHANGED
@@ -19,9 +19,13 @@ module Mhc
|
|
19
19
|
occurrences(date_range, &scope_block).map(&:event).uniq
|
20
20
|
end
|
21
21
|
|
22
|
+
def tasks(&scope_block)
|
23
|
+
@datastore.entries(category: "todo")
|
24
|
+
end
|
25
|
+
|
22
26
|
def occurrences(date_range, &scope_block)
|
23
27
|
ocs = []
|
24
|
-
@datastore.entries(date_range).each do |event|
|
28
|
+
@datastore.entries(range: date_range).each do |event|
|
25
29
|
event = decorate_event(event)
|
26
30
|
event.occurrences(range:date_range).each do |oc|
|
27
31
|
ocs << oc if in_scope?(oc, &scope_block)
|
data/lib/mhc/command/cache.rb
CHANGED
@@ -2,10 +2,11 @@ module Mhc
|
|
2
2
|
module Command
|
3
3
|
class Cache
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def initialize(datastore)
|
6
|
+
epoch = Date.new(1970, 1, 1)
|
7
|
+
puts"UID,MTIME,MIN,MAX,CATEGORIES,RECURRENCE,SUBJECT"
|
8
|
+
datastore.each_cache_entry do |uid, ent|
|
9
|
+
puts"#{ent.uid},#{ent.mtime},#{epoch + ent.range.min},#{epoch + ent.range.max},#{(ent.categories||[]).join(' ')},#{ent.recurrence},#{ent.subject}"
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
data/lib/mhc/converter.rb
CHANGED
@@ -44,8 +44,9 @@ module Mhc
|
|
44
44
|
|
45
45
|
def to_emacs_string(str)
|
46
46
|
# 1. quote " and \
|
47
|
-
# 2.
|
48
|
-
|
47
|
+
# 2. LF => \n
|
48
|
+
# 3. surround by "
|
49
|
+
'"' + str.to_s.toutf8.gsub(/[\"\\]/, '\\\\\&').gsub("\n", "\\n") + '"'
|
49
50
|
end
|
50
51
|
|
51
52
|
def to_emacs_plist(hash)
|
data/lib/mhc/datastore.rb
CHANGED
@@ -11,9 +11,9 @@ module Mhc
|
|
11
11
|
@cache = Cache.new(File.expand_path("status/cache/events.pstore", @basedir))
|
12
12
|
end
|
13
13
|
|
14
|
-
def entries(
|
15
|
-
if
|
16
|
-
int_range =
|
14
|
+
def entries(range: nil, category: nil, recurrence: nil)
|
15
|
+
if range
|
16
|
+
int_range = range.min.absolute_from_epoch .. range.max.absolute_from_epoch
|
17
17
|
end
|
18
18
|
|
19
19
|
Enumerator.new do |yielder|
|
@@ -23,13 +23,18 @@ module Mhc
|
|
23
23
|
|
24
24
|
Dir.chdir(dir) do
|
25
25
|
Dir.foreach(".") do |ent|
|
26
|
-
parse_mhcc(ent).each {|ev|
|
26
|
+
parse_mhcc(ent).each {|ev|
|
27
|
+
next if category && !ev.in_category?(category)
|
28
|
+
next if recurrence && !ev.in_recurrence?(recurrence)
|
29
|
+
yielder << ev
|
30
|
+
} if /\.mhcc$/ =~ ent
|
27
31
|
next unless /\.mhc$/ =~ ent
|
28
32
|
uid = $`
|
29
33
|
cache_entry = @cache.lookup(uid, ent)
|
30
|
-
if !
|
31
|
-
|
32
|
-
|
34
|
+
next if range && !cache_entry.in_range?(int_range)
|
35
|
+
next if category && !cache_entry.in_category?(category)
|
36
|
+
next if recurrence && !cache_entry.in_recurrence?(recurrence)
|
37
|
+
yielder << Event.parse_file(File.expand_path(ent))
|
33
38
|
end
|
34
39
|
end
|
35
40
|
end
|
@@ -78,6 +83,13 @@ module Mhc
|
|
78
83
|
end
|
79
84
|
end
|
80
85
|
|
86
|
+
# dump cache entry for debug usage
|
87
|
+
def each_cache_entry
|
88
|
+
@cache.each do |uid, ent|
|
89
|
+
yield uid, ent
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
81
93
|
################################################################
|
82
94
|
private
|
83
95
|
|
@@ -105,11 +117,21 @@ module Mhc
|
|
105
117
|
class Cache
|
106
118
|
require 'pstore'
|
107
119
|
|
120
|
+
VERSION = "1"
|
121
|
+
|
108
122
|
def initialize(cache_filename)
|
109
123
|
@pstore = PStore.new(cache_filename)
|
110
124
|
load
|
111
125
|
end
|
112
126
|
|
127
|
+
# dump cache entry for debug usage
|
128
|
+
def each
|
129
|
+
load unless @db
|
130
|
+
@db.each do |uid, ent|
|
131
|
+
yield uid, ent
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
113
135
|
def lookup(uid, filename)
|
114
136
|
unless c = get(uid) and File.mtime(filename).to_i <= c.mtime
|
115
137
|
c = CacheEntry.new(filename)
|
@@ -122,6 +144,7 @@ module Mhc
|
|
122
144
|
return self unless @dirty
|
123
145
|
@pstore.transaction do
|
124
146
|
@pstore["root"] = @db
|
147
|
+
@pstore["version"] = VERSION
|
125
148
|
end
|
126
149
|
@dirty = false
|
127
150
|
end
|
@@ -139,7 +162,7 @@ module Mhc
|
|
139
162
|
|
140
163
|
def load
|
141
164
|
@pstore.transaction do
|
142
|
-
@db = @pstore["root"] || {}
|
165
|
+
@db = (@pstore["version"] == VERSION) && @pstore["root"] || {}
|
143
166
|
end
|
144
167
|
@dirty = false
|
145
168
|
end
|
@@ -147,18 +170,34 @@ module Mhc
|
|
147
170
|
end # class Cache
|
148
171
|
|
149
172
|
class CacheEntry
|
150
|
-
attr_reader :mtime, :range
|
173
|
+
attr_reader :mtime, :uid, :subject, :location, :categories, :recurrence, :mission, :range
|
151
174
|
|
152
175
|
def initialize(filename)
|
153
|
-
@mtime
|
154
|
-
|
155
|
-
|
176
|
+
@mtime = File.mtime(filename).to_i
|
177
|
+
|
178
|
+
event = Event.parse_file(filename)
|
179
|
+
@uid = event.uid.to_s
|
180
|
+
@subject = event.subject.to_s
|
181
|
+
@location = event.location.to_s
|
182
|
+
@categories = event.categories.map {|c| c.to_s.downcase}
|
183
|
+
@recurrence = event.recurrence_tag.to_s
|
184
|
+
@mission = event.mission_tag.to_s
|
185
|
+
@range = event.range.min.absolute_from_epoch ..
|
186
|
+
event.range.max.absolute_from_epoch
|
187
|
+
end
|
188
|
+
|
189
|
+
def in_category?(category)
|
190
|
+
@categories.member?(category.downcase)
|
156
191
|
end
|
157
192
|
|
158
|
-
def
|
193
|
+
def in_range?(range)
|
159
194
|
range.min <= @range.max && @range.min <= range.max
|
160
195
|
end
|
161
196
|
|
197
|
+
def in_recurrence?(recurrence)
|
198
|
+
@recurrence && @recurrence.downcase == recurrence.downcase
|
199
|
+
end
|
200
|
+
|
162
201
|
end # class CacheEntry
|
163
202
|
|
164
203
|
end # class DataStore
|