timetrap 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+ module Timetrap
2
+ class Entry < Sequel::Model
3
+ plugin :schema
4
+
5
+ class << self
6
+ # a class level instance variable that controls whether or not all entries
7
+ # should respond to #start and #end with times rounded to 15 minute
8
+ # increments.
9
+ attr_accessor :round
10
+ end
11
+
12
+ def round?
13
+ !!self.class.round
14
+ end
15
+
16
+ def start= time
17
+ self[:start]= Chronic.parse(time) || time
18
+ end
19
+
20
+ def end= time
21
+ self[:end]= Chronic.parse(time) || time
22
+ end
23
+
24
+ def start
25
+ round? ? rounded_start : self[:start]
26
+ end
27
+
28
+ def end
29
+ round? ? rounded_end : self[:end]
30
+ end
31
+
32
+ def end_or_now
33
+ self.end || (round? ? round(Time.now) : Time.now)
34
+ end
35
+
36
+ def rounded_start
37
+ round(self[:start])
38
+ end
39
+
40
+ def rounded_end
41
+ round(self[:end])
42
+ end
43
+
44
+ def round time
45
+ return nil unless time
46
+ Time.at(
47
+ if (r = time.to_i % 900) < 450
48
+ time.to_i - r
49
+ else
50
+ time.to_i + (900 - r)
51
+ end
52
+ )
53
+ end
54
+
55
+ def self.sheets
56
+ map{|e|e.sheet}.uniq.sort
57
+ end
58
+
59
+ # do a quick pseudo migration. This should only get executed on the first run
60
+ set_schema do
61
+ primary_key :id
62
+ column :note, :string
63
+ column :start, :timestamp
64
+ column :end, :timestamp
65
+ column :sheet, :string
66
+ end
67
+ create_table unless table_exists?
68
+ end
69
+
70
+ class Meta < Sequel::Model(:meta)
71
+ plugin :schema
72
+
73
+ set_schema do
74
+ primary_key :id
75
+ column :key, :string
76
+ column :value, :string
77
+ end
78
+ create_table unless table_exists?
79
+ end
80
+ end
data/lib/timetrap.rb ADDED
@@ -0,0 +1,80 @@
1
+ require 'rubygems'
2
+ require 'chronic'
3
+ require 'sequel'
4
+ require 'sequel/extensions/inflector'
5
+ require 'Getopt/Declare'
6
+ require File.join(File.dirname(__FILE__), 'timetrap', 'helpers')
7
+ require File.join(File.dirname(__FILE__), 'timetrap', 'cli')
8
+ DB_NAME = defined?(TEST_MODE) ? nil : "#{ENV['HOME']}/.timetrap.db"
9
+ # connect to database. This will create one if it doesn't exist
10
+ DB = Sequel.sqlite DB_NAME
11
+ require File.join(File.dirname(__FILE__), 'timetrap', 'models')
12
+ Dir["#{File.dirname(__FILE__)}/timetrap/formatters/*.rb"].each do |path|
13
+ require path
14
+ end
15
+ module Timetrap
16
+ extend self
17
+
18
+ def current_sheet= sheet
19
+ m = Meta.find_or_create(:key => 'current_sheet')
20
+ m.value = sheet
21
+ m.save
22
+ end
23
+
24
+ def current_sheet
25
+ unless Meta.find(:key => 'current_sheet')
26
+ Meta.create(:key => 'current_sheet', :value => 'default')
27
+ end
28
+ Meta.find(:key => 'current_sheet').value
29
+ end
30
+
31
+ def entries sheet = nil
32
+ Entry.filter(:sheet => sheet).order_by(:start)
33
+ end
34
+
35
+ def running?
36
+ !!active_entry
37
+ end
38
+
39
+ def active_entry
40
+ Entry.find(:sheet => Timetrap.current_sheet, :end => nil)
41
+ end
42
+
43
+ def stop time = nil
44
+ while a = active_entry
45
+ time ||= Time.now
46
+ a.end = time
47
+ a.save
48
+ end
49
+ end
50
+
51
+ def start note, time = nil
52
+ raise AlreadyRunning if running?
53
+ time ||= Time.now
54
+ Entry.create(:sheet => Timetrap.current_sheet, :note => note, :start => time).save
55
+ rescue => e
56
+ CLI.say e.message
57
+ end
58
+
59
+ def switch sheet
60
+ self.current_sheet = sheet
61
+ end
62
+
63
+ def kill_sheet sheet
64
+ Entry.filter(:sheet => sheet).destroy
65
+ end
66
+
67
+ def format format_klass, entries
68
+ format_klass.new(entries).output
69
+ end
70
+
71
+ class AlreadyRunning < StandardError
72
+ def message
73
+ "Timetrap is already running"
74
+ end
75
+ end
76
+
77
+ CLI.args = Getopt::Declare.new(<<-EOF)
78
+ #{CLI::USAGE}
79
+ EOF
80
+ end