cali 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (9) hide show
  1. data/.gitignore +2 -0
  2. data/LICENCE +13 -0
  3. data/README +32 -0
  4. data/Rakefile +14 -0
  5. data/VERSION +1 -0
  6. data/bin/cali +19 -0
  7. data/examples/dotcalirc.rb +13 -0
  8. data/lib/cali.rb +265 -0
  9. metadata +87 -0
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg/
2
+ cali.gemspec
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