mhc 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/COPYRIGHT +28 -0
  6. data/Gemfile +8 -0
  7. data/README.org +209 -0
  8. data/Rakefile +13 -0
  9. data/bin/mhc +312 -0
  10. data/emacs/Cask +25 -0
  11. data/emacs/Makefile +58 -0
  12. data/emacs/mhc-calendar.el +1723 -0
  13. data/emacs/mhc-calfw.el +135 -0
  14. data/emacs/mhc-compat.el +90 -0
  15. data/emacs/mhc-date.el +642 -0
  16. data/emacs/mhc-day.el +149 -0
  17. data/emacs/mhc-db.el +158 -0
  18. data/emacs/mhc-draft.el +211 -0
  19. data/emacs/mhc-e21.el +167 -0
  20. data/emacs/mhc-face.el +236 -0
  21. data/emacs/mhc-file.el +224 -0
  22. data/emacs/mhc-guess.el +648 -0
  23. data/emacs/mhc-header.el +176 -0
  24. data/emacs/mhc-logic.el +563 -0
  25. data/emacs/mhc-message.el +130 -0
  26. data/emacs/mhc-minibuf.el +466 -0
  27. data/emacs/mhc-misc.el +248 -0
  28. data/emacs/mhc-mua.el +260 -0
  29. data/emacs/mhc-parse.el +286 -0
  30. data/emacs/mhc-process.el +35 -0
  31. data/emacs/mhc-ps.el +1174 -0
  32. data/emacs/mhc-record.el +201 -0
  33. data/emacs/mhc-schedule.el +202 -0
  34. data/emacs/mhc-summary.el +763 -0
  35. data/emacs/mhc-sync.el +158 -0
  36. data/emacs/mhc-vars.el +149 -0
  37. data/emacs/mhc.el +1114 -0
  38. data/icons/Anniversary.xbm +6 -0
  39. data/icons/Anniversary.xpm +27 -0
  40. data/icons/Birthday.xbm +6 -0
  41. data/icons/Birthday.xpm +25 -0
  42. data/icons/Business.xbm +6 -0
  43. data/icons/Business.xpm +24 -0
  44. data/icons/CheckBox.xbm +6 -0
  45. data/icons/CheckBox.xpm +24 -0
  46. data/icons/CheckedBox.xbm +6 -0
  47. data/icons/CheckedBox.xpm +25 -0
  48. data/icons/Conflict.xbm +6 -0
  49. data/icons/Conflict.xpm +22 -0
  50. data/icons/Date.xbm +6 -0
  51. data/icons/Date.xpm +29 -0
  52. data/icons/Holiday.xbm +6 -0
  53. data/icons/Holiday.xpm +25 -0
  54. data/icons/Link.xbm +6 -0
  55. data/icons/Link.xpm +25 -0
  56. data/icons/Other.xbm +6 -0
  57. data/icons/Other.xpm +28 -0
  58. data/icons/Party.xbm +6 -0
  59. data/icons/Party.xpm +23 -0
  60. data/icons/Private.xbm +6 -0
  61. data/icons/Private.xpm +26 -0
  62. data/icons/Recurrence.xbm +6 -0
  63. data/icons/Recurrence.xpm +98 -0
  64. data/icons/Vacation.xbm +6 -0
  65. data/icons/Vacation.xpm +26 -0
  66. data/lib/mhc.rb +45 -0
  67. data/lib/mhc/builder.rb +64 -0
  68. data/lib/mhc/caldav.rb +304 -0
  69. data/lib/mhc/calendar.rb +106 -0
  70. data/lib/mhc/command.rb +13 -0
  71. data/lib/mhc/command/cache.rb +14 -0
  72. data/lib/mhc/command/completions.rb +108 -0
  73. data/lib/mhc/command/init.rb +133 -0
  74. data/lib/mhc/command/scan.rb +33 -0
  75. data/lib/mhc/command/sync.rb +22 -0
  76. data/lib/mhc/config.rb +229 -0
  77. data/lib/mhc/converter.rb +330 -0
  78. data/lib/mhc/datastore.rb +164 -0
  79. data/lib/mhc/date_enumerator.rb +274 -0
  80. data/lib/mhc/date_frame.rb +124 -0
  81. data/lib/mhc/date_helper.rb +49 -0
  82. data/lib/mhc/etag.rb +68 -0
  83. data/lib/mhc/event.rb +396 -0
  84. data/lib/mhc/formatter.rb +312 -0
  85. data/lib/mhc/logger.rb +94 -0
  86. data/lib/mhc/modifier.rb +149 -0
  87. data/lib/mhc/occurrence.rb +94 -0
  88. data/lib/mhc/occurrence_enumerator.rb +113 -0
  89. data/lib/mhc/property_value.rb +33 -0
  90. data/lib/mhc/property_value/date.rb +190 -0
  91. data/lib/mhc/property_value/integer.rb +15 -0
  92. data/lib/mhc/property_value/list.rb +41 -0
  93. data/lib/mhc/property_value/period.rb +49 -0
  94. data/lib/mhc/property_value/range.rb +100 -0
  95. data/lib/mhc/property_value/recurrence_condition.rb +272 -0
  96. data/lib/mhc/property_value/text.rb +11 -0
  97. data/lib/mhc/property_value/time.rb +45 -0
  98. data/lib/mhc/query.rb +210 -0
  99. data/lib/mhc/sync.rb +46 -0
  100. data/lib/mhc/sync/driver.rb +108 -0
  101. data/lib/mhc/sync/status.rb +70 -0
  102. data/lib/mhc/sync/status_manager.rb +142 -0
  103. data/lib/mhc/sync/strategy.rb +233 -0
  104. data/lib/mhc/sync/syncinfo.rb +98 -0
  105. data/lib/mhc/templates/config.yml.erb +142 -0
  106. data/lib/mhc/version.rb +4 -0
  107. data/lib/mhc/webdav.rb +319 -0
  108. data/mhc.gemspec +24 -0
  109. data/samples/DOT.mhc-config.yml +116 -0
  110. data/samples/japanese-holidays.mhcc +153 -0
  111. data/samples/mhc-completions.zsh +11 -0
  112. data/spec/mhc_spec.rb +682 -0
  113. data/spec/spec_helper.rb +9 -0
  114. data/xpm/close.xpm +18 -0
  115. data/xpm/delete.xpm +19 -0
  116. data/xpm/exit.xpm +18 -0
  117. data/xpm/month.xpm +18 -0
  118. data/xpm/next.xpm +18 -0
  119. data/xpm/next2.xpm +18 -0
  120. data/xpm/next_year.xpm +18 -0
  121. data/xpm/open.xpm +19 -0
  122. data/xpm/prev.xpm +18 -0
  123. data/xpm/prev2.xpm +18 -0
  124. data/xpm/prev_year.xpm +18 -0
  125. data/xpm/save.xpm +19 -0
  126. data/xpm/today.xpm +18 -0
  127. metadata +214 -0
@@ -0,0 +1,176 @@
1
+ ;;; -*- mode: Emacs-Lisp; coding: utf-8 -*-
2
+
3
+ ;; Author: Yoshinari Nomura <nom@quickhack.net>,
4
+ ;; TSUCHIYA Masatoshi <tsuchiya@namazu.org>
5
+ ;; Created: 2000/05/11
6
+ ;; Revised: $Date$
7
+
8
+
9
+ ;;; Commentary:
10
+
11
+ ;; This file is a part of MHC, includes functions to manipulate
12
+ ;; headers.
13
+
14
+
15
+ ;;; Code:
16
+
17
+ ;; Global Variable:
18
+
19
+ (defconst mhc-header-table
20
+ '(("x-sc-day" "X-SC-Day:" mhc-parse/day)
21
+ ("x-sc-cond" "X-SC-Cond:" mhc-parse/cond)
22
+ ("x-sc-duration" "X-SC-Duration:" mhc-parse/duration)
23
+ ("x-sc-subject" "X-SC-Subject:" mhc-parse/subject)
24
+ ("x-sc-location" "X-SC-Location:" mhc-parse/location)
25
+ ("x-sc-time" "X-SC-Time:" mhc-parse/time)
26
+ ("x-sc-alarm" "X-SC-Alarm:" mhc-parse/alarm)
27
+ ("x-sc-category" "X-SC-Category:" mhc-parse/category)
28
+ ("x-sc-recurrence-tag" "X-SC-Recurrence-Tag:" mhc-parse/recurrence-tag)
29
+ ("x-sc-priority" "X-SC-Priority:" mhc-parse/priority)
30
+ ("x-sc-record-id" "X-SC-Record-Id:" mhc-parse/record-id)
31
+ ("x-sc-schedule" "X-SC-Schdule:" mhc-parse/schedule)
32
+ ("x-sc-sequence" "X-SC-Sequence:" mhc-parse/sequence)
33
+ ;; For backward compatibility
34
+ ("x-sc-date" "X-SC-Date:" mhc-parse/old-style-date)
35
+ ;; FIXME: 要削除
36
+ ("x-sc-next" "X-SC-Next:" mhc-parse/next)))
37
+
38
+
39
+ (defmacro mhc-header-list ()
40
+ "Return headers which are referenced by MHC."
41
+ `(mapcar (lambda (a) (nth 1 a)) mhc-header-table))
42
+
43
+
44
+ (defmacro mhc-header-parse-function (key)
45
+ "Return a function to parse KEY."
46
+ `(nth 2 (assoc (downcase ,key) mhc-header-table)))
47
+
48
+
49
+ (defmacro mhc-header-narrowing (&rest form)
50
+ "Evaluate FORM with restriction of editing in this buffer to the header."
51
+ `(save-excursion
52
+ (save-restriction
53
+ (goto-char (point-min))
54
+ (re-search-forward
55
+ (concat "^" (regexp-quote mail-header-separator) "$\\|^$") nil t)
56
+ (narrow-to-region (point-min) (match-beginning 0))
57
+ (goto-char (point-min))
58
+ ,@form)))
59
+ (put 'mhc-header-narrowing 'lisp-indent-function 0)
60
+ (put 'mhc-header-narrowing 'edebug-form-spec '(form body))
61
+
62
+
63
+ (defsubst mhc-header-goto-end ()
64
+ "Move point at end of this header."
65
+ (while (and
66
+ (forward-line 1)
67
+ (memq (following-char) '(? ?\t)))))
68
+
69
+
70
+ (defun mhc-header-delete-header (header &optional regexp) "\
71
+ Remove HEADER in the narrowed buffer.
72
+ If REGEXP, HEADER is a regular expression."
73
+ (save-excursion
74
+ (let ((case-fold-search t)
75
+ (regexp (if regexp header (concat "^" (regexp-quote header) ":"))))
76
+ (goto-char (point-min))
77
+ (while (re-search-forward regexp nil t)
78
+ (mhc-header-goto-end)
79
+ (delete-region (match-beginning 0) (point))))))
80
+
81
+ (defun mhc-header-delete-empty-header (header &optional regexp)
82
+ "Remove HEADER if empty in the narrowed buffer.
83
+ If REGEXP, HEADER is a regular expression."
84
+ (save-excursion
85
+ (let ((case-fold-search t)
86
+ (regexp (if regexp (concat header " *$")
87
+ (concat "^" (regexp-quote header) ": *$"))))
88
+ (goto-char (point-min))
89
+ (while (re-search-forward regexp nil t)
90
+ (mhc-header-goto-end)
91
+ (delete-region (match-beginning 0) (point))))))
92
+
93
+ (defun mhc-header-put-value (header value)
94
+ "Overwrite VALUE of HEADER in the narrowed buffer."
95
+ (if (assoc (downcase header) mhc-header-table)
96
+ (setq header
97
+ (substring (nth 1 (assoc (downcase header) mhc-header-table)) 0 -1)))
98
+ (let ((case-fold-search t)
99
+ (regexp (concat "^" (regexp-quote header) ":")))
100
+ (save-excursion
101
+ (goto-char (point-min))
102
+ (if (re-search-forward regexp nil t)
103
+ (save-restriction
104
+ (mhc-header-goto-end)
105
+ (delete-region (match-beginning 0) (point))
106
+ (insert (format "%s: %s\n" header value))
107
+ (narrow-to-region (point) (point-max))
108
+ (mhc-header-delete-header header))
109
+ (goto-char (point-max))
110
+ (insert (format "%s: %s\n" header value))))))
111
+
112
+
113
+ (defun mhc-header-get-value (header &optional repeat)
114
+ "Return value of HEADER in the narrowed buffer."
115
+ (let ((point (point))
116
+ (case-fold-search t)
117
+ (regexp (concat "^" (regexp-quote header) ":[ \t]*"))
118
+ value)
119
+ (goto-char (point-min))
120
+ (while (and (not value)
121
+ (re-search-forward regexp nil t repeat))
122
+ (mhc-header-goto-end)
123
+ (setq value (buffer-substring-no-properties (match-end 0) (1- (point)))))
124
+ (goto-char point)
125
+ value))
126
+
127
+
128
+ (defun mhc-header-valid-p (header &optional repeat)
129
+ "Valid HEADER in the narrowed buffer."
130
+ (let ((get (mhc-header-get-value header repeat)))
131
+ (and (stringp get) (not (string= "" get)))))
132
+
133
+
134
+ (defun mhc-header-delete-separator ()
135
+ "Delete separator between header and body in this buffer."
136
+ (save-excursion
137
+ (goto-char (point-min))
138
+ (if (re-search-forward "^-*$" nil t)
139
+ (delete-region (match-beginning 0) (match-end 0)))))
140
+
141
+
142
+
143
+ (provide 'mhc-header)
144
+
145
+ ;;; Copyright Notice:
146
+
147
+ ;; Copyright (C) 1999, 2000 Yoshinari Nomura. All rights reserved.
148
+ ;; Copyright (C) 2000 MHC developing team. All rights reserved.
149
+
150
+ ;; Redistribution and use in source and binary forms, with or without
151
+ ;; modification, are permitted provided that the following conditions
152
+ ;; are met:
153
+ ;;
154
+ ;; 1. Redistributions of source code must retain the above copyright
155
+ ;; notice, this list of conditions and the following disclaimer.
156
+ ;; 2. Redistributions in binary form must reproduce the above copyright
157
+ ;; notice, this list of conditions and the following disclaimer in the
158
+ ;; documentation and/or other materials provided with the distribution.
159
+ ;; 3. Neither the name of the team nor the names of its contributors
160
+ ;; may be used to endorse or promote products derived from this software
161
+ ;; without specific prior written permission.
162
+ ;;
163
+ ;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS''
164
+ ;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
165
+ ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
166
+ ;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
167
+ ;; THE TEAM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
168
+ ;; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
169
+ ;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
170
+ ;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
171
+ ;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
172
+ ;; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
173
+ ;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
174
+ ;; OF THE POSSIBILITY OF SUCH DAMAGE.
175
+
176
+ ;;; mhc-header.el ends here.
@@ -0,0 +1,563 @@
1
+ ;;; -*- mode: Emacs-Lisp; coding: utf-8 -*-
2
+
3
+ ;; Author: TSUCHIYA Masatoshi <tsuchiya@namazu.org>
4
+ ;; Created: 2000/04/30
5
+ ;; Revised: $Date$
6
+
7
+
8
+ ;;; Commentary:
9
+
10
+ ;; This file is a part of MHC.
11
+
12
+ ;; スケジュールの条件を表すヘッダを、その条件と等しいS式に変換するため
13
+ ;; のライブラリ。
14
+
15
+ ;; S式は、以下のようなローカル変数の束縛の下で評価される。
16
+
17
+ ;; (let ((month 4)
18
+ ;; (day 11048) ; 1970/1/1 からの日数
19
+ ;; (day-of-month 1)
20
+ ;; (day-of-week 6) ; 0 = Sun, 1 = Mon, ...
21
+ ;; (week-of-month 0) ; 0 = 1st, 1 = 2nd, 2 = 3rd, 3 = 4th, 4 = 5th
22
+ ;; (last-week nil)
23
+ ;; (todo nil))
24
+ ;; (eval sexp))
25
+
26
+ ;; 具体的な評価の形式は、mhc-logic-eval-for-date, mhc-db/eval-for-duration
27
+ ;; 関数の定義などを参照。
28
+
29
+ ;; 条件が、Emacs-Lisp の述語のみからなるS式に変換されると、元々の条件
30
+ ;; の意味が分かりづらくなるため、一旦、元々のヘッダとほとんど同じ形式
31
+ ;; のマクロを用いた式に変換する。
32
+
33
+ ;; この中間式を参照することによって、元々の条件に対する意味論的な評価
34
+ ;; が可能となる(mhc-logic-file-to-slot)。
35
+
36
+ ;; また、通常の評価を行う場合は、中間式に含まれるマクロを完全に展開し
37
+ ;; てから行うため(mhc-logic-compile-file)、スピードは高速に保たれる。
38
+
39
+ ;;; Definition:
40
+ (require 'mhc-date)
41
+ (require 'bytecomp)
42
+
43
+ ;;----------------------------------------------------------------------
44
+ ;; MHC-LOGIC 構造体
45
+ ;;----------------------------------------------------------------------
46
+
47
+ ;; MHC-LOGIC ::= [ DAY AND TODO INTERMEDIATE SEXP ]
48
+ ;; DAY ::= INT | NOT_INT
49
+ ;; NOT_INT ::= ( INT . nil )
50
+ ;; INT ::= integer ( represents exceptional date )
51
+ ;; AND ::= conditions ( each condition represents X-SC-Cond: header )
52
+ ;; INTERMEDIATE ::= macro expression
53
+ ;; SEXP ::= full expanded expression
54
+
55
+ ;; mhc-logic/day = 日付(X-SC-Day)による条件
56
+ ;; mhc-logic/and = それ以外のヘッダに基づく条件
57
+ ;; mhc-logic/todo = TODOの順位
58
+ ;; mhc-logic/intermediate = 条件をS式に変換するための中間形式
59
+ ;; mhc-logic-sexp = 完全に展開されたS式
60
+
61
+ (defun mhc-logic-new ()
62
+ (make-vector 5 nil))
63
+
64
+ (defmacro mhc-logic/day (logicinfo)
65
+ `(aref ,logicinfo 0))
66
+ (defmacro mhc-logic/and (logicinfo)
67
+ `(aref ,logicinfo 1))
68
+ (defmacro mhc-logic-todo (logicinfo)
69
+ `(aref ,logicinfo 2))
70
+ (defmacro mhc-logic/intermediate (logicinfo)
71
+ `(aref ,logicinfo 3))
72
+ (defmacro mhc-logic-sexp (logicinfo)
73
+ `(aref ,logicinfo 4))
74
+
75
+ (defmacro mhc-logic/set-day (logicinfo value)
76
+ `(aset ,logicinfo 0 ,value))
77
+ (defmacro mhc-logic/set-and (logicinfo value)
78
+ `(aset ,logicinfo 1 ,value))
79
+ (defmacro mhc-logic/set-todo (logicinfo value)
80
+ `(aset ,logicinfo 2 ,value))
81
+ (defmacro mhc-logic/set-intermediate (logicinfo value)
82
+ `(aset ,logicinfo 3 ,value))
83
+ (defmacro mhc-logic/set-sexp (logicinfo value)
84
+ `(aset ,logicinfo 4 ,value))
85
+
86
+ (defun mhc-logic-day-as-string-list (logicinfo)
87
+ (mapcar (lambda (day)
88
+ (if (consp day)
89
+ (if (null (cdr day))
90
+ (mhc-date-format (car day) "!%04d%02d%02d" yy mm dd)
91
+ (concat
92
+ (mhc-date-format (car day) "%04d%02d%02d" yy mm dd)
93
+ "-"
94
+ (mhc-date-format (cdr day) "%04d%02d%02d" yy mm dd)))
95
+ (mhc-date-format day "%04d%02d%02d" yy mm dd)))
96
+ (mhc-logic/day logicinfo)))
97
+
98
+
99
+ ;;----------------------------------------------------------------------
100
+ ;; 条件式を評価する関数
101
+ ;;----------------------------------------------------------------------
102
+
103
+ (defun mhc-logic-eval-for-date (sexp-list day &optional todo)
104
+ "指定された日のスケジュールを探索"
105
+ (mhc-day-let day
106
+ (let ((week-of-month (/ (+ day-of-month
107
+ (mhc-date-ww (mhc-date-mm-first day))
108
+ -8)
109
+ 7))
110
+ (last-week (> 7 (- (mhc-date/last-day-of-month year month)
111
+ day-of-month)))
112
+ (new (mhc-day-new year month day-of-month day-of-week)))
113
+ (mhc-day-set-schedules new (delq nil
114
+ (mapcar
115
+ (lambda (sexp)
116
+ (and sexp
117
+ (funcall sexp))) sexp-list)))
118
+ new)))
119
+
120
+
121
+
122
+ ;;----------------------------------------------------------------------
123
+ ;; 条件式を生成するための関数群
124
+ ;;----------------------------------------------------------------------
125
+
126
+ ;; S式を表現する中間形式のマクロ
127
+ ;; これらは、条件式の意味論的表示として用いられる。
128
+ (defmacro mhc-logic/condition-month (n) `(eq month ,n))
129
+ (defmacro mhc-logic/condition-day (n) `(eq day ,n))
130
+ (defmacro mhc-logic/condition-day-of-month (n) `(eq day-of-month ,n))
131
+ (defmacro mhc-logic/condition-day-of-week (n) `(eq day-of-week ,n))
132
+ (defmacro mhc-logic/condition-week-of-month (n) `(eq week-of-month ,n))
133
+ (defmacro mhc-logic/condition-last-week () 'last-week)
134
+ (defmacro mhc-logic/condition-duration (begin end) `(and (>= day ,begin) (<= day ,end)))
135
+ (defmacro mhc-logic/condition-duration-begin (begin) `(>= day ,begin))
136
+ (defmacro mhc-logic/condition-duration-end (end) `(<= day ,end))
137
+
138
+ (defconst mhc-logic/space-regexp "[,| \t\n]+"
139
+ "構文要素の区切りに一致する正規表現")
140
+
141
+ (defconst mhc-logic/not-regexp "\\(!\\)?[ \t]*"
142
+ "構文要素の否定に一致する正規表現")
143
+
144
+ (defconst mhc-logic/day-regexp
145
+ "\\([0-9][0-9][0-9][0-9]\\)\\([0-9][0-9]\\)\\([0-9][0-9]\\)"
146
+ "構文要素の日付に一致する正規表現")
147
+
148
+ (defconst mhc-logic/day-of-month-regexp
149
+ "0*\\([1-9]\\|[1-2][0-9]\\|3[01]\\)"
150
+ "構文要素の該当月の何日目かを表す序数に一致する正規表現")
151
+
152
+ (defconst mhc-logic/week-of-month-alist
153
+ '(("1st" 0 (mhc-logic/condition-week-of-month 0))
154
+ ("2nd" 1 (mhc-logic/condition-week-of-month 1))
155
+ ("3rd" 2 (mhc-logic/condition-week-of-month 2))
156
+ ("4th" 3 (mhc-logic/condition-week-of-month 3))
157
+ ("5th" 4 (mhc-logic/condition-week-of-month 4))
158
+ ("last" 5 (mhc-logic/condition-last-week)))
159
+ "構文要素の該当月の何週目かを表す序数の連想配列")
160
+
161
+ (defconst mhc-logic/week-of-month-regexp
162
+ (mhc-regexp-opt (mapcar (function car) mhc-logic/week-of-month-alist) 'paren)
163
+ "構文要素の何週目かを表す序数に一致する正規表現")
164
+
165
+ (defconst mhc-logic/day-of-week-alist
166
+ '(("sun" . 0) ("mon" . 1) ("tue" . 2) ("wed" . 3) ("thu" . 4) ("fri" . 5) ("sat" . 6)
167
+ ("sunday" . 0) ("monday" . 1) ("tuesday" . 2) ("wednesday" . 3) ("thursday" . 4)
168
+ ("friday" . 5) ("saturday" . 6))
169
+ "構文要素の曜日の連想配列")
170
+
171
+ (defconst mhc-logic/day-of-week-regexp
172
+ (mhc-regexp-opt (mapcar (function car) mhc-logic/day-of-week-alist) 'paren)
173
+ "構文要素の曜日に一致する正規表現")
174
+
175
+ (defconst mhc-logic/month-alist
176
+ '(("jan" . 1) ("feb" . 2) ("mar" . 3) ("apr" . 4) ("may" . 5) ("jun" . 6)
177
+ ("jul" . 7) ("aug" . 8) ("sep" . 9) ("oct" . 10) ("nov" . 11) ("dec" . 12)
178
+ ("january" . 1) ("february" . 2) ("march" . 3) ("april" . 4) ("june" . 6)
179
+ ("july" . 7) ("august" . 8) ("september" . 9) ("october" .10) ("november" . 11)
180
+ ("december" . 12))
181
+ "構文要素の月の連想配列")
182
+
183
+ (defconst mhc-logic/month-regexp
184
+ (mhc-regexp-opt (mapcar (function car) mhc-logic/month-alist) 'paren)
185
+ "構文要素の月に一致する正規表現")
186
+
187
+ (defconst mhc-logic/old-style-date-regexp
188
+ "\\([0-9]+\\)[\t ]+\\([A-Z][a-z][a-z]\\)[\t ]+\\([0-9]+\\)"
189
+ "構文要素の旧形式の日付指定に一致する正規表現")
190
+
191
+
192
+ (defmacro mhc-logic/looking-at (&rest regexp)
193
+ "正規表現に一致する構文要素を発見するマクロ"
194
+ `(looking-at (concat ,@regexp mhc-logic/space-regexp)))
195
+
196
+
197
+ (defun mhc-logic-parse-day (logicinfo)
198
+ "X-SC-Day: ヘッダを解析する関数"
199
+ (let ((d) (days (mhc-logic/day logicinfo)))
200
+ (if (looking-at mhc-logic/space-regexp)
201
+ (goto-char (match-end 0)))
202
+ (while (not (eobp))
203
+ (setq
204
+ days
205
+ (cons
206
+ (cond
207
+ ((mhc-logic/looking-at mhc-logic/day-regexp
208
+ "-" mhc-logic/day-regexp)
209
+ (cons
210
+ (mhc-date-new (string-to-number (match-string 1))
211
+ (string-to-number (match-string 2))
212
+ (string-to-number (match-string 3)))
213
+ (mhc-date-new (string-to-number (match-string 4))
214
+ (string-to-number (match-string 5))
215
+ (string-to-number (match-string 6)))))
216
+ ((mhc-logic/looking-at mhc-logic/not-regexp mhc-logic/day-regexp)
217
+ (setq d (mhc-date-new (string-to-number (match-string 2))
218
+ (string-to-number (match-string 3))
219
+ (string-to-number (match-string 4))))
220
+ (if (match-string 1) (cons d nil) d))
221
+ (t
222
+ (error "Parse ERROR !!! (at X-SC-Day:)")))
223
+ days))
224
+ (goto-char (match-end 0)))
225
+ (mhc-logic/set-day logicinfo (nreverse days)))) ;; xxxxx
226
+
227
+
228
+ (defun mhc-logic-parse-old-style-date (logicinfo)
229
+ "X-SC-Date: ヘッダの日付部分を解析する関数"
230
+ (if (looking-at mhc-logic/space-regexp)
231
+ (goto-char (match-end 0)))
232
+ (let (month)
233
+ (if (and (mhc-logic/looking-at mhc-logic/old-style-date-regexp)
234
+ (setq month (cdr (assoc (downcase (match-string 2))
235
+ mhc-logic/month-alist))))
236
+ (let ((year (string-to-number (match-string 3))))
237
+ (mhc-logic/set-day
238
+ logicinfo
239
+ (cons (mhc-date-new (cond ((< year 69)
240
+ (+ year 2000))
241
+ ((< year 1000)
242
+ (+ year 1900))
243
+ (t year))
244
+ month
245
+ (string-to-number (match-string 1)))
246
+ (mhc-logic/day logicinfo)))
247
+ (goto-char (match-end 0)))
248
+ (error "Parse ERROR !!!(at X-SC-Date:)"))))
249
+
250
+
251
+ (defun mhc-logic-parse-cond (logicinfo)
252
+ "X-SC-Cond: ヘッダを解析する関数"
253
+ (let (sexp day-of-month week-of-month day-of-week month)
254
+ (if (looking-at mhc-logic/space-regexp)
255
+ (goto-char (match-end 0)))
256
+ (while (not (eobp))
257
+ (cond
258
+ ;; 何日目
259
+ ((mhc-logic/looking-at mhc-logic/day-of-month-regexp)
260
+ (setq day-of-month
261
+ (cons (list 'mhc-logic/condition-day-of-month (string-to-number (match-string 1)))
262
+ day-of-month)))
263
+ ;; 何週目
264
+ ((mhc-logic/looking-at mhc-logic/week-of-month-regexp)
265
+ (setq week-of-month
266
+ (cons (nth 2 (assoc (downcase (match-string 1))
267
+ mhc-logic/week-of-month-alist))
268
+ week-of-month)))
269
+ ;; 曜日
270
+ ((mhc-logic/looking-at mhc-logic/day-of-week-regexp)
271
+ (setq day-of-week
272
+ (cons (list 'mhc-logic/condition-day-of-week
273
+ (cdr (assoc (downcase (match-string 1))
274
+ mhc-logic/day-of-week-alist)))
275
+ day-of-week)))
276
+ ;; 月
277
+ ((mhc-logic/looking-at mhc-logic/month-regexp)
278
+ (setq month
279
+ (cons (list 'mhc-logic/condition-month
280
+ (cdr (assoc (downcase (match-string 1))
281
+ mhc-logic/month-alist)))
282
+ month)))
283
+ (t ;; 解釈できない要素の場合
284
+ (error "Parse ERROR !!!(at X-SC-Cond:)")))
285
+ (goto-char (match-end 0)))
286
+ (mapc (lambda (s)
287
+ (set s (if (symbol-value s)
288
+ (if (= 1 (length (symbol-value s)))
289
+ (car (symbol-value s))
290
+ (cons 'or (nreverse (symbol-value s)))))))
291
+ '(day-of-month week-of-month day-of-week month))
292
+ (setq sexp (cond
293
+ ((and week-of-month day-of-week) `(and ,week-of-month ,day-of-week))
294
+ (week-of-month week-of-month)
295
+ (day-of-week day-of-week)))
296
+ (if day-of-month (setq sexp (if sexp (list 'or day-of-month sexp) day-of-month)))
297
+ (if month (setq sexp (if sexp (list 'and month sexp) month)))
298
+ (if sexp (mhc-logic/set-and logicinfo (cons sexp (mhc-logic/and logicinfo))))))
299
+
300
+
301
+ (defun mhc-logic-parse-duration (logicinfo)
302
+ "X-SC-Duration: ヘッダを解析する関数"
303
+ (let (sexp)
304
+ (if (looking-at mhc-logic/space-regexp)
305
+ (goto-char (match-end 0)))
306
+ (while (not (eobp))
307
+ (setq sexp
308
+ (cons (cond
309
+ ((mhc-logic/looking-at mhc-logic/day-regexp
310
+ "-" mhc-logic/day-regexp)
311
+ (list 'mhc-logic/condition-duration
312
+ (mhc-date-new (string-to-number (match-string 1))
313
+ (string-to-number (match-string 2))
314
+ (string-to-number (match-string 3)))
315
+ (mhc-date-new (string-to-number (match-string 4))
316
+ (string-to-number (match-string 5))
317
+ (string-to-number (match-string 6)))))
318
+ ((mhc-logic/looking-at mhc-logic/day-regexp "-")
319
+ (list 'mhc-logic/condition-duration-begin
320
+ (mhc-date-new (string-to-number (match-string 1))
321
+ (string-to-number (match-string 2))
322
+ (string-to-number (match-string 3)))))
323
+ ((mhc-logic/looking-at "-" mhc-logic/day-regexp)
324
+ (list 'mhc-logic/condition-duration-end
325
+ (mhc-date-new (string-to-number (match-string 1))
326
+ (string-to-number (match-string 2))
327
+ (string-to-number (match-string 3)))))
328
+ (t ; それ以外の場合
329
+ (error "Parse ERROR !!!(at X-SC-Duration:)")))
330
+ sexp))
331
+ (goto-char (match-end 0)))
332
+ (if sexp
333
+ (mhc-logic/set-and logicinfo (cons (if (= 1 (length sexp))
334
+ (car sexp)
335
+ (cons 'or (nreverse sexp)))
336
+ (mhc-logic/and logicinfo))))))
337
+
338
+ ;; Need to be deleted.
339
+ (defun mhc-logic-parse-todo (logicinfo)
340
+ (if (looking-at mhc-logic/space-regexp)
341
+ (goto-char (match-end 0)))
342
+ (let ((content (buffer-substring
343
+ (point) (progn (skip-chars-forward "0-9") (point)))))
344
+ (if (looking-at mhc-logic/space-regexp)
345
+ (goto-char (match-end 0)))
346
+ (if (eobp)
347
+ (mhc-logic/set-todo logicinfo (string-to-number content))
348
+ (error "Parse ERROR !!!(at X-SC-Todo:)"))))
349
+
350
+
351
+ (defun mhc-logic-compile-file (record)
352
+ "日付を指定されたときに、関係するスケジュールを選びだすためのS式を生成する"
353
+ (let ((sexp) (schedules (mhc-record-schedules record))
354
+ (byte-compile-warnings))
355
+ (while schedules
356
+ (setq sexp (cons (mhc-logic/compile-schedule (car schedules)) sexp)
357
+ schedules (cdr schedules)))
358
+ (setq sexp (delq nil sexp))
359
+ (mhc-record-set-sexp
360
+ record
361
+ (if sexp
362
+ (let (year month day day-of-month day-of-week week-of-month last-week todo)
363
+ (byte-compile
364
+ (list 'lambda ()
365
+ (if (= 1 (length sexp))
366
+ (car sexp)
367
+ (cons 'or (nreverse sexp))))))))))
368
+
369
+
370
+ (defun mhc-logic/compile-schedule (schedule)
371
+ "mhc-logic-compile-file の下請け関数"
372
+ (let* ((logicinfo (mhc-schedule-condition schedule)) sexp)
373
+ ;; 日付による例外条件とそれ以外の条件を結合した論理式を生成する
374
+ (setq sexp
375
+ (nreverse
376
+ (delq nil
377
+ (cons (let ((and (mhc-logic/and logicinfo)))
378
+ (if and
379
+ (if (= 1 (length and))
380
+ (list (car and) t)
381
+ (list (cons 'and (reverse and)) t))))
382
+ (mapcar (lambda (day)
383
+ (if (consp day)
384
+ (if (null (cdr day))
385
+ `((mhc-logic/condition-day ,(car day)) nil)
386
+ `((mhc-logic/condition-duration ,(car day) ,(cdr day)) t))
387
+ `((mhc-logic/condition-day ,day) t)))
388
+ (mhc-logic/day logicinfo))))))
389
+ (if sexp
390
+ (progn
391
+ ;; 条件の数によって、条件式を最適化しておく
392
+ (setq sexp (if (= 1 (length sexp))
393
+ (if (nth 1 (car sexp))
394
+ (car (car sexp))
395
+ `(not ,(car (car sexp))))
396
+ (cons 'cond sexp)))
397
+ ;; TODOに基づく条件を加える
398
+ (setq sexp (if (mhc-logic-todo logicinfo)
399
+ `(if todo t ,sexp)
400
+ `(if todo nil ,sexp))))
401
+ (if (mhc-logic-todo logicinfo)
402
+ (setq sexp 'todo)))
403
+ ;; この中間形式を保存しておく
404
+ (mhc-logic/set-intermediate logicinfo sexp)
405
+ ;; 中間形式を展開する
406
+ (mhc-logic/set-sexp logicinfo
407
+ (if sexp (mhc-logic/macroexpand
408
+ `(if ,sexp ,schedule))))))
409
+
410
+
411
+ (defun mhc-logic/macroexpand (sexp)
412
+ "部分式に遡ってマクロを展開する関数"
413
+ (macroexpand
414
+ (if (listp sexp)
415
+ (mapcar (function mhc-logic/macroexpand) sexp)
416
+ sexp)))
417
+
418
+
419
+
420
+ ;;----------------------------------------------------------------------
421
+ ;; mhc-logic-record-to-slot
422
+ ;;----------------------------------------------------------------------
423
+
424
+ (defun mhc-logic-record-to-slot (record)
425
+ "Return appropriate slot key, ( YEAR . MONTH ), for RECORD."
426
+ (let ((schedules (mhc-record-schedules record))
427
+ pre-month cur-month)
428
+ (while (and schedules
429
+ (not (mhc-logic-todo (mhc-schedule-condition (car schedules))))
430
+ (setq cur-month
431
+ (mhc-logic/check-sexp-range
432
+ (mhc-schedule-condition (car schedules))))
433
+ (if pre-month
434
+ (equal pre-month cur-month)
435
+ (setq pre-month cur-month)))
436
+ (setq schedules (cdr schedules)))
437
+ (if schedules (cons nil nil) cur-month)))
438
+
439
+
440
+ (defun mhc-logic/day-to-slot (day)
441
+ "Generate slot key by DAY, which represents the number of days from 1970/01/01,"
442
+ (mhc-day-let day (cons year month)))
443
+
444
+
445
+ (defun mhc-logic/check-sexp-range (logicinfo)
446
+ "Estimate appropriate slot for LOGICINFO, with macro expression."
447
+ (let (duration-begin duration-end day-list month-list require-duration)
448
+ (mhc-logic/check-sexp-range-internal (mhc-logic/intermediate logicinfo))
449
+ (if (or (> (length month-list) 1)
450
+ (if require-duration
451
+ (or (not duration-begin)
452
+ (not duration-end)))
453
+ (progn
454
+ (if day-list (setq day-list (sort day-list '<)))
455
+ (not (equal
456
+ (setq duration-begin
457
+ (if day-list
458
+ (mhc-logic/day-to-slot
459
+ (if duration-begin
460
+ (min (car day-list) duration-begin)
461
+ (car day-list)))))
462
+ (if day-list
463
+ (mhc-logic/day-to-slot
464
+ (if duration-end
465
+ (max (nth (1- (length day-list)) day-list) duration-end)
466
+ (nth (1- (length day-list)) day-list))))))))
467
+ '(nil . nil)
468
+ duration-begin)))
469
+
470
+
471
+ (eval-when-compile
472
+ (defvar day-list)
473
+ (defvar duration-begin)
474
+ (defvar duration-end)
475
+ (defvar month-list)
476
+ (defvar require-duration))
477
+
478
+ (defun mhc-logic/check-sexp-range-internal (sexp)
479
+ "Recursive subroutine of mhc-logic/check-sexp-range."
480
+ (if (listp sexp)
481
+ (cond
482
+ ((eq (car sexp) 'mhc-logic/condition-duration)
483
+ (if (or (not duration-begin)
484
+ (< (nth 1 sexp) duration-begin))
485
+ (setq duration-begin (nth 1 sexp)))
486
+ (if (or (not duration-end)
487
+ (> (nth 1 sexp) duration-end))
488
+ (setq duration-end (nth 2 sexp))))
489
+ ((eq (car sexp) 'mhc-logic/condition-duration-begin)
490
+ (if (or (not duration-begin)
491
+ (< (nth 1 sexp) duration-begin))
492
+ (setq duration-begin (nth 1 sexp))))
493
+ ((eq (car sexp) 'mhc-logic/condition-duration-end)
494
+ (if (or (not duration-end)
495
+ (> (nth 1 sexp) duration-end))
496
+ (setq duration-end (nth 1 sexp))))
497
+ ((eq (car sexp) 'mhc-logic/condition-day)
498
+ (setq day-list (cons (nth 1 sexp) day-list)))
499
+ ((eq (car sexp) 'mhc-logic/condition-month)
500
+ (or (memq (nth 1 sexp) month-list)
501
+ (setq month-list (cons (nth 1 sexp) month-list)))
502
+ (setq require-duration t))
503
+ ((eq (car sexp) 'mhc-logic/condition-day-of-week)
504
+ (setq require-duration t))
505
+ ((eq (car sexp) 'mhc-logic/condition-day-of-month)
506
+ (setq require-duration t))
507
+ (t
508
+ (while sexp
509
+ (mhc-logic/check-sexp-range-internal (car sexp))
510
+ (setq sexp (cdr sexp)))))))
511
+
512
+
513
+ ; (defun mhc-logic-occur-multiple-p (logicinfo)
514
+ ; "If LOGICINFO occurs multiple times, return t."
515
+ ; (let (duration-begin duration-end day-list month-list require-duration)
516
+ ; (mhc-logic/check-sexp-range-internal (mhc-logic/intermediate logicinfo))
517
+ ; (if (or duration-begin
518
+ ; duration-end
519
+ ; month-list
520
+ ; (> (length day-list) 1))
521
+ ; t)))
522
+
523
+ ;; rough (but safety) check -- nom
524
+ (defun mhc-logic-occur-multiple-p (logicinfo)
525
+ "If LOGICINFO occurs multiple times, return t."
526
+ (if (or (mhc-logic/and logicinfo)
527
+ (> (length (mhc-logic/day logicinfo)) 1))
528
+ t))
529
+
530
+ (provide 'mhc-logic)
531
+
532
+ ;;; Copyright Notice:
533
+
534
+ ;; Copyright (C) 1999, 2000 Yoshinari Nomura. All rights reserved.
535
+ ;; Copyright (C) 2000 MHC developing team. All rights reserved.
536
+
537
+ ;; Redistribution and use in source and binary forms, with or without
538
+ ;; modification, are permitted provided that the following conditions
539
+ ;; are met:
540
+ ;;
541
+ ;; 1. Redistributions of source code must retain the above copyright
542
+ ;; notice, this list of conditions and the following disclaimer.
543
+ ;; 2. Redistributions in binary form must reproduce the above copyright
544
+ ;; notice, this list of conditions and the following disclaimer in the
545
+ ;; documentation and/or other materials provided with the distribution.
546
+ ;; 3. Neither the name of the team nor the names of its contributors
547
+ ;; may be used to endorse or promote products derived from this software
548
+ ;; without specific prior written permission.
549
+ ;;
550
+ ;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS''
551
+ ;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
552
+ ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
553
+ ;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
554
+ ;; THE TEAM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
555
+ ;; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
556
+ ;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
557
+ ;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
558
+ ;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
559
+ ;; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
560
+ ;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
561
+ ;; OF THE POSSIBILITY OF SUCH DAMAGE.
562
+
563
+ ;;; mhc-logic.el ends here