cali 0.1.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.
- data/.gitignore +2 -0
- data/LICENCE +13 -0
- data/README +32 -0
- data/Rakefile +14 -0
- data/VERSION +1 -0
- data/bin/cali +19 -0
- data/examples/dotcalirc.rb +13 -0
- data/lib/cali.rb +265 -0
- metadata +87 -0
data/.gitignore
ADDED
data/LICENCE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright © 2008-2010, Tom Adams
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
8
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
9
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
10
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
11
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
12
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
13
|
+
PERFORMANCE OF THIS SOFTWARE.
|
data/README
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
cali
|
|
3
|
+
====
|
|
4
|
+
|
|
5
|
+
Interactive cal(1) (but the name ical was taken)
|
|
6
|
+
|
|
7
|
+
.calirc.rb
|
|
8
|
+
==========
|
|
9
|
+
|
|
10
|
+
This file lives in your home directory and is a Ruby script which gets
|
|
11
|
+
required if it exists. See examples/dotcalirc.rb for an example.
|
|
12
|
+
|
|
13
|
+
dates
|
|
14
|
+
=====
|
|
15
|
+
|
|
16
|
+
The -d/--dates option takes a filename as an argument. That file should
|
|
17
|
+
contain linebreak-separated items containing strings of the form
|
|
18
|
+
/\d{4}-\d{2}-\d{2}/.
|
|
19
|
+
|
|
20
|
+
I have something similar in my home directory containing items such as:
|
|
21
|
+
|
|
22
|
+
2008-12-21 Start on RE essay, ML revision
|
|
23
|
+
|
|
24
|
+
2009-01-04 The L Word season 6 (final season)
|
|
25
|
+
|
|
26
|
+
2009-01-22 Shop meeting
|
|
27
|
+
|
|
28
|
+
It's a very simple diary. Try running:
|
|
29
|
+
ruby -rubygems bin/cali -d README
|
|
30
|
+
|
|
31
|
+
The above dates should be underlined in the calendar, and pressing the
|
|
32
|
+
appropriate key should display the item below the calendar.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'jeweler'
|
|
3
|
+
Jeweler::Tasks.new do |gem|
|
|
4
|
+
gem.name = "cali"
|
|
5
|
+
gem.summary = %Q{Interactive cal(1) (but the name ical was taken)}
|
|
6
|
+
gem.email = "tom@holizz.com"
|
|
7
|
+
gem.homepage = "http://github.com/holizz/cali"
|
|
8
|
+
gem.authors = ["Tom Adams"]
|
|
9
|
+
gem.add_runtime_dependency "ncurses"
|
|
10
|
+
end
|
|
11
|
+
Jeweler::GemcutterTasks.new
|
|
12
|
+
rescue LoadError
|
|
13
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
|
14
|
+
end
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
data/bin/cali
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# Copyright © 2008-2010, Tom Adams
|
|
4
|
+
#
|
|
5
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
# purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
# copyright notice and this permission notice appear in all copies.
|
|
8
|
+
#
|
|
9
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
# PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
|
|
17
|
+
require 'cali'
|
|
18
|
+
|
|
19
|
+
Cali::run
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Sample rc file for cali
|
|
2
|
+
class Cali
|
|
3
|
+
def preinit_hook
|
|
4
|
+
@default_dates = "#{ENV['HOME']}/dates"
|
|
5
|
+
end
|
|
6
|
+
def postinit_hook
|
|
7
|
+
define_key('.',:showevents)
|
|
8
|
+
end
|
|
9
|
+
def define_key(key,action)
|
|
10
|
+
key = key[0] if key.instance_of? String
|
|
11
|
+
@key[key]=action
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/cali.rb
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# Copyright © 2008-2010, Tom Adams
|
|
4
|
+
#
|
|
5
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
# purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
# copyright notice and this permission notice appear in all copies.
|
|
8
|
+
#
|
|
9
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
# PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
|
|
17
|
+
require 'date'
|
|
18
|
+
require 'optparse'
|
|
19
|
+
require 'ncurses'
|
|
20
|
+
|
|
21
|
+
class Cali
|
|
22
|
+
KEYBINDINGS = {
|
|
23
|
+
['q'[0]]=> :quit,
|
|
24
|
+
[12]=> :refresh, # C-l
|
|
25
|
+
['l'[0], Ncurses::KEY_RIGHT, 6]=> :tomorrow, # C-f
|
|
26
|
+
['h'[0], Ncurses::KEY_LEFT, 2]=> :yesterday, # C-b
|
|
27
|
+
['j'[0], Ncurses::KEY_DOWN, 14]=> :nextweek, # C-n
|
|
28
|
+
['k'[0], Ncurses::KEY_UP, 16]=> :prevweek, # C-p
|
|
29
|
+
['n'[0], Ncurses::KEY_NPAGE]=> :nextmonth,
|
|
30
|
+
['p'[0], Ncurses::KEY_PPAGE]=> :prevmonth,
|
|
31
|
+
['}'[0]]=> :nextyear,
|
|
32
|
+
['{'[0]]=> :prevyear,
|
|
33
|
+
['w'[0]]=> :nextevent,
|
|
34
|
+
['b'[0]]=> :prevevent
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def Cali::run
|
|
38
|
+
options = {}
|
|
39
|
+
OptionParser.new { |opts|
|
|
40
|
+
opts.banner = "Usage: cali [-d FILE]"
|
|
41
|
+
opts.on("-d","--dates FILE","Use FILE for events") {|d|
|
|
42
|
+
options[:dates] = d
|
|
43
|
+
}
|
|
44
|
+
}.parse!
|
|
45
|
+
dotcali = Dir["#{ENV['HOME']}/.calirc.rb"][0]
|
|
46
|
+
require dotcali if dotcali
|
|
47
|
+
cali=Cali.new(options[:dates])
|
|
48
|
+
cali.run
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def initialize(dates=nil)
|
|
52
|
+
preinit_hook
|
|
53
|
+
@today = Date.today
|
|
54
|
+
@days = {}
|
|
55
|
+
dates ||= @default_dates
|
|
56
|
+
@dates = {}
|
|
57
|
+
if dates
|
|
58
|
+
open(dates){|f|
|
|
59
|
+
until f.eof
|
|
60
|
+
line = f.readline.strip
|
|
61
|
+
d = line.match(/(\d{4})-(\d{2})-(\d{2})/)
|
|
62
|
+
if d
|
|
63
|
+
date = Date.new(*d[1..3].map{|m|m.to_i})
|
|
64
|
+
@dates[date] ||= []
|
|
65
|
+
@dates[date] << line
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
}
|
|
69
|
+
end
|
|
70
|
+
@key = {}
|
|
71
|
+
KEYBINDINGS.each {|k,v|
|
|
72
|
+
k.each {|kk|
|
|
73
|
+
@key[kk] = v
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
postinit_hook
|
|
77
|
+
end
|
|
78
|
+
def run
|
|
79
|
+
begin
|
|
80
|
+
Ncurses.initscr
|
|
81
|
+
Ncurses.cbreak
|
|
82
|
+
Ncurses.noecho
|
|
83
|
+
Ncurses.keypad(Ncurses.stdscr,true)
|
|
84
|
+
mainloop
|
|
85
|
+
ensure
|
|
86
|
+
Ncurses.endwin
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
def mainloop
|
|
90
|
+
displaycal
|
|
91
|
+
displayevents
|
|
92
|
+
catch :quit do
|
|
93
|
+
while true
|
|
94
|
+
move @key[Ncurses.getch]
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
def displaycal
|
|
99
|
+
Ncurses.clear
|
|
100
|
+
Ncurses.move(0,0)
|
|
101
|
+
Ncurses.printw(@today.strftime(" %B %Y\n"))
|
|
102
|
+
Ncurses.printw(weekdays.join(" ")+"\n")
|
|
103
|
+
displaydays
|
|
104
|
+
Ncurses.refresh
|
|
105
|
+
end
|
|
106
|
+
def displaydays
|
|
107
|
+
counter = (first - first.wday)
|
|
108
|
+
before_month = true
|
|
109
|
+
after_month = false
|
|
110
|
+
while not after_month
|
|
111
|
+
if counter.month == @today.month and before_month
|
|
112
|
+
before_month = false
|
|
113
|
+
elsif counter.month != @today.month and not before_month
|
|
114
|
+
after_month = true
|
|
115
|
+
end
|
|
116
|
+
if before_month or after_month
|
|
117
|
+
Ncurses.printw(" ")
|
|
118
|
+
Ncurses.printw("\n") if after_month
|
|
119
|
+
else
|
|
120
|
+
@days[counter.day] = [Ncurses.getcurx(Ncurses.stdscr),
|
|
121
|
+
Ncurses.getcury(Ncurses.stdscr)]
|
|
122
|
+
if counter == @today
|
|
123
|
+
x,y = Ncurses.getcurx(Ncurses.stdscr),Ncurses.getcury(Ncurses.stdscr)
|
|
124
|
+
end
|
|
125
|
+
Ncurses.attron(Ncurses::A_UNDERLINE) if has_items?(counter)
|
|
126
|
+
Ncurses.attron(Ncurses::A_REVERSE) if counter == @today
|
|
127
|
+
Ncurses.printw("%2d" % counter.day)
|
|
128
|
+
Ncurses.attroff(Ncurses::A_REVERSE) if counter == @today
|
|
129
|
+
Ncurses.attroff(Ncurses::A_UNDERLINE) if has_items?(counter)
|
|
130
|
+
Ncurses.printw(" ")
|
|
131
|
+
end
|
|
132
|
+
if counter.wday == 6
|
|
133
|
+
Ncurses.printw("\n")
|
|
134
|
+
end
|
|
135
|
+
counter += 1
|
|
136
|
+
end
|
|
137
|
+
Ncurses.move(y,x+1)
|
|
138
|
+
end
|
|
139
|
+
def displayevents
|
|
140
|
+
displaycal
|
|
141
|
+
bounce {
|
|
142
|
+
y = @days[last.day][1]
|
|
143
|
+
@dates[@today].each {|l|
|
|
144
|
+
y += 2
|
|
145
|
+
Ncurses.move(y,0)
|
|
146
|
+
Ncurses.printw("#{l}")
|
|
147
|
+
} if @dates[@today]
|
|
148
|
+
}
|
|
149
|
+
end
|
|
150
|
+
def bounce (&block)
|
|
151
|
+
y,x = Ncurses.getcury(Ncurses.stdscr),Ncurses.getcurx(Ncurses.stdscr)
|
|
152
|
+
yield
|
|
153
|
+
Ncurses.move(y,x)
|
|
154
|
+
end
|
|
155
|
+
def movecursor(old)
|
|
156
|
+
if old != @today
|
|
157
|
+
a = @days[old.day]
|
|
158
|
+
Ncurses.attron(Ncurses::A_UNDERLINE) if has_items?(old)
|
|
159
|
+
Ncurses.mvprintw(a[1],a[0],"%2d" % old.day)
|
|
160
|
+
Ncurses.attroff(Ncurses::A_UNDERLINE) if has_items?(old)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
Ncurses.attron(Ncurses::A_UNDERLINE) if has_items?(@today)
|
|
164
|
+
Ncurses.attron(Ncurses::A_REVERSE)
|
|
165
|
+
a = @days[@today.day]
|
|
166
|
+
Ncurses.mvprintw(a[1],a[0],"%2d" % @today.day)
|
|
167
|
+
Ncurses.attroff(Ncurses::A_REVERSE)
|
|
168
|
+
Ncurses.attroff(Ncurses::A_UNDERLINE) if has_items?(@today)
|
|
169
|
+
Ncurses.move(a[1],a[0]+1)
|
|
170
|
+
end
|
|
171
|
+
def update(&block)
|
|
172
|
+
oldtoday = @today.dup
|
|
173
|
+
yield
|
|
174
|
+
if oldtoday.month == @today.month and oldtoday.year == @today.year
|
|
175
|
+
movecursor(oldtoday)
|
|
176
|
+
else
|
|
177
|
+
displaycal
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
def move(to)
|
|
181
|
+
case to
|
|
182
|
+
when :quit
|
|
183
|
+
throw :quit
|
|
184
|
+
when :refresh
|
|
185
|
+
displaycal
|
|
186
|
+
when :tomorrow
|
|
187
|
+
update { @today += 1 }
|
|
188
|
+
when :yesterday
|
|
189
|
+
update { @today -= 1 }
|
|
190
|
+
when :nextweek
|
|
191
|
+
update { @today += 7 }
|
|
192
|
+
when :prevweek
|
|
193
|
+
update { @today -= 7 }
|
|
194
|
+
when :nextmonth
|
|
195
|
+
oldtoday = @today.dup
|
|
196
|
+
@today += 4*7
|
|
197
|
+
if @today.month == oldtoday.month
|
|
198
|
+
@today += 7
|
|
199
|
+
end
|
|
200
|
+
displaycal
|
|
201
|
+
when :prevmonth
|
|
202
|
+
oldtoday = @today.dup
|
|
203
|
+
@today -= 4*7
|
|
204
|
+
if @today.month == oldtoday.month
|
|
205
|
+
@today -= 7
|
|
206
|
+
end
|
|
207
|
+
displaycal
|
|
208
|
+
when :nextyear
|
|
209
|
+
oldtoday = @today.dup
|
|
210
|
+
@today += 52*7
|
|
211
|
+
while @today.year == oldtoday.year or @today.month != oldtoday.month
|
|
212
|
+
@today += 7
|
|
213
|
+
end
|
|
214
|
+
displaycal
|
|
215
|
+
when :prevyear
|
|
216
|
+
oldtoday = @today.dup
|
|
217
|
+
@today -= 52*7
|
|
218
|
+
while @today.year == oldtoday.year or @today.month != oldtoday.month
|
|
219
|
+
@today -= 7
|
|
220
|
+
end
|
|
221
|
+
displaycal
|
|
222
|
+
when :nextevent
|
|
223
|
+
update {
|
|
224
|
+
newtoday = @dates.keys.select{|d| @today < d }.sort.first
|
|
225
|
+
@today = newtoday if newtoday
|
|
226
|
+
}
|
|
227
|
+
when :prevevent
|
|
228
|
+
update {
|
|
229
|
+
newtoday = @dates.keys.select{|d| @today > d }.sort.last
|
|
230
|
+
@today = newtoday if newtoday
|
|
231
|
+
}
|
|
232
|
+
end
|
|
233
|
+
displayevents
|
|
234
|
+
end
|
|
235
|
+
def weekdays
|
|
236
|
+
wds = []
|
|
237
|
+
counter = (@today - @today.wday)
|
|
238
|
+
n = 0
|
|
239
|
+
while n < 7
|
|
240
|
+
#TODO: handle other charsets correctly
|
|
241
|
+
wds << counter.strftime('%a')[0..1]
|
|
242
|
+
counter += 1
|
|
243
|
+
n += 1
|
|
244
|
+
end
|
|
245
|
+
wds
|
|
246
|
+
end
|
|
247
|
+
def first
|
|
248
|
+
Date.new(@today.year,@today.month,1)
|
|
249
|
+
end
|
|
250
|
+
def last
|
|
251
|
+
newlast = @today.dup
|
|
252
|
+
until newlast.month != @today.month
|
|
253
|
+
last = newlast.dup
|
|
254
|
+
newlast += 1
|
|
255
|
+
end
|
|
256
|
+
last
|
|
257
|
+
end
|
|
258
|
+
def has_items?(date=@today)
|
|
259
|
+
@dates.include?(date)
|
|
260
|
+
end
|
|
261
|
+
def preinit_hook
|
|
262
|
+
end
|
|
263
|
+
def postinit_hook
|
|
264
|
+
end
|
|
265
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: cali
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 27
|
|
5
|
+
prerelease: false
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 1
|
|
9
|
+
- 0
|
|
10
|
+
version: 0.1.0
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Tom Adams
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2010-08-31 00:00:00 +01:00
|
|
19
|
+
default_executable: cali
|
|
20
|
+
dependencies:
|
|
21
|
+
- !ruby/object:Gem::Dependency
|
|
22
|
+
name: ncurses
|
|
23
|
+
prerelease: false
|
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
hash: 3
|
|
30
|
+
segments:
|
|
31
|
+
- 0
|
|
32
|
+
version: "0"
|
|
33
|
+
type: :runtime
|
|
34
|
+
version_requirements: *id001
|
|
35
|
+
description:
|
|
36
|
+
email: tom@holizz.com
|
|
37
|
+
executables:
|
|
38
|
+
- cali
|
|
39
|
+
extensions: []
|
|
40
|
+
|
|
41
|
+
extra_rdoc_files:
|
|
42
|
+
- README
|
|
43
|
+
files:
|
|
44
|
+
- .gitignore
|
|
45
|
+
- LICENCE
|
|
46
|
+
- README
|
|
47
|
+
- Rakefile
|
|
48
|
+
- VERSION
|
|
49
|
+
- bin/cali
|
|
50
|
+
- examples/dotcalirc.rb
|
|
51
|
+
- lib/cali.rb
|
|
52
|
+
has_rdoc: true
|
|
53
|
+
homepage: http://github.com/holizz/cali
|
|
54
|
+
licenses: []
|
|
55
|
+
|
|
56
|
+
post_install_message:
|
|
57
|
+
rdoc_options:
|
|
58
|
+
- --charset=UTF-8
|
|
59
|
+
require_paths:
|
|
60
|
+
- lib
|
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
|
+
none: false
|
|
63
|
+
requirements:
|
|
64
|
+
- - ">="
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
hash: 3
|
|
67
|
+
segments:
|
|
68
|
+
- 0
|
|
69
|
+
version: "0"
|
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
|
+
none: false
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
hash: 3
|
|
76
|
+
segments:
|
|
77
|
+
- 0
|
|
78
|
+
version: "0"
|
|
79
|
+
requirements: []
|
|
80
|
+
|
|
81
|
+
rubyforge_project:
|
|
82
|
+
rubygems_version: 1.3.7
|
|
83
|
+
signing_key:
|
|
84
|
+
specification_version: 3
|
|
85
|
+
summary: Interactive cal(1) (but the name ical was taken)
|
|
86
|
+
test_files:
|
|
87
|
+
- examples/dotcalirc.rb
|