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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e9eb513930c0f5d993e1755bed627593443df3e2
|
4
|
+
data.tar.gz: d4a6c467fe781e96c68c0ebad0a96f743e8d6a8b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0027ebd2eaab008113d12e02062011bf403ce7f3611f8d41cd874ee0c16434ed3e9c576abb10199426f2d374c6ea8c397209ee35ec453b86c42713c56c7c39b1
|
7
|
+
data.tar.gz: 4b3ba18ed523c7105e9109f573b10f74bf1c4cfefbc99dea2e5d2dc4a09b03f6a17bd349097efae502b650323a6b64456dd3e0193fbc5f41516029519d1438e8
|
data/.gitignore
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
*.elc
|
2
|
+
*.gem
|
3
|
+
*.rbc
|
4
|
+
.DS_Store
|
5
|
+
.bundle
|
6
|
+
.config
|
7
|
+
.yardoc
|
8
|
+
Gemfile.lock
|
9
|
+
InstalledFiles
|
10
|
+
_yardoc
|
11
|
+
attic/
|
12
|
+
coverage
|
13
|
+
doc/
|
14
|
+
lib/bundler/man
|
15
|
+
pkg
|
16
|
+
rdoc
|
17
|
+
rdocs/
|
18
|
+
spec/reports
|
19
|
+
test/tmp
|
20
|
+
test/version_tmp
|
21
|
+
tmp
|
22
|
+
vendor/bundle
|
23
|
+
.ruby-version
|
24
|
+
.ruby-gemset
|
25
|
+
.rvmrc
|
26
|
+
dist
|
27
|
+
.cask
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/COPYRIGHT
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Copyright (C) 1999, 2000 Yoshinari Nomura. All rights reserved.
|
2
|
+
Copyright (C) 2000-2015 MHC developing team. All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions
|
6
|
+
are met:
|
7
|
+
|
8
|
+
1. Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
12
|
+
documentation and/or other materials provided with the distribution.
|
13
|
+
3. Neither the name of the team nor the names of its contributors
|
14
|
+
may be used to endorse or promote products derived from this software
|
15
|
+
without specific prior written permission.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS''
|
18
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
19
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
20
|
+
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
21
|
+
THE TEAM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
22
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
23
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
25
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
26
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
27
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
|
+
OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/Gemfile
ADDED
data/README.org
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
#+TITLE: MHC -- Message Harmonized Calendaring system.
|
2
|
+
#+AUTHOR: Yoshinari Nomura
|
3
|
+
#+EMAIL:
|
4
|
+
#+DATE: 2015-03-16
|
5
|
+
#+OPTIONS: H:3 num:2 toc:nil
|
6
|
+
#+OPTIONS: ^:nil @:t \n:nil ::t |:t f:t TeX:t
|
7
|
+
#+OPTIONS: skip:nil
|
8
|
+
#+OPTIONS: author:t
|
9
|
+
#+OPTIONS: email:nil
|
10
|
+
#+OPTIONS: creator:nil
|
11
|
+
#+OPTIONS: timestamp:nil
|
12
|
+
#+OPTIONS: timestamps:nil
|
13
|
+
#+OPTIONS: d:nil
|
14
|
+
#+OPTIONS: tags:t
|
15
|
+
#+TEXT:
|
16
|
+
#+DESCRIPTION:
|
17
|
+
#+KEYWORDS:
|
18
|
+
#+LANGUAGE: ja
|
19
|
+
#+LATEX_CLASS: jsarticle
|
20
|
+
#+LATEX_CLASS_OPTIONS: [a4j]
|
21
|
+
# #+LATEX_HEADER: \usepackage{plain-article}
|
22
|
+
# #+LATEX_HEADER: \renewcommand\maketitle{}
|
23
|
+
# #+LATEX_HEADER: \pagestyle{empty}
|
24
|
+
# #+LaTeX: \thispagestyle{empty}
|
25
|
+
|
26
|
+
* DESCRIPTION
|
27
|
+
MHC is designed to help those who receive most appointments via email.
|
28
|
+
Using MHC, you can easily import schedule articles from emails.
|
29
|
+
|
30
|
+
You can get the latest version from:
|
31
|
+
+ https://github.com/yoshinari-nomura/mhc
|
32
|
+
+ http://www.quickhack.net/mhc
|
33
|
+
|
34
|
+
MHC has following features:
|
35
|
+
|
36
|
+
+ Easy import your schedule from existing buffers.
|
37
|
+
For example, using with Mew/Gnus/Wanderlust (MUAs on Emacs),
|
38
|
+
you can easily compose your schedule items from
|
39
|
+
appoint-emails. MHC will guess the title,
|
40
|
+
date, time and description by scanning the email.
|
41
|
+
+ Simple data structure allows you to manipulate stored data in many ways.
|
42
|
+
+ Appointments can be made to repeat in flexible ways.
|
43
|
+
+ powerful but simple expression of appointments.
|
44
|
+
|
45
|
+
MHC stores schedule articles in the same form of MH; you can manipulate
|
46
|
+
these messages not only by above tools but also by many other MUAs,
|
47
|
+
editors, UNIX commandline tools or your own scripts.
|
48
|
+
|
49
|
+
* SYSTEM REQUIREMENTS
|
50
|
+
+ Ruby 2.1 or newer
|
51
|
+
+ Emacs 24 or newer
|
52
|
+
|
53
|
+
* Information for Developers
|
54
|
+
** INSTALL for developers:
|
55
|
+
1) Install rbenv + ruby-build
|
56
|
+
(see https://github.com/sstephenson/rbenv#basic-github-checkout for details)
|
57
|
+
#+BEGIN_SRC shell-script
|
58
|
+
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
|
59
|
+
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
|
60
|
+
# Edit your shell dot files to add some path and environment variables.
|
61
|
+
#+END_SRC
|
62
|
+
|
63
|
+
2) Install Latest Ruby and bundler
|
64
|
+
#+BEGIN_SRC shell-script
|
65
|
+
# Install ruby 2.1.2
|
66
|
+
$ rbenv install 2.1.2
|
67
|
+
|
68
|
+
# Installation check
|
69
|
+
$ rbenv global 2.1.2
|
70
|
+
$ ruby -v # -> You will see: ruby 2.1.2...
|
71
|
+
|
72
|
+
# Install bundler for your new Ruby
|
73
|
+
$ gem install bundler
|
74
|
+
|
75
|
+
# If you want to use Ruby in your sytem, say /usr/bin/ruby
|
76
|
+
$ rbenv global system
|
77
|
+
$ ruby -v
|
78
|
+
#+END_SRC
|
79
|
+
|
80
|
+
3) Clone MHC from github
|
81
|
+
#+BEGIN_SRC shell-script
|
82
|
+
$ git clone git@github.com:yoshinari-nomura/mhc.git ~/src/mhc
|
83
|
+
#+END_SRC
|
84
|
+
|
85
|
+
4) Set default ruby version in MHC project
|
86
|
+
#+BEGIN_SRC shell-script
|
87
|
+
$ cd ~/src/mhc
|
88
|
+
$ echo '2.1.2' > .ruby-version
|
89
|
+
$ ruby -v # -> You will see: ruby 2.1.2...
|
90
|
+
#+END_SRC
|
91
|
+
|
92
|
+
5) Install requied gem packages in sandbox ~/src/mhc/vendor/bundle
|
93
|
+
#+BEGIN_SRC shell-script
|
94
|
+
$ cd ~/src/mhc
|
95
|
+
$ bundle install --path vendor/bundle
|
96
|
+
#+END_SRC
|
97
|
+
|
98
|
+
6) Initialize config file and spool directory
|
99
|
+
#+BEGIN_SRC shell-script
|
100
|
+
$ bin/mhc init ~/mhc
|
101
|
+
|
102
|
+
Guessing current local timezone ...
|
103
|
+
ok guess timezone ... Asia/Tokyo
|
104
|
+
Making directries under ~/mhc ...
|
105
|
+
create ~/mhc/draft
|
106
|
+
create ~/mhc/inbox
|
107
|
+
create ~/mhc/presets
|
108
|
+
create ~/mhc/spool
|
109
|
+
create ~/mhc/trash
|
110
|
+
create ~/mhc/status/cache
|
111
|
+
create ~/mhc/status/log
|
112
|
+
create ~/mhc/status/sync_channels
|
113
|
+
Copying config file(s) into ~/.config/mhc/config.yml ...
|
114
|
+
ok copy ~/.config/mhc/config.yml
|
115
|
+
Done.
|
116
|
+
|
117
|
+
# Read comments in config.yml carefully
|
118
|
+
$ vi ~/.config/mhc/config.yml
|
119
|
+
|
120
|
+
# Add Japanese Holidays if needed.
|
121
|
+
$ cp samples/japanese-holidays.mhcc ~/mhc/presets/
|
122
|
+
|
123
|
+
# Add ~/src/mhc/bin directory to your $PATH for dogfooding
|
124
|
+
$ export PATH=$HOME/src/mhc/bin:$PATH
|
125
|
+
#+END_SRC
|
126
|
+
|
127
|
+
7) Byte-compile Emacs client
|
128
|
+
#+BEGIN_SRC shell-script
|
129
|
+
$ cd emacs
|
130
|
+
$ make
|
131
|
+
#+END_SRC
|
132
|
+
|
133
|
+
8) Add setup in your =.emacs.d/init.el=
|
134
|
+
#+BEGIN_SRC emacs-lisp
|
135
|
+
(setq load-path
|
136
|
+
(cons "~/src/mhc/emacs" load-path))
|
137
|
+
(autoload 'mhc-mua-setup "mhc-mua")
|
138
|
+
(mhc-mua-setup)
|
139
|
+
|
140
|
+
;; M-x mhc-goto-this-month
|
141
|
+
#+END_SRC
|
142
|
+
|
143
|
+
9) Check if TODAY is good.
|
144
|
+
#+BEGIN_SRC shell-script
|
145
|
+
$ mhc scan today
|
146
|
+
#+END_SRC
|
147
|
+
|
148
|
+
You may add ~/src/mhc/bin directory to your $PATH for dogfooding
|
149
|
+
|
150
|
+
** DIRECTORY STRUCTURE
|
151
|
+
*** Configuration Directory
|
152
|
+
Default configuration directory is =~/.config/mhc=.
|
153
|
+
If environment variable =MHC_CONFIG_HOME= or =XDG_CONFIG_HOME= is set,
|
154
|
+
it is taken as =$MHC_CONFIG_HOME/mhc= or =$XDG_CONFIG_HOME/mhc=.
|
155
|
+
|
156
|
+
Configuration directory =~/.config/mhc= has these stuffs:
|
157
|
+
+ config.yml :: Configuration file (mandatory).
|
158
|
+
+ plugins :: Your home-made Ruby functions.
|
159
|
+
See [[file:samples][samples]] for details.
|
160
|
+
|
161
|
+
*** Spool Directory
|
162
|
+
Location of the spool directory should be set
|
163
|
+
by =TOPDIR:= element in =config.yml=.
|
164
|
+
|
165
|
+
For example, if you have =TOPDIR: ~/MHC= entry
|
166
|
+
in your =config.yml=, you will have these directory structure
|
167
|
+
under =~/MHC=:
|
168
|
+
|
169
|
+
+ spool/*.mhc :: MHC event database. All events are flatly located
|
170
|
+
in this directory in the form of ={x-sc-message-id}.mhc=
|
171
|
+
+ draft/*.mhc :: Draft files of events.
|
172
|
+
Opening a file in directory by Emacs,
|
173
|
+
and Typing =C-cC-c= will move the file into =spool= directory.
|
174
|
+
(Not implemented yet. Should be empty for now.)
|
175
|
+
+ inbox/*.mhc :: Mainly same as =spool=. You will have a chance to
|
176
|
+
review these events in this directory afterwards.
|
177
|
+
(Not implemented yet. Should be empty for now.)
|
178
|
+
+ presets/*.mhcc :: Database for fixed anniversary events
|
179
|
+
such as birthdays or national holidays.
|
180
|
+
+ trash/*.mhc :: Removed events from =spool= directory.
|
181
|
+
+ status/ ::
|
182
|
+
+ cache/* :: Cache files for speed-up.
|
183
|
+
You can remove these files without any damage to MHC Database.
|
184
|
+
+ log/* :: log files for debug.
|
185
|
+
You can remove these files without any damage to MHC DB.
|
186
|
+
|
187
|
+
+ sync_channels/* :: Sync records of MHC DB.
|
188
|
+
If you remove any files under this directory,
|
189
|
+
MHC Sync will be DAMAGED.
|
190
|
+
* How to convert from the old MHC spool
|
191
|
+
[[https://gist.github.com/yoshinari-nomura/bb9a197e0e01ad81c883][update-uuid.sh]] would help you.
|
192
|
+
|
193
|
+
New format is:
|
194
|
+
+ =X-SC-Record-Id= is now in UUID style.
|
195
|
+
+ Each filename is in the form of ={UUID}.mhc=, not =[0-9]+=.
|
196
|
+
+ UUID in =X-SC-Record-Id= is same as its file's base name.
|
197
|
+
+ All articles are flatly placed in TOP/spool/ directory.
|
198
|
+
|
199
|
+
#+BEGIN_SRC shell-script
|
200
|
+
$ ./update-uuid.sh ~/Mail/schedule ~/mhc
|
201
|
+
|
202
|
+
Converting... logfile will be in /Users/nom/mhc/update-uuid.sh34485.log
|
203
|
+
#+END_SRC
|
204
|
+
|
205
|
+
For Japanese people, character-code conversion might be needed.
|
206
|
+
#+BEGIN_SRC shell-script
|
207
|
+
$ cd ~/mhc/spool
|
208
|
+
$ find . -name '*.mhc' | xargs -n 10 nkf --overwrite
|
209
|
+
#+END_SRC
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
require 'rdoc/task'
|
9
|
+
Rake::RDocTask.new do |rd|
|
10
|
+
rd.rdoc_dir = 'rdocs'
|
11
|
+
rd.rdoc_files = FileList["lib/**/*.rb"]
|
12
|
+
rd.options << '-charset=UTF-8'
|
13
|
+
end
|
data/bin/mhc
ADDED
@@ -0,0 +1,312 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
################################################################
|
4
|
+
# rbenv support:
|
5
|
+
# If this file is a symlink, and bound to a specific ruby
|
6
|
+
# version via rbenv (indicated by RBENV_VERSION),
|
7
|
+
# I want to resolve the symlink and re-exec
|
8
|
+
# the original executable respecting the .ruby_version
|
9
|
+
# which should indicate the right version.
|
10
|
+
#
|
11
|
+
if File.symlink?(__FILE__) and ENV["RBENV_VERSION"]
|
12
|
+
ENV["RBENV_VERSION"] = nil
|
13
|
+
shims_path = File.expand_path("shims", ENV["RBENV_ROOT"])
|
14
|
+
ENV["PATH"] = shims_path + ":" + ENV["PATH"]
|
15
|
+
exec(File.readlink(__FILE__), *ARGV)
|
16
|
+
end
|
17
|
+
|
18
|
+
ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
|
19
|
+
|
20
|
+
require "rubygems"
|
21
|
+
require "bundler/setup"
|
22
|
+
|
23
|
+
require "thor"
|
24
|
+
require "mhc"
|
25
|
+
|
26
|
+
Encoding.default_external="UTF-8"
|
27
|
+
|
28
|
+
class MhcCLI < Thor
|
29
|
+
################################################################
|
30
|
+
# constants
|
31
|
+
|
32
|
+
DEFAULT_CONFIG_HOME = File.join((ENV["XDG_CONFIG_HOME"] || "~/.config"), "mhc")
|
33
|
+
DEFAULT_CONFIG_FILE = "config.yml"
|
34
|
+
DEFAULT_CONFIG_PATH = File.join(DEFAULT_CONFIG_HOME, DEFAULT_CONFIG_FILE)
|
35
|
+
|
36
|
+
package_name 'MHC'
|
37
|
+
|
38
|
+
################################################################
|
39
|
+
# class methods
|
40
|
+
|
41
|
+
class << self
|
42
|
+
attr_accessor :calendar
|
43
|
+
attr_accessor :popular_options
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.register_option(name, options)
|
47
|
+
@popular_options ||= {}
|
48
|
+
@popular_options[name] = options
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.named_option(*names)
|
52
|
+
names.each do |name|
|
53
|
+
method_option name, @popular_options[name]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
################################################################
|
58
|
+
# global options
|
59
|
+
|
60
|
+
class_option :debug, :desc => "Set debug flag", :type => :boolean
|
61
|
+
class_option :profile, :desc => "Set profiler flag", :type => :boolean
|
62
|
+
class_option :config, :desc => "Set config path (default: #{DEFAULT_CONFIG_PATH})", :banner => "FILE"
|
63
|
+
|
64
|
+
check_unknown_options! :except => :completions
|
65
|
+
|
66
|
+
################################################################
|
67
|
+
# frequently used options
|
68
|
+
|
69
|
+
register_option :repository, :desc => "Set MHC top directory", :banner => "DIRECTORY"
|
70
|
+
register_option :calendar, :desc => "Set source CALENDAR"
|
71
|
+
register_option :category, :desc => "Pick items only in CATEGORY"
|
72
|
+
register_option :format, :desc => "Set printing format", :enum => %w(text mail orgtable emacs icalendar calfw howm)
|
73
|
+
register_option :search, :desc => "Search items by complex expression"
|
74
|
+
register_option :dry_run, :desc => "Perform a trial run with no changes made", :type => :boolean
|
75
|
+
|
76
|
+
################################################################
|
77
|
+
# command name mappings
|
78
|
+
|
79
|
+
map ["--version", "-v"] => :version
|
80
|
+
|
81
|
+
map ["--help", "-h"] => :help
|
82
|
+
default_command :help
|
83
|
+
|
84
|
+
################################################################
|
85
|
+
# Command: help
|
86
|
+
################################################################
|
87
|
+
|
88
|
+
desc "help [COMMAND]", "Describe available commands or one specific command"
|
89
|
+
def help(command = nil)
|
90
|
+
super(command)
|
91
|
+
end
|
92
|
+
|
93
|
+
################################################################
|
94
|
+
# Command: version
|
95
|
+
################################################################
|
96
|
+
desc "version", "Show version"
|
97
|
+
|
98
|
+
def version
|
99
|
+
puts Mhc::VERSION
|
100
|
+
end
|
101
|
+
|
102
|
+
################################################################
|
103
|
+
# Command: cache
|
104
|
+
################################################################
|
105
|
+
desc "cache", "Dump cache file"
|
106
|
+
|
107
|
+
named_option :repository
|
108
|
+
|
109
|
+
def cache
|
110
|
+
Mhc::Command::Cache.new(calendar)
|
111
|
+
end
|
112
|
+
|
113
|
+
################################################################
|
114
|
+
# Command: completions
|
115
|
+
################################################################
|
116
|
+
desc "completions [COMMAND]", "List available commands or options for COMMAND", :hide => true
|
117
|
+
|
118
|
+
long_desc <<-LONGDESC
|
119
|
+
List available commands or options for COMMAND
|
120
|
+
This is supposed to be a zsh compsys helper"
|
121
|
+
LONGDESC
|
122
|
+
|
123
|
+
def completions(*command)
|
124
|
+
help = self.class.commands
|
125
|
+
global_options = self.class.class_options
|
126
|
+
Mhc::Command::Completions.new(help, global_options, command, config)
|
127
|
+
end
|
128
|
+
|
129
|
+
################################################################
|
130
|
+
# Command: config
|
131
|
+
################################################################
|
132
|
+
desc "configuration", "Show current configuration in various formats."
|
133
|
+
|
134
|
+
named_option :format
|
135
|
+
|
136
|
+
def configuration(name = nil)
|
137
|
+
puts Mhc::Converter::Emacs.new.to_emacs(config.get_value(name))
|
138
|
+
end
|
139
|
+
|
140
|
+
################################################################
|
141
|
+
# Command: init
|
142
|
+
################################################################
|
143
|
+
desc "init DIRECTORY", "Initialize MHC repository and configuration template"
|
144
|
+
|
145
|
+
def init(top_dir)
|
146
|
+
Mhc::Command::Init.new(top_dir, options[:config] || DEFAULT_CONFIG_PATH, ENV["MHC_TZID"])
|
147
|
+
end
|
148
|
+
|
149
|
+
################################################################
|
150
|
+
# Command: scan
|
151
|
+
################################################################
|
152
|
+
desc "scan RANGE", "Scan events in date RANGE"
|
153
|
+
|
154
|
+
long_desc <<-LONGDESC
|
155
|
+
scan events in date RANGE.
|
156
|
+
|
157
|
+
RANGE is one of:
|
158
|
+
\x5 + START-YYYYMMDD
|
159
|
+
\x5 + START[+LENGTH]
|
160
|
+
|
161
|
+
START is one of:
|
162
|
+
\x5 + today, tomorrow, sun ... sat, yyyymmdd
|
163
|
+
\x5 + thismonth, nextmonth, yyyymm
|
164
|
+
|
165
|
+
LENGTH is a number followed by a SUFFIX. SUFFIX is one of:
|
166
|
+
\x5 + d (days)
|
167
|
+
\x5 + w (weeks)
|
168
|
+
\x5 + m (months)
|
169
|
+
|
170
|
+
If LENGTH is omitted, it is treated as '1d' or '1m' depending on
|
171
|
+
which type of START is set.
|
172
|
+
|
173
|
+
Examples:
|
174
|
+
\x5 mhc scan 20140101-20141231
|
175
|
+
\x5 mhc scan 2140101+3d
|
176
|
+
\x5 mhc scan today --category 'Business'
|
177
|
+
\x5 mhc scan thismonth --search 'category:Business & !subject:"Trip"'
|
178
|
+
LONGDESC
|
179
|
+
|
180
|
+
named_option :calendar, :category, :format, :repository, :search
|
181
|
+
|
182
|
+
def scan(range)
|
183
|
+
begin
|
184
|
+
Mhc::Command::Scan.new(calendar, range, **symbolize_keys(options))
|
185
|
+
rescue Mhc::PropertyValue::ParseError, Mhc::FormatterNameError, Mhc::Query::ParseError => e
|
186
|
+
STDERR.print "Error: " + e.message + "\n"
|
187
|
+
end
|
188
|
+
return self
|
189
|
+
end
|
190
|
+
|
191
|
+
################################################################
|
192
|
+
# Command: server
|
193
|
+
################################################################
|
194
|
+
desc "server", "Invoked as server (backend of emacs)"
|
195
|
+
|
196
|
+
named_option :repository
|
197
|
+
|
198
|
+
def server
|
199
|
+
require "shellwords"
|
200
|
+
while line = STDIN.gets # STDIN.noecho(&:gets)
|
201
|
+
argv = line.chomp.shellsplit
|
202
|
+
self.class.start(argv)
|
203
|
+
STDOUT.flush
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
################################################################
|
208
|
+
# Command: show
|
209
|
+
################################################################
|
210
|
+
desc "show MESSAGE_ID", "Show article found by MESSAGE_ID"
|
211
|
+
|
212
|
+
named_option :calendar, :repository
|
213
|
+
|
214
|
+
def show(message_id)
|
215
|
+
event = exit_on_error do
|
216
|
+
calendar.find(uid: message_id)
|
217
|
+
end
|
218
|
+
print event.dump if event
|
219
|
+
end
|
220
|
+
|
221
|
+
################################################################
|
222
|
+
# Command: sync
|
223
|
+
################################################################
|
224
|
+
desc "sync SYNC_CHANNEL", "Synchronize DBs via SYNC_CHANNEL"
|
225
|
+
|
226
|
+
named_option :dry_run
|
227
|
+
|
228
|
+
def sync(channel_name)
|
229
|
+
driver = exit_on_error do
|
230
|
+
builder.sync_driver(channel_name)
|
231
|
+
end
|
232
|
+
driver.sync_all(options[:dry_run])
|
233
|
+
return self
|
234
|
+
end
|
235
|
+
|
236
|
+
################################################################
|
237
|
+
# add some hooks to Thor
|
238
|
+
|
239
|
+
no_commands do
|
240
|
+
def invoke_command(command, *args)
|
241
|
+
setup_global_options unless command.name == "init"
|
242
|
+
result = super
|
243
|
+
teardown
|
244
|
+
result
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
################################################################
|
249
|
+
# private
|
250
|
+
|
251
|
+
private
|
252
|
+
|
253
|
+
def exit_on_error(&block)
|
254
|
+
begin
|
255
|
+
yield if block_given?
|
256
|
+
rescue Mhc::ConfigurationError => e
|
257
|
+
STDERR.print "ERROR: #{e.message}.\n"
|
258
|
+
exit 1
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
attr_reader :builder, :config, :calendar
|
263
|
+
|
264
|
+
def setup_global_options
|
265
|
+
exit_on_error do
|
266
|
+
@config = Mhc::Config.create_from_file(options[:config] || DEFAULT_CONFIG_PATH)
|
267
|
+
@builder ||= Mhc::Builder.new(@config)
|
268
|
+
if @config.general.tzid
|
269
|
+
Mhc.default_tzid = @config.general.tzid
|
270
|
+
end
|
271
|
+
|
272
|
+
calname = options[:calendar] || @config.calendars.first.name
|
273
|
+
@config.general.repository = options[:repository] if options[:repository]
|
274
|
+
|
275
|
+
self.class.calendar ||= builder.calendar(calname)
|
276
|
+
@calendar = self.class.calendar
|
277
|
+
end
|
278
|
+
|
279
|
+
load_plugins
|
280
|
+
|
281
|
+
if options[:profile]
|
282
|
+
require 'profiler'
|
283
|
+
Profiler__.start_profile
|
284
|
+
end
|
285
|
+
if options[:debug]
|
286
|
+
require "pp"
|
287
|
+
$MHC_DEBUG = true
|
288
|
+
$MHC_DEBUG_FOR_DEVELOPER = true if ENV["MHC_DEBUG_FOR_DEVELOPER"]
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def load_plugins
|
293
|
+
config_path = options[:config] || DEFAULT_CONFIG_PATH
|
294
|
+
plugin_dir = File.dirname(config_path)
|
295
|
+
|
296
|
+
Dir.glob(File.expand_path("plugins/*.rb", plugin_dir)) do |rb|
|
297
|
+
require rb
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def teardown
|
302
|
+
if options[:profile]
|
303
|
+
Profiler__.print_profile($stdout)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def symbolize_keys(hash)
|
308
|
+
Hash[hash.map {|k,v| [k.to_sym, v]}]
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
command = MhcCLI.start(ARGV)
|