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.
- checksums.yaml +7 -0
- data/.gitignore +27 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/COPYRIGHT +28 -0
- data/Gemfile +8 -0
- data/README.org +209 -0
- data/Rakefile +13 -0
- data/bin/mhc +312 -0
- data/emacs/Cask +25 -0
- data/emacs/Makefile +58 -0
- data/emacs/mhc-calendar.el +1723 -0
- data/emacs/mhc-calfw.el +135 -0
- data/emacs/mhc-compat.el +90 -0
- data/emacs/mhc-date.el +642 -0
- data/emacs/mhc-day.el +149 -0
- data/emacs/mhc-db.el +158 -0
- data/emacs/mhc-draft.el +211 -0
- data/emacs/mhc-e21.el +167 -0
- data/emacs/mhc-face.el +236 -0
- data/emacs/mhc-file.el +224 -0
- data/emacs/mhc-guess.el +648 -0
- data/emacs/mhc-header.el +176 -0
- data/emacs/mhc-logic.el +563 -0
- data/emacs/mhc-message.el +130 -0
- data/emacs/mhc-minibuf.el +466 -0
- data/emacs/mhc-misc.el +248 -0
- data/emacs/mhc-mua.el +260 -0
- data/emacs/mhc-parse.el +286 -0
- data/emacs/mhc-process.el +35 -0
- data/emacs/mhc-ps.el +1174 -0
- data/emacs/mhc-record.el +201 -0
- data/emacs/mhc-schedule.el +202 -0
- data/emacs/mhc-summary.el +763 -0
- data/emacs/mhc-sync.el +158 -0
- data/emacs/mhc-vars.el +149 -0
- data/emacs/mhc.el +1114 -0
- data/icons/Anniversary.xbm +6 -0
- data/icons/Anniversary.xpm +27 -0
- data/icons/Birthday.xbm +6 -0
- data/icons/Birthday.xpm +25 -0
- data/icons/Business.xbm +6 -0
- data/icons/Business.xpm +24 -0
- data/icons/CheckBox.xbm +6 -0
- data/icons/CheckBox.xpm +24 -0
- data/icons/CheckedBox.xbm +6 -0
- data/icons/CheckedBox.xpm +25 -0
- data/icons/Conflict.xbm +6 -0
- data/icons/Conflict.xpm +22 -0
- data/icons/Date.xbm +6 -0
- data/icons/Date.xpm +29 -0
- data/icons/Holiday.xbm +6 -0
- data/icons/Holiday.xpm +25 -0
- data/icons/Link.xbm +6 -0
- data/icons/Link.xpm +25 -0
- data/icons/Other.xbm +6 -0
- data/icons/Other.xpm +28 -0
- data/icons/Party.xbm +6 -0
- data/icons/Party.xpm +23 -0
- data/icons/Private.xbm +6 -0
- data/icons/Private.xpm +26 -0
- data/icons/Recurrence.xbm +6 -0
- data/icons/Recurrence.xpm +98 -0
- data/icons/Vacation.xbm +6 -0
- data/icons/Vacation.xpm +26 -0
- data/lib/mhc.rb +45 -0
- data/lib/mhc/builder.rb +64 -0
- data/lib/mhc/caldav.rb +304 -0
- data/lib/mhc/calendar.rb +106 -0
- data/lib/mhc/command.rb +13 -0
- data/lib/mhc/command/cache.rb +14 -0
- data/lib/mhc/command/completions.rb +108 -0
- data/lib/mhc/command/init.rb +133 -0
- data/lib/mhc/command/scan.rb +33 -0
- data/lib/mhc/command/sync.rb +22 -0
- data/lib/mhc/config.rb +229 -0
- data/lib/mhc/converter.rb +330 -0
- data/lib/mhc/datastore.rb +164 -0
- data/lib/mhc/date_enumerator.rb +274 -0
- data/lib/mhc/date_frame.rb +124 -0
- data/lib/mhc/date_helper.rb +49 -0
- data/lib/mhc/etag.rb +68 -0
- data/lib/mhc/event.rb +396 -0
- data/lib/mhc/formatter.rb +312 -0
- data/lib/mhc/logger.rb +94 -0
- data/lib/mhc/modifier.rb +149 -0
- data/lib/mhc/occurrence.rb +94 -0
- data/lib/mhc/occurrence_enumerator.rb +113 -0
- data/lib/mhc/property_value.rb +33 -0
- data/lib/mhc/property_value/date.rb +190 -0
- data/lib/mhc/property_value/integer.rb +15 -0
- data/lib/mhc/property_value/list.rb +41 -0
- data/lib/mhc/property_value/period.rb +49 -0
- data/lib/mhc/property_value/range.rb +100 -0
- data/lib/mhc/property_value/recurrence_condition.rb +272 -0
- data/lib/mhc/property_value/text.rb +11 -0
- data/lib/mhc/property_value/time.rb +45 -0
- data/lib/mhc/query.rb +210 -0
- data/lib/mhc/sync.rb +46 -0
- data/lib/mhc/sync/driver.rb +108 -0
- data/lib/mhc/sync/status.rb +70 -0
- data/lib/mhc/sync/status_manager.rb +142 -0
- data/lib/mhc/sync/strategy.rb +233 -0
- data/lib/mhc/sync/syncinfo.rb +98 -0
- data/lib/mhc/templates/config.yml.erb +142 -0
- data/lib/mhc/version.rb +4 -0
- data/lib/mhc/webdav.rb +319 -0
- data/mhc.gemspec +24 -0
- data/samples/DOT.mhc-config.yml +116 -0
- data/samples/japanese-holidays.mhcc +153 -0
- data/samples/mhc-completions.zsh +11 -0
- data/spec/mhc_spec.rb +682 -0
- data/spec/spec_helper.rb +9 -0
- data/xpm/close.xpm +18 -0
- data/xpm/delete.xpm +19 -0
- data/xpm/exit.xpm +18 -0
- data/xpm/month.xpm +18 -0
- data/xpm/next.xpm +18 -0
- data/xpm/next2.xpm +18 -0
- data/xpm/next_year.xpm +18 -0
- data/xpm/open.xpm +19 -0
- data/xpm/prev.xpm +18 -0
- data/xpm/prev2.xpm +18 -0
- data/xpm/prev_year.xpm +18 -0
- data/xpm/save.xpm +19 -0
- data/xpm/today.xpm +18 -0
- metadata +214 -0
data/emacs/mhc-sync.el
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
;;; -*- emacs-lisp -*-
|
2
|
+
;; mhc-sync.el -- mhc-sync (ruby script) interface
|
3
|
+
;;
|
4
|
+
;; Author: Hideyuki SHIRAI <shirai@quickhack.net>
|
5
|
+
;;
|
6
|
+
;; Created: 2000/06/12
|
7
|
+
;; Revised: $Date: 2002/11/11 05:27:15 $
|
8
|
+
|
9
|
+
;;; Commentary:
|
10
|
+
|
11
|
+
;; This file is a part of MHC, includes backend functions to
|
12
|
+
;; manipulate schedule files.
|
13
|
+
|
14
|
+
|
15
|
+
;;; Customize Variables:
|
16
|
+
(defcustom mhc-sync-id nil
|
17
|
+
"*Identical id of mhc-sync (-x option)."
|
18
|
+
:group 'mhc
|
19
|
+
:type 'string)
|
20
|
+
|
21
|
+
(defcustom mhc-sync-remote nil
|
22
|
+
"*Remote server repository of mhc-sync ([user@]remote.host[:dir])."
|
23
|
+
:group 'mhc
|
24
|
+
:type 'string)
|
25
|
+
|
26
|
+
(defcustom mhc-sync-localdir nil
|
27
|
+
"*Local repository directory of mhc-sync (-r option)."
|
28
|
+
:group 'mhc
|
29
|
+
:type 'string)
|
30
|
+
|
31
|
+
(defcustom mhc-sync-coding-system
|
32
|
+
(if (>= emacs-major-version 20) 'undecided '*autoconv*)
|
33
|
+
"*Default coding system for process of mhc-sync."
|
34
|
+
:group 'mhc
|
35
|
+
:type 'symbol)
|
36
|
+
|
37
|
+
|
38
|
+
;;; Interanal variabiles:
|
39
|
+
(defconst mhc-sync/passwd-regexp "password:\\|passphrase:\\|Enter passphrase")
|
40
|
+
|
41
|
+
(defvar mhc-sync/process nil)
|
42
|
+
|
43
|
+
(defvar mhc-sync/req-passwd nil)
|
44
|
+
|
45
|
+
|
46
|
+
;;; Code:
|
47
|
+
(defun mhc-sync/backup-and-remove (file &optional offline)
|
48
|
+
"Backend function to remove FILE."
|
49
|
+
(let ((file (expand-file-name file))
|
50
|
+
(new-path (expand-file-name
|
51
|
+
"trash"
|
52
|
+
(mhc-config-base-directory))))
|
53
|
+
(or (file-directory-p new-path)
|
54
|
+
(make-directory new-path))
|
55
|
+
(rename-file file (mhc-misc-get-new-path new-path file))))
|
56
|
+
|
57
|
+
(defun mhc-sync/start-process (&optional full)
|
58
|
+
(cond
|
59
|
+
((not (and (stringp mhc-sync-remote) (stringp mhc-sync-id)))
|
60
|
+
(message "No remote server specified.")
|
61
|
+
nil)
|
62
|
+
((processp mhc-sync/process)
|
63
|
+
(message "another mhc-sync running.")
|
64
|
+
nil)
|
65
|
+
(t
|
66
|
+
(let ((buf (mhc-get-buffer-create " *mhc-sync*"))
|
67
|
+
(ldir (expand-file-name (or mhc-sync-localdir "~/Mail/schedule"))))
|
68
|
+
(mhc-window-push)
|
69
|
+
(pop-to-buffer buf)
|
70
|
+
(setq buffer-read-only nil)
|
71
|
+
(erase-buffer)
|
72
|
+
(setq buffer-read-only t)
|
73
|
+
(message "mhc-sync...")
|
74
|
+
(setq mhc-sync/req-passwd t)
|
75
|
+
(setq mhc-sync/process
|
76
|
+
(apply (function start-process)
|
77
|
+
"mhc-sync" buf "mhc-sync"
|
78
|
+
(list "-x" mhc-sync-id "-r" ldir mhc-sync-remote)))
|
79
|
+
(set-process-coding-system mhc-sync/process mhc-sync-coding-system)
|
80
|
+
(set-process-filter mhc-sync/process 'mhc-sync/filter)
|
81
|
+
(set-process-sentinel mhc-sync/process 'mhc-sync/sentinel)
|
82
|
+
(if (featurep 'xemacs)
|
83
|
+
(while mhc-sync/process
|
84
|
+
(accept-process-output))
|
85
|
+
(while mhc-sync/process
|
86
|
+
(sit-for 0.1)
|
87
|
+
(discard-input)))
|
88
|
+
(sit-for 1)
|
89
|
+
(mhc-window-pop)
|
90
|
+
(or (and (mhc-summary-buffer-p)
|
91
|
+
(mhc-rescan-month mhc-default-hide-private-schedules))
|
92
|
+
(and (mhc-calendar-p) (mhc-calendar-rescan)))
|
93
|
+
t))))
|
94
|
+
|
95
|
+
(defun mhc-sync/filter (process string)
|
96
|
+
(if (bufferp (process-buffer process))
|
97
|
+
(let ((obuf (buffer-name)))
|
98
|
+
(unwind-protect
|
99
|
+
(progn
|
100
|
+
(set-buffer (process-buffer process))
|
101
|
+
(let ((buffer-read-only nil)
|
102
|
+
passwd)
|
103
|
+
(goto-char (point-max))
|
104
|
+
(insert string)
|
105
|
+
(cond
|
106
|
+
((and mhc-sync/req-passwd
|
107
|
+
(string-match mhc-sync/passwd-regexp string))
|
108
|
+
(setq passwd (mhc-misc-read-passwd string))
|
109
|
+
(process-send-string process (concat passwd "\n")))
|
110
|
+
((string-match "---------------------" string)
|
111
|
+
(setq mhc-sync/req-passwd nil)))))
|
112
|
+
(if (get-buffer obuf)
|
113
|
+
(set-buffer obuf))))))
|
114
|
+
|
115
|
+
(defun mhc-sync/sentinel (process event)
|
116
|
+
(when (bufferp (process-buffer process))
|
117
|
+
(pop-to-buffer (process-buffer process))
|
118
|
+
(let ((buffer-read-only nil))
|
119
|
+
(goto-char (point-max))
|
120
|
+
(insert "<<<transfer finish>>>")))
|
121
|
+
(setq mhc-sync/process nil))
|
122
|
+
|
123
|
+
|
124
|
+
(provide 'mhc-sync)
|
125
|
+
(put 'mhc-sync 'remove 'mhc-sync/backup-and-remove)
|
126
|
+
(put 'mhc-sync 'sync 'mhc-sync/start-process)
|
127
|
+
|
128
|
+
;;; Copyright Notice:
|
129
|
+
|
130
|
+
;; Copyright (C) 2000 MHC developing team. All rights reserved.
|
131
|
+
|
132
|
+
;; Redistribution and use in source and binary forms, with or without
|
133
|
+
;; modification, are permitted provided that the following conditions
|
134
|
+
;; are met:
|
135
|
+
;;
|
136
|
+
;; 1. Redistributions of source code must retain the above copyright
|
137
|
+
;; notice, this list of conditions and the following disclaimer.
|
138
|
+
;; 2. Redistributions in binary form must reproduce the above copyright
|
139
|
+
;; notice, this list of conditions and the following disclaimer in the
|
140
|
+
;; documentation and/or other materials provided with the distribution.
|
141
|
+
;; 3. Neither the name of the team nor the names of its contributors
|
142
|
+
;; may be used to endorse or promote products derived from this software
|
143
|
+
;; without specific prior written permission.
|
144
|
+
;;
|
145
|
+
;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS''
|
146
|
+
;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
147
|
+
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
148
|
+
;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
149
|
+
;; THE TEAM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
150
|
+
;; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
151
|
+
;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
152
|
+
;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
153
|
+
;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
154
|
+
;; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
155
|
+
;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
156
|
+
;; OF THE POSSIBILITY OF SUCH DAMAGE.
|
157
|
+
|
158
|
+
;; mhc-sync.el ends here
|
data/emacs/mhc-vars.el
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
;;; -*- mode: Emacs-Lisp; coding: utf-8 -*-
|
2
|
+
|
3
|
+
;; Author: Yoshinari Nomura <nom@quickhack.net>,
|
4
|
+
;; Created: 2000/04/30
|
5
|
+
;; Revised: $Date$
|
6
|
+
|
7
|
+
|
8
|
+
;;; Commentary:
|
9
|
+
|
10
|
+
;; This file is a part of MHC, and includes defintions of global
|
11
|
+
;; confiration variables.
|
12
|
+
|
13
|
+
|
14
|
+
;;; Code:
|
15
|
+
(require 'mhc-compat)
|
16
|
+
(require 'mhc-process)
|
17
|
+
|
18
|
+
|
19
|
+
;;; Constants:
|
20
|
+
(defconst mhc-version "mhc 1.0.0")
|
21
|
+
|
22
|
+
|
23
|
+
;;; Configration Variables:
|
24
|
+
(defgroup mhc nil
|
25
|
+
"Various sorts of MH Calender."
|
26
|
+
:group 'mail)
|
27
|
+
|
28
|
+
(defcustom mhc-mailer-package 'mua
|
29
|
+
"*Variable to set your favorite mailer."
|
30
|
+
:group 'mhc
|
31
|
+
:type '(radio (const :tag "Mew" mew)
|
32
|
+
(const :tag "Wanderlust" wl)
|
33
|
+
(const :tag "Gnus" gnus)))
|
34
|
+
|
35
|
+
(defcustom mhc-start-day-of-week 0
|
36
|
+
"*Day of the week as the start of the week."
|
37
|
+
:group 'mhc
|
38
|
+
:type '(choice (const :tag "Sunday" 0)
|
39
|
+
(const :tag "Monday" 1)
|
40
|
+
(const :tag "Tuesday" 2)
|
41
|
+
(const :tag "Wednesday" 3)
|
42
|
+
(const :tag "Thursday" 4)
|
43
|
+
(const :tag "Friday" 5)
|
44
|
+
(const :tag "Saturday" 6)))
|
45
|
+
|
46
|
+
(defcustom mhc-insert-calendar t
|
47
|
+
"*If non nil value, display vertical calender."
|
48
|
+
:group 'mhc
|
49
|
+
:type 'boolean)
|
50
|
+
|
51
|
+
(defcustom mhc-vertical-calendar-length 3
|
52
|
+
"*Length of vertical calendar in summary buffer."
|
53
|
+
:group 'mhc
|
54
|
+
:type '(radio (integer :tag "Show length (current month is center)" 3)
|
55
|
+
(cons (integer :tag " Show length" 3)
|
56
|
+
(integer :tag "Length of before current" 1))))
|
57
|
+
|
58
|
+
(defcustom mhc-default-coding-system
|
59
|
+
(if (>= emacs-major-version 20) 'utf-8-unix '*iso-2022-ss2-7*)
|
60
|
+
"*Default coding system for MHC schedule files."
|
61
|
+
:group 'mhc
|
62
|
+
:type 'symbol)
|
63
|
+
|
64
|
+
(defcustom mhc-default-hide-private-schedules nil
|
65
|
+
"*If non-nil value, hide private schedules."
|
66
|
+
:group 'mhc
|
67
|
+
:type 'boolean)
|
68
|
+
|
69
|
+
(defcustom mhc-category-as-private '("private")
|
70
|
+
"*String list of private categories."
|
71
|
+
:group 'mhc
|
72
|
+
:type '(repeat (string :tag "Category")))
|
73
|
+
|
74
|
+
(defcustom mhc-default-network-status t
|
75
|
+
"*Flag of the default network status."
|
76
|
+
:group 'mhc
|
77
|
+
:type 'boolean)
|
78
|
+
|
79
|
+
(defcustom mhc-show-network-status t
|
80
|
+
"*Flag to show the network status."
|
81
|
+
:group 'mhc
|
82
|
+
:type 'boolean)
|
83
|
+
|
84
|
+
(defcustom mhc-use-cache t
|
85
|
+
"*Flag to decide whether to use cache or not."
|
86
|
+
:group 'mhc
|
87
|
+
:type '(radio (const :tag "Use" t)
|
88
|
+
(const :tag "Lazy check" 0)
|
89
|
+
(const :tag "No use" nil)))
|
90
|
+
|
91
|
+
(defcustom mhc-use-wide-scope nil
|
92
|
+
"*Wide scope method in summary mode."
|
93
|
+
:group 'mhc
|
94
|
+
:type '(radio (const :tag "No use" nil)
|
95
|
+
(const :tag "Complete week scope" week)
|
96
|
+
(const :tag "Wide week scope" wide)
|
97
|
+
(integer :tag "Scope wide size (>=0)" 3)))
|
98
|
+
|
99
|
+
(defcustom mhc-default-alarm "5 minute"
|
100
|
+
"*Default alarm string in making draft."
|
101
|
+
:group 'mhc
|
102
|
+
:type 'string)
|
103
|
+
|
104
|
+
(defcustom mhc-ask-alarm nil
|
105
|
+
"*If non-nil value, ask the alarm string in making draft."
|
106
|
+
:group 'mhc
|
107
|
+
:type 'boolean)
|
108
|
+
|
109
|
+
(defun mhc-config-get-property (&optional dot-separated-key)
|
110
|
+
(mhc-process-send-command
|
111
|
+
(format "config --format=emacs %s" (or dot-separated-key ""))))
|
112
|
+
|
113
|
+
(defun mhc-config-base-directory ()
|
114
|
+
(expand-file-name (mhc-config-get-property "general.repository")))
|
115
|
+
|
116
|
+
(provide 'mhc-vars)
|
117
|
+
|
118
|
+
;;; Copyright Notice:
|
119
|
+
|
120
|
+
;; Copyright (C) 1999, 2000 Yoshinari Nomura. All rights reserved.
|
121
|
+
;; Copyright (C) 2000 MHC developing team. All rights reserved.
|
122
|
+
|
123
|
+
;; Redistribution and use in source and binary forms, with or without
|
124
|
+
;; modification, are permitted provided that the following conditions
|
125
|
+
;; are met:
|
126
|
+
;;
|
127
|
+
;; 1. Redistributions of source code must retain the above copyright
|
128
|
+
;; notice, this list of conditions and the following disclaimer.
|
129
|
+
;; 2. Redistributions in binary form must reproduce the above copyright
|
130
|
+
;; notice, this list of conditions and the following disclaimer in the
|
131
|
+
;; documentation and/or other materials provided with the distribution.
|
132
|
+
;; 3. Neither the name of the team nor the names of its contributors
|
133
|
+
;; may be used to endorse or promote products derived from this software
|
134
|
+
;; without specific prior written permission.
|
135
|
+
;;
|
136
|
+
;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS''
|
137
|
+
;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
138
|
+
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
139
|
+
;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
140
|
+
;; THE TEAM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
141
|
+
;; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
142
|
+
;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
143
|
+
;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
144
|
+
;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
145
|
+
;; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
146
|
+
;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
147
|
+
;; OF THE POSSIBILITY OF SUCH DAMAGE.
|
148
|
+
|
149
|
+
;;; mhc-vars.el ends here
|
data/emacs/mhc.el
ADDED
@@ -0,0 +1,1114 @@
|
|
1
|
+
;;; mhc.el --- MH Calendar.
|
2
|
+
|
3
|
+
;; Author: Yoshinari Nomura <nom@quickhack.net>
|
4
|
+
;;
|
5
|
+
;; Created: 1994/07/04
|
6
|
+
;; Revised: $Date: 2009/05/31 12:54:50 $
|
7
|
+
|
8
|
+
;;;
|
9
|
+
;;; Commentary:
|
10
|
+
;;;
|
11
|
+
|
12
|
+
;; Mhc is the personal schedule management package cooperating
|
13
|
+
;; with Mew, Wanderlust or Gnus.
|
14
|
+
;;
|
15
|
+
;; Minimum setup:
|
16
|
+
;;
|
17
|
+
;; for Mew user:
|
18
|
+
;; (autoload 'mhc-mew-setup "mhc-mew")
|
19
|
+
;; (add-hook 'mew-init-hook 'mhc-mew-setup)
|
20
|
+
;;
|
21
|
+
;; for Wanderlust user:
|
22
|
+
;; (autoload 'mhc-wl-setup "mhc-wl")
|
23
|
+
;; (add-hook 'wl-init-hook 'mhc-wl-setup)
|
24
|
+
;;
|
25
|
+
;; for Gnus user:
|
26
|
+
;; (autoload 'mhc-gnus-setup "mhc-gnus")
|
27
|
+
;; (add-hook 'gnus-startup-hook 'mhc-gnus-setup)
|
28
|
+
|
29
|
+
;;; Code:
|
30
|
+
|
31
|
+
(eval-when-compile (require 'cl))
|
32
|
+
|
33
|
+
;; For Mule 2.3
|
34
|
+
(eval-and-compile
|
35
|
+
(when (boundp 'MULE)
|
36
|
+
(require 'poe)
|
37
|
+
(require 'pcustom)))
|
38
|
+
|
39
|
+
(require 'mhc-vars)
|
40
|
+
(require 'mhc-record)
|
41
|
+
(require 'mhc-parse)
|
42
|
+
(require 'mhc-file)
|
43
|
+
(require 'mhc-process)
|
44
|
+
(require 'mhc-db)
|
45
|
+
(require 'mhc-message)
|
46
|
+
(require 'mhc-misc)
|
47
|
+
(require 'mhc-date)
|
48
|
+
(require 'mhc-guess)
|
49
|
+
(require 'mhc-schedule)
|
50
|
+
(require 'mhc-face)
|
51
|
+
(require 'mhc-calendar)
|
52
|
+
(require 'mhc-draft)
|
53
|
+
|
54
|
+
(cond
|
55
|
+
((eval-when-compile (and (not (featurep 'xemacs))
|
56
|
+
(>= emacs-major-version 21)
|
57
|
+
(if (eq system-type 'windows-nt)
|
58
|
+
;; Meadow2 or NTEmacs21.3(and the later
|
59
|
+
;; version) supports the image feature.
|
60
|
+
(or (featurep 'meadow)
|
61
|
+
(>= emacs-major-version 22)
|
62
|
+
(>= emacs-minor-version 3))
|
63
|
+
t)))
|
64
|
+
(require 'mhc-e21))
|
65
|
+
((eval-when-compile
|
66
|
+
(condition-case nil
|
67
|
+
(require 'bitmap)
|
68
|
+
(error nil)))
|
69
|
+
(require 'mhc-bm))
|
70
|
+
((eval-when-compile (featurep 'xemacs))
|
71
|
+
(require 'mhc-xmas))
|
72
|
+
(t (defun mhc-use-icon-p ())))
|
73
|
+
|
74
|
+
(require 'mhc-minibuf)
|
75
|
+
(require 'mhc-summary)
|
76
|
+
(provide 'mhc)
|
77
|
+
|
78
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
79
|
+
;; Menu setup
|
80
|
+
;;
|
81
|
+
(defvar mhc-mode-menu-spec
|
82
|
+
'("Mhc"
|
83
|
+
["This month" mhc-goto-this-month t]
|
84
|
+
["Next month" mhc-goto-next-month t]
|
85
|
+
["Prev month" mhc-goto-prev-month t]
|
86
|
+
["Goto month" mhc-goto-month t]
|
87
|
+
["Goto date" mhc-goto-date t]
|
88
|
+
["Import" mhc-import t]
|
89
|
+
["Set category" mhc-set-default-category t]
|
90
|
+
"----"
|
91
|
+
["Goto today" mhc-goto-today (mhc-summary-buffer-p)]
|
92
|
+
["Modify" mhc-modify (mhc-summary-buffer-p)]
|
93
|
+
["Edit" mhc-edit (mhc-summary-buffer-p)]
|
94
|
+
["Rescan" mhc-rescan-month (mhc-summary-buffer-p)]
|
95
|
+
["Delete" mhc-delete (mhc-summary-buffer-p)]
|
96
|
+
["Insert Schedule" mhc-insert-schedule (not buffer-read-only)]
|
97
|
+
["3 months Mini calendar" mhc-calendar t]
|
98
|
+
["Toggle 3 months calendar" mhc-calendar-toggle-insert-rectangle
|
99
|
+
(mhc-summary-buffer-p)]
|
100
|
+
"----"
|
101
|
+
["Reset" mhc-reset (mhc-summary-buffer-p)]
|
102
|
+
("Network"
|
103
|
+
["Online" mhc-file-toggle-offline mhc-file/offline]
|
104
|
+
["Offline" mhc-file-toggle-offline (not mhc-file/offline)]
|
105
|
+
["Sync" mhc-file-sync (and (not (and mhc-file/offline
|
106
|
+
(not mhc-file-sync-enable-offline)))
|
107
|
+
(if (eq mhc-file-method 'mhc-sync)
|
108
|
+
(and (stringp mhc-sync-remote)
|
109
|
+
(stringp mhc-sync-id))
|
110
|
+
mhc-file-method))])
|
111
|
+
"----"
|
112
|
+
("PostScript"
|
113
|
+
["PostScript" mhc-ps t]
|
114
|
+
["Preview" mhc-ps-preview t]
|
115
|
+
["Print" mhc-ps-print t]
|
116
|
+
["Save" mhc-ps-save t]
|
117
|
+
["Insert buffer" mhc-ps-insert-buffer t])))
|
118
|
+
|
119
|
+
(defvar mhc-prefix-key "\C-c."
|
120
|
+
"*Prefix key to call MHC functions.")
|
121
|
+
|
122
|
+
(defvar mhc-mode-map nil "Keymap for `mhc-mode'.")
|
123
|
+
(defvar mhc-prefix-map nil "Keymap for 'mhc-key-prefix'.")
|
124
|
+
|
125
|
+
(if (and mhc-mode-map mhc-prefix-map)
|
126
|
+
()
|
127
|
+
(setq mhc-mode-map (make-sparse-keymap))
|
128
|
+
(setq mhc-prefix-map (make-sparse-keymap))
|
129
|
+
(define-key mhc-prefix-map "g" 'mhc-goto-month)
|
130
|
+
(define-key mhc-prefix-map "j" 'mhc-goto-date)
|
131
|
+
(define-key mhc-prefix-map "." 'mhc-goto-this-month)
|
132
|
+
(define-key mhc-prefix-map "n" 'mhc-goto-next-month)
|
133
|
+
(define-key mhc-prefix-map "N" 'mhc-goto-next-year)
|
134
|
+
(define-key mhc-prefix-map "p" 'mhc-goto-prev-month)
|
135
|
+
(define-key mhc-prefix-map "P" 'mhc-goto-prev-year)
|
136
|
+
(define-key mhc-prefix-map "f" 'mhc-goto-today)
|
137
|
+
(define-key mhc-prefix-map "|" 'mhc-import)
|
138
|
+
(define-key mhc-prefix-map "m" 'mhc-modify)
|
139
|
+
(define-key mhc-prefix-map "e" 'mhc-edit)
|
140
|
+
(define-key mhc-prefix-map "s" 'mhc-rescan-month)
|
141
|
+
(define-key mhc-prefix-map "d" 'mhc-delete)
|
142
|
+
(define-key mhc-prefix-map "c" 'mhc-set-default-category)
|
143
|
+
(define-key mhc-prefix-map "i" 'mhc-insert-schedule)
|
144
|
+
(define-key mhc-prefix-map "?" 'mhc-calendar)
|
145
|
+
(define-key mhc-prefix-map "t" 'mhc-calendar-toggle-insert-rectangle)
|
146
|
+
(define-key mhc-prefix-map "T" 'mhc-file-toggle-offline)
|
147
|
+
(define-key mhc-prefix-map "S" 'mhc-file-sync)
|
148
|
+
(define-key mhc-prefix-map "R" 'mhc-reset)
|
149
|
+
(define-key mhc-mode-map mhc-prefix-key mhc-prefix-map)
|
150
|
+
(cond
|
151
|
+
((featurep 'xemacs)
|
152
|
+
(define-key mhc-mode-map [(button1)] 'mhc-calendar-mouse-goto-date)
|
153
|
+
(define-key mhc-mode-map [(button2)] 'mhc-calendar-mouse-goto-date-view))
|
154
|
+
(t
|
155
|
+
(define-key mhc-mode-map [mouse-1] 'mhc-calendar-mouse-goto-date)
|
156
|
+
(define-key mhc-mode-map [mouse-2] 'mhc-calendar-mouse-goto-date-view))))
|
157
|
+
|
158
|
+
(defvar mhc-mode nil "Non-nil when in mhc-mode.")
|
159
|
+
|
160
|
+
(defcustom mhc-mode-hook nil
|
161
|
+
"Hook run in when entering MHC mode."
|
162
|
+
:group 'mhc
|
163
|
+
:type 'hook)
|
164
|
+
|
165
|
+
;; Avoid warning of byte-compiler.
|
166
|
+
(defvar mhc-mode-menu)
|
167
|
+
(eval-and-compile
|
168
|
+
(autoload 'easy-menu-add "easymenu"))
|
169
|
+
|
170
|
+
(defun mhc-mode (&optional arg) "\
|
171
|
+
\\<mhc-mode-map>
|
172
|
+
MHC is the mode for registering schdule directly from email.
|
173
|
+
Requres Mew or Wanderlust or Gnus.
|
174
|
+
|
175
|
+
Key assinment on mhc-mode.
|
176
|
+
|
177
|
+
\\[mhc-goto-this-month] Review the schedule of this month
|
178
|
+
\\[mhc-goto-next-month] Review the schedule of next month
|
179
|
+
\\[mhc-goto-prev-month] Review the schedule of previous month
|
180
|
+
\\[mhc-goto-month] Jump to your prefer month
|
181
|
+
\\[mhc-goto-date] Jump to your prefer date
|
182
|
+
\\[mhc-rescan-month] Rescan the buffer of the month
|
183
|
+
\\[mhc-goto-today] Move cursor to today (Only available reviewing this month)
|
184
|
+
\\[mhc-import] Register the reviewing mail to schdule
|
185
|
+
\\[mhc-delete] Delete the schdule on the cursor line
|
186
|
+
\\[mhc-set-default-category] Edit the schdule on the cursor line
|
187
|
+
\\[mhc-modify] Modify the schdule on the cursor line
|
188
|
+
\\[mhc-edit] Create new schdule file
|
189
|
+
\\[mhc-set-default-category] Change default category
|
190
|
+
\\[mhc-calendar] Display 3 months mini calendar
|
191
|
+
\\[mhc-calendar-toggle-insert-rectangle] Toggle 3 months calendar
|
192
|
+
\\[mhc-reset] Reset MHC
|
193
|
+
|
194
|
+
'\\[universal-argument]' prefix is available on using '\\[mhc-rescan-month]', '\\[mhc-goto-this-month]', '\\[mhc-goto-month]', '\\[mhc-goto-date]'
|
195
|
+
, it works to assign the category (see below).
|
196
|
+
|
197
|
+
The prefix arg '\\[mhc-goto-next-month]', '\\[mhc-goto-prev-month]' is also available and you can indicate
|
198
|
+
the number of months to forward/back.
|
199
|
+
|
200
|
+
Field names using by MHC.
|
201
|
+
|
202
|
+
X-SC-Category:
|
203
|
+
Space-seperated Keywords. You can set default category to scan.
|
204
|
+
You can also indicate keywords by typing '\\[mhc-rescan-month]', '\\[mhc-goto-this-month]', '\\[mhc-goto-month]', '\\[mhc-goto-date]' with C-u.
|
205
|
+
"
|
206
|
+
(interactive "P")
|
207
|
+
(make-local-variable 'mhc-mode)
|
208
|
+
(setq mhc-mode
|
209
|
+
(if (null arg)
|
210
|
+
(not mhc-mode)
|
211
|
+
(> (prefix-numeric-value arg) 0)))
|
212
|
+
(when (featurep 'xemacs)
|
213
|
+
(easy-menu-add mhc-mode-menu))
|
214
|
+
(force-mode-line-update)
|
215
|
+
(run-hooks 'mhc-mode-hook))
|
216
|
+
|
217
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
218
|
+
;; lexical analyzer part for category.
|
219
|
+
;;
|
220
|
+
|
221
|
+
(defsubst mhc-expr/new ()
|
222
|
+
(vector nil nil nil nil))
|
223
|
+
|
224
|
+
(defsubst mhc-expr/token (expr-obj) ;; literal
|
225
|
+
(aref expr-obj 0))
|
226
|
+
(defsubst mhc-expr/token-type (expr-obj) ;; symbolized
|
227
|
+
(aref expr-obj 1))
|
228
|
+
(defsubst mhc-expr/string (expr-obj) ;; currently parsing string.
|
229
|
+
(aref expr-obj 2))
|
230
|
+
|
231
|
+
(defsubst mhc-expr/set-token (expr-obj val)
|
232
|
+
(aset expr-obj 0 val))
|
233
|
+
(defsubst mhc-expr/set-token-type (expr-obj val)
|
234
|
+
(aset expr-obj 1 val))
|
235
|
+
(defsubst mhc-expr/set-string (expr-obj val)
|
236
|
+
(aset expr-obj 2 val))
|
237
|
+
|
238
|
+
(defconst mhc-expr-token-type-alist
|
239
|
+
'(
|
240
|
+
("[^!&|()\t \n]+" . symbol)
|
241
|
+
("!" . negop)
|
242
|
+
("&&" . andop)
|
243
|
+
("||" . orop)
|
244
|
+
("(" . lparen)
|
245
|
+
(")" . rparen)))
|
246
|
+
|
247
|
+
;; Eat one token from parsing string in obj.
|
248
|
+
(defun mhc-expr/gettoken (obj)
|
249
|
+
(let ((string (mhc-expr/string obj))
|
250
|
+
(token-alist mhc-expr-token-type-alist)
|
251
|
+
(token-type nil)
|
252
|
+
(token nil))
|
253
|
+
;; delete leading white spaces.
|
254
|
+
(if (string-match "^[\t ]+" string)
|
255
|
+
(setq string (substring string (match-end 0))))
|
256
|
+
(while (and token-alist (not token-type))
|
257
|
+
(if (string-match (concat "^" (car (car token-alist))) string)
|
258
|
+
(setq token (substring string 0 (match-end 0))
|
259
|
+
string (substring string (match-end 0))
|
260
|
+
token-type (cdr (car token-alist))))
|
261
|
+
(setq token-alist (cdr token-alist)))
|
262
|
+
|
263
|
+
(mhc-expr/set-token obj token)
|
264
|
+
(mhc-expr/set-string obj string)
|
265
|
+
(mhc-expr/set-token-type obj token-type)
|
266
|
+
obj))
|
267
|
+
|
268
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
269
|
+
;; recursive descent parser for category.
|
270
|
+
;;
|
271
|
+
|
272
|
+
;;
|
273
|
+
;; expression -> term ("||" term)*
|
274
|
+
;;
|
275
|
+
(defun mhc-expr/expression (obj)
|
276
|
+
(let ((ret (list (mhc-expr/term obj))))
|
277
|
+
(while (eq (mhc-expr/token-type obj) 'orop)
|
278
|
+
(mhc-expr/gettoken obj)
|
279
|
+
(setq ret (cons (mhc-expr/term obj) ret)))
|
280
|
+
(if (= 1 (length ret))
|
281
|
+
(car ret)
|
282
|
+
(cons 'or (nreverse ret)))))
|
283
|
+
|
284
|
+
;;
|
285
|
+
;; term -> factor ("&&" factor)*
|
286
|
+
;;
|
287
|
+
(defun mhc-expr/term (obj)
|
288
|
+
(let ((ret (list (mhc-expr/factor obj))))
|
289
|
+
(while (eq (mhc-expr/token-type obj) 'andop)
|
290
|
+
(mhc-expr/gettoken obj)
|
291
|
+
(setq ret (cons (mhc-expr/factor obj) ret)))
|
292
|
+
(if (= 1 (length ret))
|
293
|
+
(car ret)
|
294
|
+
(cons 'and (nreverse ret)))))
|
295
|
+
|
296
|
+
;;
|
297
|
+
;; factor -> "!"* category_name || "(" expression ")"
|
298
|
+
;;
|
299
|
+
(defun mhc-expr/factor (obj)
|
300
|
+
(let ((ret)
|
301
|
+
(neg-flag nil))
|
302
|
+
(while (eq (mhc-expr/token-type obj) 'negop)
|
303
|
+
(setq neg-flag (not neg-flag))
|
304
|
+
(mhc-expr/gettoken obj))
|
305
|
+
(cond
|
306
|
+
;; symbol
|
307
|
+
((eq (mhc-expr/token-type obj) 'symbol)
|
308
|
+
(setq ret (list 'mhc-schedule-in-category-p
|
309
|
+
'schedule (mhc-expr/token obj)))
|
310
|
+
(mhc-expr/gettoken obj))
|
311
|
+
;; ( expression )
|
312
|
+
((eq (mhc-expr/token-type obj) 'lparen)
|
313
|
+
(mhc-expr/gettoken obj)
|
314
|
+
(setq ret (mhc-expr/expression obj))
|
315
|
+
(if (not (eq (mhc-expr/token-type obj) 'rparen))
|
316
|
+
(error "Syntax error."))
|
317
|
+
(mhc-expr/gettoken obj))
|
318
|
+
;; error
|
319
|
+
(t
|
320
|
+
(error "Syntax error.")
|
321
|
+
;; (error "Missing category name or `(' %s %s"
|
322
|
+
;; mhc-expr-token mhc-expr-parsing-string)
|
323
|
+
))
|
324
|
+
(if neg-flag (list 'not ret) ret)))
|
325
|
+
|
326
|
+
(defun mhc-expr-parse (string)
|
327
|
+
(let ((obj (mhc-expr/new)) (ret nil))
|
328
|
+
(if (or (not string) (string= string ""))
|
329
|
+
t
|
330
|
+
(mhc-expr/set-string obj string)
|
331
|
+
(mhc-expr/gettoken obj)
|
332
|
+
(setq ret (mhc-expr/expression obj))
|
333
|
+
(if (mhc-expr/token obj)
|
334
|
+
(error "Syntax Error.")
|
335
|
+
ret))))
|
336
|
+
|
337
|
+
(defun mhc-expr-compile (string)
|
338
|
+
(byte-compile
|
339
|
+
`(lambda (schedule)
|
340
|
+
,(mhc-expr-parse string)
|
341
|
+
)))
|
342
|
+
|
343
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
344
|
+
;;
|
345
|
+
;; category
|
346
|
+
;;
|
347
|
+
(defvar mhc-default-category nil)
|
348
|
+
(defvar mhc-default-category-predicate-sexp
|
349
|
+
(mhc-expr-compile ""))
|
350
|
+
|
351
|
+
(defvar mhc-default-category-hist nil)
|
352
|
+
|
353
|
+
(defun mhc-set-default-category ()
|
354
|
+
(interactive)
|
355
|
+
(setq mhc-default-category
|
356
|
+
(read-from-minibuffer "Default Category: "
|
357
|
+
(or mhc-default-category "")
|
358
|
+
nil nil 'mhc-default-category-hist))
|
359
|
+
(setq mhc-default-category-predicate-sexp
|
360
|
+
(mhc-expr-compile mhc-default-category))
|
361
|
+
(if (mhc-summary-buffer-p)
|
362
|
+
(mhc-rescan-month)))
|
363
|
+
|
364
|
+
; (defun mhc-category-convert (lst)
|
365
|
+
; (let (ret inv)
|
366
|
+
; ;; preceding `!' means invert logic.
|
367
|
+
; (if (and lst (string-match "^!" (car lst)))
|
368
|
+
; (setq lst (cons (substring (car lst) (match-end 0)) (cdr lst))
|
369
|
+
; inv t))
|
370
|
+
; (cons inv lst)))
|
371
|
+
|
372
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
373
|
+
;; goto-*
|
374
|
+
|
375
|
+
(defun mhc-goto-month (&optional date hide-private)
|
376
|
+
"*Show schedules of specified month.
|
377
|
+
If HIDE-PRIVATE, priavate schedules are suppressed."
|
378
|
+
(interactive
|
379
|
+
(list
|
380
|
+
(mhc-input-month "Month ")
|
381
|
+
(if mhc-default-hide-private-schedules
|
382
|
+
(not current-prefix-arg)
|
383
|
+
current-prefix-arg)))
|
384
|
+
(mhc-scan-month date
|
385
|
+
(mhc-summary-mailer-type)
|
386
|
+
mhc-default-category-predicate-sexp
|
387
|
+
hide-private))
|
388
|
+
|
389
|
+
(defvar mhc-goto-date-func 'mhc-goto-date-calendar)
|
390
|
+
; or mhc-goto-date-summary
|
391
|
+
(defun mhc-goto-date (&optional hide-private)
|
392
|
+
"*Show schedules of specified date.
|
393
|
+
If HIDE-PRIVATE, private schedules are suppressed."
|
394
|
+
(interactive
|
395
|
+
(list
|
396
|
+
(if mhc-default-hide-private-schedules
|
397
|
+
(not current-prefix-arg)
|
398
|
+
current-prefix-arg)))
|
399
|
+
(let* ((owin (get-buffer-window (current-buffer)))
|
400
|
+
(buf (mhc-summary-get-import-buffer))
|
401
|
+
(win (if buf (get-buffer-window buf) nil))
|
402
|
+
date)
|
403
|
+
(save-excursion
|
404
|
+
(when win (select-window win))
|
405
|
+
(setq date (car (mhc-input-day "Date: " (mhc-date-now) (mhc-guess-date))))
|
406
|
+
(select-window owin))
|
407
|
+
(funcall mhc-goto-date-func date hide-private)))
|
408
|
+
(defun mhc-goto-date-calendar (date hide-private)
|
409
|
+
(mhc-calendar-goto-month date))
|
410
|
+
(defun mhc-goto-date-summary (date hide-private)
|
411
|
+
;; XXX mhc-calendar-scanのパクリです
|
412
|
+
(mhc-goto-month date hide-private)
|
413
|
+
(goto-char (point-min))
|
414
|
+
(if (mhc-summary-search-date date)
|
415
|
+
(progn
|
416
|
+
(beginning-of-line)
|
417
|
+
(if (not (pos-visible-in-window-p (point)))
|
418
|
+
(recenter)))))
|
419
|
+
|
420
|
+
(defun mhc-goto-this-month (&optional hide-private)
|
421
|
+
"*Show schedules of this month.
|
422
|
+
If HIDE-PRIVATE, private schedules are suppressed."
|
423
|
+
(interactive
|
424
|
+
(list
|
425
|
+
(if mhc-default-hide-private-schedules
|
426
|
+
(not current-prefix-arg)
|
427
|
+
current-prefix-arg)))
|
428
|
+
(mhc-goto-month (mhc-date-now) hide-private))
|
429
|
+
|
430
|
+
(defun mhc-goto-next-month (&optional arg)
|
431
|
+
(interactive "p")
|
432
|
+
(mhc-goto-month (mhc-date-mm+
|
433
|
+
(or (mhc-current-date-month) (mhc-date-now)) arg)
|
434
|
+
mhc-default-hide-private-schedules))
|
435
|
+
|
436
|
+
(defun mhc-goto-next-year (&optional arg)
|
437
|
+
(interactive "p")
|
438
|
+
(mhc-goto-next-month (* (or arg 1) 12)))
|
439
|
+
|
440
|
+
(defun mhc-goto-prev-month (&optional arg)
|
441
|
+
(interactive "p")
|
442
|
+
(mhc-goto-next-month (- arg)))
|
443
|
+
|
444
|
+
(defun mhc-goto-prev-year (&optional arg)
|
445
|
+
(interactive "p")
|
446
|
+
(mhc-goto-next-year (- arg)))
|
447
|
+
|
448
|
+
(defun mhc-goto-today (&optional no-display)
|
449
|
+
"*Go to the line of today's schedule or first day of month.
|
450
|
+
Unless NO-DISPLAY, display it."
|
451
|
+
(interactive "P")
|
452
|
+
(let ((now (mhc-date-now))
|
453
|
+
(buf-date (mhc-current-date-month)))
|
454
|
+
(when buf-date
|
455
|
+
(goto-char (point-min))
|
456
|
+
(mhc-date-let now
|
457
|
+
(if (and (= yy (mhc-date-yy buf-date))
|
458
|
+
(= mm (mhc-date-mm buf-date)))
|
459
|
+
(when (mhc-summary-search-date now)
|
460
|
+
(forward-line 0)
|
461
|
+
(or (pos-visible-in-window-p (point))
|
462
|
+
(recenter))
|
463
|
+
(or no-display
|
464
|
+
(mhc-summary-display-article)))
|
465
|
+
(when (and mhc-use-wide-scope
|
466
|
+
(mhc-summary-search-date (mhc-date-mm-first buf-date)))
|
467
|
+
(forward-line 0)
|
468
|
+
(or (pos-visible-in-window-p (point))
|
469
|
+
(recenter))
|
470
|
+
(or no-display
|
471
|
+
(mhc-summary-display-article)))))
|
472
|
+
;; Emacs-21.3.50 something wrong
|
473
|
+
(beginning-of-line))))
|
474
|
+
|
475
|
+
(defun mhc-rescan-month (&optional hide-private)
|
476
|
+
"*Rescan schedules of this buffer.
|
477
|
+
If HIDE-PRIVATE, private schedules are suppressed."
|
478
|
+
(interactive
|
479
|
+
(list
|
480
|
+
(if mhc-default-hide-private-schedules
|
481
|
+
(not current-prefix-arg)
|
482
|
+
current-prefix-arg)))
|
483
|
+
(move-to-column 1)
|
484
|
+
(let ((line (+ (count-lines (point-min) (point))
|
485
|
+
(if (= (current-column) 0) 1 0))))
|
486
|
+
(mhc-scan-month (or (mhc-current-date-month) (mhc-date-now))
|
487
|
+
(mhc-summary-mailer-type)
|
488
|
+
mhc-default-category-predicate-sexp
|
489
|
+
hide-private)
|
490
|
+
(goto-char (point-min))
|
491
|
+
(if (eq selective-display t)
|
492
|
+
(re-search-forward "[\n\C-m]" nil 'end (1- line))
|
493
|
+
(forward-line (1- line))))
|
494
|
+
(beginning-of-line))
|
495
|
+
|
496
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
497
|
+
;; make scan form.
|
498
|
+
|
499
|
+
(defvar mhc-face-week-color-paint-thick nil)
|
500
|
+
|
501
|
+
(defvar mhc-summary-buffer-current-date-month nil
|
502
|
+
"Indicate summary buffer's month. It is also used by mhc-summary-buffer-p")
|
503
|
+
(make-variable-buffer-local 'mhc-summary-buffer-current-date-month)
|
504
|
+
|
505
|
+
(defun mhc-expand-date-scope-backward (date scope)
|
506
|
+
"Expand date scope backward involving the whole first week of month.
|
507
|
+
DATE can be any date of the target month.
|
508
|
+
SCOPE is one of:
|
509
|
+
+ 'week: Expand to involve the whole first week of month.
|
510
|
+
+ 'wide: Just like 'week, but if 'week does not expand nothing,
|
511
|
+
it takes 7 days.
|
512
|
+
+ number: Expand N days backward."
|
513
|
+
(let ((edge-date (mhc-date-mm-first date)))
|
514
|
+
(cond
|
515
|
+
((integerp scope)
|
516
|
+
(mhc-date- edge-date scope))
|
517
|
+
((eq scope 'week)
|
518
|
+
(mhc-date-ww-first edge-date mhc-start-day-of-week))
|
519
|
+
((eq scope 'wide)
|
520
|
+
(mhc-date-ww-first (mhc-date-- edge-date) mhc-start-day-of-week)))))
|
521
|
+
|
522
|
+
(defun mhc-expand-date-scope-forward (date scope)
|
523
|
+
"Expand date scope forward involving the whole last week of month.
|
524
|
+
DATE can be any date of the target month.
|
525
|
+
SCOPE is one of:
|
526
|
+
+ 'week: Expand to involve the whole last week of month.
|
527
|
+
+ 'wide: Just like 'week, but if 'week does not expand nothing,
|
528
|
+
it takes 7 days.
|
529
|
+
+ number: Expand N days forward."
|
530
|
+
(let ((edge-date (mhc-date-mm-last date)))
|
531
|
+
(cond
|
532
|
+
((integerp scope)
|
533
|
+
(mhc-date+ edge-date scope))
|
534
|
+
((eq scope 'week)
|
535
|
+
(mhc-date-ww-last edge-date mhc-start-day-of-week))
|
536
|
+
((eq scope 'wide)
|
537
|
+
(mhc-date-ww-last (mhc-date++ edge-date) mhc-start-day-of-week)))))
|
538
|
+
|
539
|
+
(defun mhc-scan-month (date mailer category-predicate secret)
|
540
|
+
"Make summary buffer for a month indicated by DATE.
|
541
|
+
DATE can be any date of the target month.
|
542
|
+
If MAILER is 'direct, insert scanned result into current buffer.
|
543
|
+
CATEGORY-PREDICATE must be a function that can take one mhc-schedule
|
544
|
+
argument and return a boolean value indicates opacity of the article.
|
545
|
+
If SECRET is non-nil, hide articles those categories are
|
546
|
+
listed in ``mhc-category-as-private''."
|
547
|
+
(let* ((from (mhc-date-mm-first date))
|
548
|
+
(to (mhc-date-mm-last date))
|
549
|
+
(today (mhc-date-now))
|
550
|
+
;; need three months for mini-calendar
|
551
|
+
(dayinfo-list (mhc-db-scan (mhc-date-mm-- from) (mhc-date-mm++ to))))
|
552
|
+
(unless (eq 'direct mailer)
|
553
|
+
(mhc-summary-generate-buffer date mailer)
|
554
|
+
(setq mhc-summary-buffer-current-date-month
|
555
|
+
(mhc-date-mm-first date)))
|
556
|
+
(when mhc-use-wide-scope
|
557
|
+
(setq from (mhc-expand-date-scope-backward date mhc-use-wide-scope))
|
558
|
+
(setq to (mhc-expand-date-scope-forward date mhc-use-wide-scope)))
|
559
|
+
(message "%s" (mhc-date-format date "Scanning %04d/%02d..." yy mm))
|
560
|
+
(mhc-summary-make-contents
|
561
|
+
dayinfo-list
|
562
|
+
from to mailer category-predicate secret)
|
563
|
+
(unless (eq 'direct mailer)
|
564
|
+
(when mhc-insert-calendar
|
565
|
+
(mhc-calendar-insert-rectangle-at
|
566
|
+
date
|
567
|
+
(- (mhc-misc-get-width) mhc-calendar-width)
|
568
|
+
mhc-vertical-calendar-length
|
569
|
+
dayinfo-list))
|
570
|
+
(mhc-summary-mode-setup date mailer)
|
571
|
+
(mhc-mode 1)
|
572
|
+
(setq mhc-summary-buffer-current-date-month
|
573
|
+
(mhc-date-mm-first date))
|
574
|
+
(mhc-goto-today t)
|
575
|
+
(message "%s" (mhc-date-format date "Scanning %04d/%02d...done" yy mm)))))
|
576
|
+
|
577
|
+
(defun mhc-search (string &optional subject-only)
|
578
|
+
"Search events by STRING.
|
579
|
+
If SUBJECT-ONLY is non-nil, it will search only on X-SC-Subject:"
|
580
|
+
(interactive "sSearch: \nP")
|
581
|
+
(let* ((match (mhc-db-search :subject string :body (unless subject-only string))))
|
582
|
+
(if (null match)
|
583
|
+
(message "No match")
|
584
|
+
(mhc-scan match))))
|
585
|
+
|
586
|
+
(defun mhc-scan (events &optional insert-current-buffer clip-from clip-to)
|
587
|
+
"Create mhc-summary buffer using EVENTS list.
|
588
|
+
If INSERT-CURRENT-BUFFER is non-nil, insert contents in the current buffer.
|
589
|
+
if CLIP-FROM and CLIP-TO are specified, clip EVENTS by date using these two params."
|
590
|
+
(unless insert-current-buffer
|
591
|
+
(mhc-summary-generate-buffer "MHC SEARCH"))
|
592
|
+
(message "Listing MHC events...")
|
593
|
+
(mhc-summary-make-contents events clip-from clip-to)
|
594
|
+
(mhc-summary-mode)
|
595
|
+
(goto-char (point-min))
|
596
|
+
(message "Listing MHC events...done"))
|
597
|
+
|
598
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
599
|
+
;; import, edit, delete, modify
|
600
|
+
|
601
|
+
(defcustom mhc-input-sequences '(date time subject location category recurrence-tag alarm)
|
602
|
+
"*Sequence of the inputs."
|
603
|
+
:group 'mhc
|
604
|
+
:type '(repeat (choice (const :tag "Date" date)
|
605
|
+
(const :tag "Time" time)
|
606
|
+
(const :tag "Subject" subject)
|
607
|
+
(const :tag "Location" location)
|
608
|
+
(const :tag "Category" category)
|
609
|
+
(const :tag "Recurrence tag" recurrence-tag)
|
610
|
+
(const :tag "Alarm" alarm))))
|
611
|
+
|
612
|
+
(defun mhc-edit (&optional import-buffer)
|
613
|
+
"Edit a new schedule.
|
614
|
+
If optional argument IMPORT-BUFFER is specified, import its content.
|
615
|
+
Returns t if the importation was succeeded."
|
616
|
+
(interactive
|
617
|
+
(if current-prefix-arg
|
618
|
+
(list (get-buffer (read-buffer "Import buffer: "
|
619
|
+
(current-buffer))))))
|
620
|
+
(let ((draft-buffer (generate-new-buffer mhc-draft-buffer-name))
|
621
|
+
(current-date (or (mhc-current-date) (mhc-calendar-get-date) (mhc-date-now)))
|
622
|
+
(succeed t)
|
623
|
+
msgp date time subject location category recurrence-tag priority alarm)
|
624
|
+
(and (called-interactively-p 'interactive)
|
625
|
+
(mhc-window-push))
|
626
|
+
(set-buffer draft-buffer)
|
627
|
+
(if import-buffer
|
628
|
+
(progn
|
629
|
+
(insert-buffer-substring-no-properties
|
630
|
+
(if (consp import-buffer)
|
631
|
+
(cdr import-buffer)
|
632
|
+
import-buffer))
|
633
|
+
(mhc-header-narrowing
|
634
|
+
(setq msgp (or (mhc-header-get-value "from")
|
635
|
+
(mhc-header-get-value "x-sc-subject")))
|
636
|
+
(mhc-header-delete-header
|
637
|
+
(concat "^\\("
|
638
|
+
(mhc-regexp-opt mhc-draft-unuse-hdr-list)
|
639
|
+
"\\)")
|
640
|
+
'regexp))
|
641
|
+
(mhc-highlight-message)
|
642
|
+
(switch-to-buffer draft-buffer t)))
|
643
|
+
(condition-case ()
|
644
|
+
(if import-buffer
|
645
|
+
(progn
|
646
|
+
(delete-other-windows)
|
647
|
+
(goto-char (point-min))
|
648
|
+
(if (y-or-n-p "Do you want to import this article? ")
|
649
|
+
(let* ((original (with-current-buffer
|
650
|
+
(if (consp import-buffer)
|
651
|
+
(cdr import-buffer)
|
652
|
+
import-buffer)
|
653
|
+
(mhc-parse-buffer)))
|
654
|
+
(schedule (car (mhc-record-schedules original)))
|
655
|
+
(inputs (copy-sequence mhc-input-sequences))
|
656
|
+
input)
|
657
|
+
(while (setq input (car inputs))
|
658
|
+
(setq inputs (delq input inputs))
|
659
|
+
(cond
|
660
|
+
((eq input 'date)
|
661
|
+
;; input date
|
662
|
+
(setq date
|
663
|
+
(mhc-input-day "Date: "
|
664
|
+
current-date
|
665
|
+
(mhc-guess-date))))
|
666
|
+
((eq input 'time)
|
667
|
+
;; input time
|
668
|
+
(setq time
|
669
|
+
(mhc-input-time "Time: "
|
670
|
+
(mhc-schedule-time-as-string
|
671
|
+
schedule)
|
672
|
+
(mhc-guess-time
|
673
|
+
(mhc-minibuf-candidate-nth-begin)))))
|
674
|
+
((eq input 'subject)
|
675
|
+
;; input subject
|
676
|
+
(setq subject
|
677
|
+
(mhc-input-subject
|
678
|
+
"Subject: "
|
679
|
+
(mhc-misc-sub
|
680
|
+
(or (mhc-record-subject original)
|
681
|
+
(mhc-header-narrowing
|
682
|
+
(mhc-header-get-value "subject")))
|
683
|
+
"^\\(Re:\\)? *\\(\\[[^\]]+\\]\\)? *"
|
684
|
+
""))))
|
685
|
+
((eq input 'location)
|
686
|
+
;; input location
|
687
|
+
(setq location
|
688
|
+
(mhc-input-location
|
689
|
+
"Location: "
|
690
|
+
(mhc-schedule-location schedule))))
|
691
|
+
((eq input 'category)
|
692
|
+
;; input category
|
693
|
+
(setq category
|
694
|
+
(mhc-input-category
|
695
|
+
"Category: "
|
696
|
+
(mhc-schedule-categories-as-string schedule))))
|
697
|
+
;; input recurrence tag
|
698
|
+
((eq input 'recurrence-tag)
|
699
|
+
(setq recurrence-tag
|
700
|
+
(mhc-input-recurrence-tag
|
701
|
+
"Recurrence Tag: "
|
702
|
+
(mhc-schedule-recurrence-tag-as-string schedule))))
|
703
|
+
;; input alarm
|
704
|
+
((eq input 'alarm)
|
705
|
+
(if mhc-ask-alarm
|
706
|
+
(setq alarm
|
707
|
+
(mhc-input-alarm
|
708
|
+
"Alarm: "
|
709
|
+
mhc-default-alarm))))))
|
710
|
+
;;
|
711
|
+
(setq priority (mhc-schedule-priority schedule)))
|
712
|
+
;; Answer was no.
|
713
|
+
(message "") ; flush minibuffer.
|
714
|
+
(and (called-interactively-p 'interactive)
|
715
|
+
(mhc-window-pop))
|
716
|
+
(setq succeed nil)
|
717
|
+
(kill-buffer draft-buffer)))
|
718
|
+
;; No import (it succeeds).
|
719
|
+
(let ((inputs (copy-sequence mhc-input-sequences))
|
720
|
+
input)
|
721
|
+
(while (setq input (car inputs))
|
722
|
+
(setq inputs (delq input inputs))
|
723
|
+
(cond
|
724
|
+
((eq input 'date)
|
725
|
+
(setq date (mhc-input-day "Date: " current-date)))
|
726
|
+
((eq input 'time)
|
727
|
+
(setq time (mhc-input-time "Time: ")))
|
728
|
+
((eq input 'subject)
|
729
|
+
(setq subject (mhc-input-subject "Subject: ")))
|
730
|
+
((eq input 'location)
|
731
|
+
(setq location (mhc-input-location "Location: ")))
|
732
|
+
((eq input 'category)
|
733
|
+
(setq category (mhc-input-category "Category: ")))
|
734
|
+
((eq input 'recurrence-tag)
|
735
|
+
(setq recurrence-tag (mhc-input-recurrence-tag "Recurrence Tag: " (or subject ""))))
|
736
|
+
((eq input 'alarm)
|
737
|
+
(if mhc-ask-alarm
|
738
|
+
(setq alarm (mhc-input-alarm "Alarm: " mhc-default-alarm))))))))
|
739
|
+
;; Quit.
|
740
|
+
(quit
|
741
|
+
(and (called-interactively-p 'interactive)
|
742
|
+
(mhc-window-pop))
|
743
|
+
(setq succeed nil)
|
744
|
+
(kill-buffer draft-buffer)))
|
745
|
+
(if succeed
|
746
|
+
(progn
|
747
|
+
(switch-to-buffer draft-buffer t)
|
748
|
+
(set-buffer draft-buffer)
|
749
|
+
(if (and import-buffer msgp)
|
750
|
+
(if (consp import-buffer)
|
751
|
+
(mhc-draft-reedit-buffer (car import-buffer) 'original)
|
752
|
+
;; Delete candidate overlay if exists.
|
753
|
+
(if mhc-minibuf-candidate-overlay
|
754
|
+
(delete-overlay mhc-minibuf-candidate-overlay))
|
755
|
+
;; Already imported to current buffer.
|
756
|
+
(mhc-draft-reedit-buffer (current-buffer)))
|
757
|
+
;; Delete candidate overlay if exists.
|
758
|
+
(if mhc-minibuf-candidate-overlay
|
759
|
+
(delete-overlay mhc-minibuf-candidate-overlay))
|
760
|
+
(mhc-draft-setup-new))
|
761
|
+
(mhc-header-narrowing
|
762
|
+
(mhc-header-delete-header
|
763
|
+
(concat "^\\("
|
764
|
+
(mhc-regexp-opt (mhc-header-list))
|
765
|
+
"\\)")
|
766
|
+
'regexp))
|
767
|
+
(goto-char (point-min))
|
768
|
+
(insert "X-SC-Subject: " subject
|
769
|
+
"\nX-SC-Location: " location
|
770
|
+
"\nX-SC-Day: "
|
771
|
+
(mapconcat
|
772
|
+
(lambda (day)
|
773
|
+
(mhc-date-format day "%04d%02d%02d" yy mm dd))
|
774
|
+
date " ")
|
775
|
+
"\nX-SC-Time: "
|
776
|
+
(if time
|
777
|
+
(let ((begin (car time))
|
778
|
+
(end (nth 1 time)))
|
779
|
+
(concat
|
780
|
+
(if begin (mhc-time-to-string begin) "")
|
781
|
+
(if end (concat "-" (mhc-time-to-string end)) "")))
|
782
|
+
"")
|
783
|
+
"\nX-SC-Category: "
|
784
|
+
(mapconcat (function capitalize) category " ")
|
785
|
+
"\nX-SC-Priority: " (if priority
|
786
|
+
(number-to-string priority)
|
787
|
+
"")
|
788
|
+
"\nX-SC-Recurrence-Tag: " recurrence-tag
|
789
|
+
"\nX-SC-Cond: "
|
790
|
+
"\nX-SC-Duration: "
|
791
|
+
"\nX-SC-Alarm: " (or alarm "")
|
792
|
+
"\nX-SC-Record-Id: " (mhc-record-create-id)
|
793
|
+
"\nX-SC-Sequence: 0\n")
|
794
|
+
(goto-char (point-min))
|
795
|
+
(mhc-draft-mode)
|
796
|
+
succeed))))
|
797
|
+
|
798
|
+
(defcustom mhc-default-import-original-article nil
|
799
|
+
"*If non-nil value, import a schedule with MIME attachements."
|
800
|
+
:group 'mhc
|
801
|
+
:type 'boolean)
|
802
|
+
|
803
|
+
(defun mhc-import (&optional get-original)
|
804
|
+
"Import a schedule from the current article.
|
805
|
+
The default action of this command is to import a schedule from the
|
806
|
+
current article without MIME attachements. If you want to import a
|
807
|
+
schedule including MIME attachements, call this command with a prefix
|
808
|
+
argument GET-ORIGINAL.
|
809
|
+
Set non-nil to `mhc-default-import-original-article', and
|
810
|
+
the default action of this command is changed to the latter."
|
811
|
+
(interactive
|
812
|
+
(list (if mhc-default-import-original-article
|
813
|
+
(not current-prefix-arg)
|
814
|
+
current-prefix-arg)))
|
815
|
+
(mhc-window-push)
|
816
|
+
(unless (mhc-edit (mhc-summary-get-import-buffer get-original))
|
817
|
+
;; failed.
|
818
|
+
(mhc-window-pop)))
|
819
|
+
|
820
|
+
(defun mhc-import-from-region (beg end)
|
821
|
+
"Import a schedule from region BEG END."
|
822
|
+
(interactive "r")
|
823
|
+
(save-restriction
|
824
|
+
(narrow-to-region beg end)
|
825
|
+
(let ((str (buffer-substring beg end)))
|
826
|
+
(mhc-import)
|
827
|
+
(goto-char (point-max))
|
828
|
+
(insert str)
|
829
|
+
(goto-char (point-min)))))
|
830
|
+
|
831
|
+
(defun mhc-delete ()
|
832
|
+
"Delete the current schedule."
|
833
|
+
(interactive)
|
834
|
+
(mhc-delete-file (mhc-summary-record)))
|
835
|
+
|
836
|
+
(defcustom mhc-delete-file-hook nil
|
837
|
+
"Normal hook run after mhc-delete-file."
|
838
|
+
:group 'mhc
|
839
|
+
:type 'hook)
|
840
|
+
|
841
|
+
(defun mhc-delete-file (record)
|
842
|
+
(interactive)
|
843
|
+
(if (not (and record (file-exists-p (mhc-record-name record))))
|
844
|
+
(message "File does not exist (%s)." (mhc-record-name record))
|
845
|
+
(if (not (y-or-n-p (format "Do you delete %s ?"
|
846
|
+
(mhc-record-subject-as-string record))))
|
847
|
+
(message "Never mind..")
|
848
|
+
(if (and
|
849
|
+
(mhc-record-occur-multiple-p record)
|
850
|
+
(not (y-or-n-p
|
851
|
+
(format
|
852
|
+
"%s has multiple occurrences. Delete all(=y) or one(=n) ?"
|
853
|
+
(mhc-record-subject-as-string record)))))
|
854
|
+
(mhc-db-add-exception-rule
|
855
|
+
record
|
856
|
+
(or (mhc-current-date)
|
857
|
+
(mhc-calendar-view-date)))
|
858
|
+
(mhc-db-delete-file record))
|
859
|
+
(or (and (mhc-summary-buffer-p)
|
860
|
+
(mhc-rescan-month mhc-default-hide-private-schedules))
|
861
|
+
(and (mhc-calendar-p) (mhc-calendar-rescan)))
|
862
|
+
(run-hooks 'mhc-delete-file-hook))))
|
863
|
+
|
864
|
+
(defun mhc-modify ()
|
865
|
+
"Modify the current schedule."
|
866
|
+
(interactive)
|
867
|
+
(mhc-modify-file (mhc-summary-filename)))
|
868
|
+
|
869
|
+
(defcustom mhc-browse-x-url-function 'browse-url
|
870
|
+
"*A function to browse URL."
|
871
|
+
:group 'mhc
|
872
|
+
:type 'function)
|
873
|
+
|
874
|
+
(defun mhc-browse-x-url ()
|
875
|
+
"Browse X-URL field."
|
876
|
+
(interactive)
|
877
|
+
(let ((filename (mhc-summary-filename))
|
878
|
+
url)
|
879
|
+
(with-temp-buffer
|
880
|
+
(insert-file-contents filename)
|
881
|
+
(if (setq url (mhc-header-narrowing
|
882
|
+
(or (mhc-header-get-value "x-uri")
|
883
|
+
(mhc-header-get-value "x-url"))))
|
884
|
+
(progn
|
885
|
+
(funcall mhc-browse-x-url-function url)
|
886
|
+
(message "X-URL browser started."))
|
887
|
+
(message "No X-URL field.")))))
|
888
|
+
|
889
|
+
(defun mhc-modify-file (file)
|
890
|
+
(if (and (stringp file) (file-exists-p file))
|
891
|
+
(let* ((name (format
|
892
|
+
"*mhc draft %s*"
|
893
|
+
(file-name-nondirectory file)))
|
894
|
+
(buffer (get-buffer name)))
|
895
|
+
(if (buffer-live-p buffer)
|
896
|
+
(progn
|
897
|
+
(message "Specified file(%s) has already been opened." file)
|
898
|
+
(switch-to-buffer-other-window buffer))
|
899
|
+
(mhc-window-push)
|
900
|
+
(set-buffer (setq buffer (get-buffer-create name)))
|
901
|
+
(mhc-draft-reedit-file file)
|
902
|
+
(set-buffer-modified-p nil)
|
903
|
+
(switch-to-buffer-other-window buffer)
|
904
|
+
(goto-char (point-min))
|
905
|
+
(mhc-draft-mode)
|
906
|
+
(set (make-local-variable 'mhc-draft-buffer-file-name) file)))
|
907
|
+
(message "Specified file(%s) does not exist." file)))
|
908
|
+
|
909
|
+
|
910
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
911
|
+
;;
|
912
|
+
;; Window stack
|
913
|
+
;;
|
914
|
+
|
915
|
+
(defvar mhc-window-stack nil)
|
916
|
+
|
917
|
+
(defun mhc-window-push ()
|
918
|
+
(interactive)
|
919
|
+
(setq mhc-window-stack
|
920
|
+
(cons (current-window-configuration) mhc-window-stack)))
|
921
|
+
|
922
|
+
(defun mhc-window-pop ()
|
923
|
+
(interactive)
|
924
|
+
(if mhc-window-stack
|
925
|
+
(set-window-configuration (car-safe mhc-window-stack)))
|
926
|
+
(setq mhc-window-stack (cdr-safe mhc-window-stack)))
|
927
|
+
|
928
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
929
|
+
;;
|
930
|
+
;; (Category . (parent-face fg bg))
|
931
|
+
;;
|
932
|
+
|
933
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
934
|
+
;; manipulate data from mhc-summary-buffer.
|
935
|
+
|
936
|
+
(defconst mhc-summary-day-regex "\\([^|]+| +\\)?[0-9]+/\\([0-9]+\\)")
|
937
|
+
|
938
|
+
(defun mhc-summary-buffer-p (&optional buffer)
|
939
|
+
(if buffer
|
940
|
+
(set-buffer buffer))
|
941
|
+
mhc-summary-buffer-current-date-month)
|
942
|
+
|
943
|
+
(defun mhc-current-date ()
|
944
|
+
(when (mhc-summary-buffer-p)
|
945
|
+
(let ((dayinfo (get-text-property (point) 'mhc-dayinfo)))
|
946
|
+
(or (and dayinfo (mhc-day-date dayinfo))
|
947
|
+
(save-excursion
|
948
|
+
(end-of-line)
|
949
|
+
(while (and (not (bobp))
|
950
|
+
(null dayinfo))
|
951
|
+
(or (setq dayinfo (get-text-property (point) 'mhc-dayinfo))
|
952
|
+
(forward-char -1)))
|
953
|
+
(and dayinfo (mhc-day-date dayinfo)))))))
|
954
|
+
|
955
|
+
(defun mhc-current-date-month ()
|
956
|
+
mhc-summary-buffer-current-date-month)
|
957
|
+
|
958
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
959
|
+
;; misc.
|
960
|
+
|
961
|
+
;;
|
962
|
+
;; Convinient function when you want to insert your schedule into an
|
963
|
+
;; editing buffer.
|
964
|
+
;;
|
965
|
+
(defun mhc-insert-schedule (&optional hide-private)
|
966
|
+
(interactive "P")
|
967
|
+
(set-mark (point))
|
968
|
+
(mhc-scan-month (mhc-input-month "Month ")
|
969
|
+
'direct ;; insert into current buffer.
|
970
|
+
mhc-default-category-predicate-sexp
|
971
|
+
hide-private)
|
972
|
+
(exchange-point-and-mark))
|
973
|
+
|
974
|
+
(defun mhc-view-file ()
|
975
|
+
"View the schedule on the current line in View mode in another window."
|
976
|
+
(interactive)
|
977
|
+
(let ((path (mhc-summary-filename)))
|
978
|
+
(view-file-other-window path)))
|
979
|
+
|
980
|
+
|
981
|
+
;;; Temporary buffers
|
982
|
+
|
983
|
+
(defvar mhc-tmp-buffer-list nil)
|
984
|
+
|
985
|
+
(defun mhc-get-buffer-create (name)
|
986
|
+
"Return NAME buffer for temporary use of MHC."
|
987
|
+
(let ((buf (get-buffer name)))
|
988
|
+
(or (and buf (buffer-name buf))
|
989
|
+
(progn
|
990
|
+
(setq buf (get-buffer-create name)
|
991
|
+
mhc-tmp-buffer-list (cons buf mhc-tmp-buffer-list))
|
992
|
+
(buffer-disable-undo buf)))
|
993
|
+
buf))
|
994
|
+
|
995
|
+
(defun mhc-kill-all-buffers ()
|
996
|
+
"Kill all buffers for temporary use of MHC."
|
997
|
+
(while mhc-tmp-buffer-list
|
998
|
+
(if (buffer-name (car mhc-tmp-buffer-list))
|
999
|
+
(kill-buffer (car mhc-tmp-buffer-list)))
|
1000
|
+
(setq mhc-tmp-buffer-list
|
1001
|
+
(cdr mhc-tmp-buffer-list))))
|
1002
|
+
|
1003
|
+
|
1004
|
+
;;; Setup and exit
|
1005
|
+
|
1006
|
+
(defcustom mhc-setup-hook nil
|
1007
|
+
"Run hook after mhc-setup."
|
1008
|
+
:group 'mhc
|
1009
|
+
:type 'hook)
|
1010
|
+
|
1011
|
+
(defvar mhc-setup-p nil)
|
1012
|
+
|
1013
|
+
(defun mhc-setup ()
|
1014
|
+
(unless mhc-setup-p
|
1015
|
+
(condition-case nil
|
1016
|
+
(progn
|
1017
|
+
(or (featurep 'easymenu) (require 'easymenu))
|
1018
|
+
(easy-menu-define mhc-mode-menu
|
1019
|
+
mhc-mode-map
|
1020
|
+
"Menu used in mhc mode."
|
1021
|
+
mhc-mode-menu-spec)
|
1022
|
+
(easy-menu-define mhc-calendar-mode-menu
|
1023
|
+
mhc-calendar-mode-map
|
1024
|
+
"Menu used in mhc calendar mode."
|
1025
|
+
mhc-calendar-mode-menu-spec))
|
1026
|
+
(error nil))
|
1027
|
+
(or (assq 'mhc-mode minor-mode-alist)
|
1028
|
+
(setq minor-mode-alist
|
1029
|
+
(cons (list 'mhc-mode (mhc-file-line-status))
|
1030
|
+
minor-mode-alist)))
|
1031
|
+
(or (assq 'mhc-mode minor-mode-map-alist)
|
1032
|
+
(setq minor-mode-map-alist
|
1033
|
+
(cons (cons 'mhc-mode mhc-mode-map)
|
1034
|
+
minor-mode-map-alist)))
|
1035
|
+
(mhc-face-setup)
|
1036
|
+
(mhc-calendar-setup)
|
1037
|
+
(mhc-file-setup)
|
1038
|
+
(setq mhc-default-category-predicate-sexp
|
1039
|
+
(mhc-expr-compile mhc-default-category))
|
1040
|
+
(and (mhc-use-icon-p) (mhc-icon-setup))
|
1041
|
+
(and mhc-calendar-link-hnf (mhc-calendar-hnf-face-setup))
|
1042
|
+
(mhc-summary-line-inserter-setup)
|
1043
|
+
(mhc-guess-location-setup)
|
1044
|
+
(autoload 'mhc-ps "mhc-ps" "*Create PostScript calendar with selected method." t)
|
1045
|
+
(autoload 'mhc-ps-preview "mhc-ps" "*Preview PostScript calendar." t)
|
1046
|
+
(autoload 'mhc-ps-print "mhc-ps" "*Print PostScript calendar." t)
|
1047
|
+
(autoload 'mhc-ps-save "mhc-ps" "*Save PostScript calendar." t)
|
1048
|
+
(autoload 'mhc-ps-insert-buffer "mhc-ps" "*Insert PostScript calendar." t)
|
1049
|
+
(setq mhc-setup-p t)
|
1050
|
+
(run-hooks 'mhc-setup-hook)))
|
1051
|
+
|
1052
|
+
(defun mhc-reset ()
|
1053
|
+
"Reset MHC."
|
1054
|
+
(interactive)
|
1055
|
+
(message "MHC resetting...")
|
1056
|
+
(mhc-face-setup)
|
1057
|
+
(mhc-calendar-setup)
|
1058
|
+
(and (mhc-use-icon-p) (mhc-icon-setup))
|
1059
|
+
(and mhc-calendar-link-hnf (mhc-calendar-hnf-face-setup))
|
1060
|
+
(mhc-summary-line-inserter-setup)
|
1061
|
+
(mhc-guess-location-setup)
|
1062
|
+
(or (and (mhc-summary-buffer-p)
|
1063
|
+
(mhc-rescan-month mhc-default-hide-private-schedules))
|
1064
|
+
(and (mhc-calendar-p) (mhc-calendar-rescan)))
|
1065
|
+
(message "MHC resetting...done"))
|
1066
|
+
|
1067
|
+
(defcustom mhc-exit-hook nil
|
1068
|
+
"Run hook after mhc-exit."
|
1069
|
+
:group 'mhc
|
1070
|
+
:type 'hook)
|
1071
|
+
|
1072
|
+
(defun mhc-exit ()
|
1073
|
+
(setq mhc-setup-p nil)
|
1074
|
+
(mhc-file-exit)
|
1075
|
+
(mhc-kill-all-buffers)
|
1076
|
+
(run-hooks 'mhc-exit-hook))
|
1077
|
+
|
1078
|
+
(defun mhc-version ()
|
1079
|
+
"Show mhc version."
|
1080
|
+
(interactive)
|
1081
|
+
(message mhc-version))
|
1082
|
+
|
1083
|
+
;;; Copyright Notice:
|
1084
|
+
|
1085
|
+
;; Copyright (C) 1999, 2000 Yoshinari Nomura. All rights reserved.
|
1086
|
+
;; Copyright (C) 2000 MHC developing team. All rights reserved.
|
1087
|
+
|
1088
|
+
;; Redistribution and use in source and binary forms, with or without
|
1089
|
+
;; modification, are permitted provided that the following conditions
|
1090
|
+
;; are met:
|
1091
|
+
;;
|
1092
|
+
;; 1. Redistributions of source code must retain the above copyright
|
1093
|
+
;; notice, this list of conditions and the following disclaimer.
|
1094
|
+
;; 2. Redistributions in binary form must reproduce the above copyright
|
1095
|
+
;; notice, this list of conditions and the following disclaimer in the
|
1096
|
+
;; documentation and/or other materials provided with the distribution.
|
1097
|
+
;; 3. Neither the name of the team nor the names of its contributors
|
1098
|
+
;; may be used to endorse or promote products derived from this software
|
1099
|
+
;; without specific prior written permission.
|
1100
|
+
;;
|
1101
|
+
;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS''
|
1102
|
+
;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
1103
|
+
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
1104
|
+
;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
1105
|
+
;; THE TEAM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
1106
|
+
;; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
1107
|
+
;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
1108
|
+
;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
1109
|
+
;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
1110
|
+
;; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
1111
|
+
;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
1112
|
+
;; OF THE POSSIBILITY OF SUCH DAMAGE.
|
1113
|
+
|
1114
|
+
;;; mhc.el ends here
|