timetrap 1.1.1

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.
@@ -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