timetrackr 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,21 @@
1
+ = v0.2
2
+
3
+ * clean up and simplify
4
+ * removed JSON and SQLite support, only YAML
5
+ * added 'notes' command
6
+
7
+ = v0.1.6
8
+
9
+ * group by days or tasks
10
+
11
+ = v0.1.5
12
+
13
+ * added JSON database
14
+
15
+ = v0.1.4
16
+
17
+ * more commands
18
+
19
+ = v0.1.3
20
+
21
+ * stop playing with jeweller and release
data/Gemfile CHANGED
@@ -1,10 +1,7 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
3
  group :development do
4
- gem 'sqlite3'
5
- gem 'json'
6
- gem 'shoulda', '>= 0'
7
- gem 'bundler', '~> 1.0.0'
8
- gem 'jeweler', '~> 1.5.2'
9
- gem 'rcov', '>= 0'
4
+ gem 'rake'
5
+ gem 'bundler', '>= 1.0.0'
6
+ gem 'gemcutter'
10
7
  end
data/Gemfile.lock CHANGED
@@ -1,24 +1,13 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- git (1.2.5)
5
- jeweler (1.5.2)
6
- bundler (~> 1.0.0)
7
- git (>= 1.2.5)
8
- rake
9
- json (1.5.1)
10
- rake (0.8.7)
11
- rcov (0.9.9)
12
- shoulda (2.11.3)
13
- sqlite3 (1.3.3)
4
+ gemcutter (0.7.0)
5
+ rake (0.9.2.2)
14
6
 
15
7
  PLATFORMS
16
8
  ruby
17
9
 
18
10
  DEPENDENCIES
19
- bundler (~> 1.0.0)
20
- jeweler (~> 1.5.2)
21
- json
22
- rcov
23
- shoulda
24
- sqlite3
11
+ bundler (>= 1.0.0)
12
+ gemcutter
13
+ rake
File without changes
data/Manifest ADDED
@@ -0,0 +1,16 @@
1
+ CHANGELOG
2
+ Gemfile
3
+ Gemfile.lock
4
+ LICENSE
5
+ Manifest
6
+ README
7
+ Rakefile
8
+ TODO
9
+ bin/timetrackr
10
+ lib/timetrackr.rb
11
+ lib/timetrackr/cli.rb
12
+ lib/timetrackr/database.rb
13
+ lib/timetrackr/period.rb
14
+ test/helper.rb
15
+ test/test_timetrackr.rb
16
+ timetrackr.gemspec
@@ -61,13 +61,18 @@ start a task:
61
61
 
62
62
  ## Contributing to timetrackr
63
63
 
64
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
65
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
64
+ * Check out the latest master to make sure the feature hasn't been implemented
65
+ or the bug hasn't been fixed yet
66
+ * Check out the issue tracker to make sure someone already hasn't requested it
67
+ and/or contributed it
66
68
  * Fork the project
67
69
  * Start a feature/bugfix branch
68
70
  * Commit and push until you are happy with your contribution
69
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
70
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
71
+ * Make sure to add tests for it. This is important so I don't break it in a
72
+ future version unintentionally.
73
+ * Please try not to mess with the Rakefile, version, or history. If you want to
74
+ have your own version, or is otherwise necessary, that is fine, but please
75
+ isolate to its own commit so I can cherry-pick around it.
71
76
 
72
77
 
73
78
  ## Copyright
data/Rakefile CHANGED
@@ -1,53 +1,102 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
- begin
4
- Bundler.setup(:default, :development)
5
- rescue Bundler::BundlerError => e
6
- $stderr.puts e.message
7
- $stderr.puts "Run `bundle install` to install missing gems"
8
- exit e.status_code
9
- end
10
- require 'rake'
11
-
12
- require 'jeweler'
13
- Jeweler::Tasks.new do |gem|
14
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
- gem.name = "timetrackr"
16
- gem.homepage = "http://github.com/felix/timetrackr"
17
- gem.license = "MIT"
18
- gem.summary = "A simple time tracking utility"
19
- gem.description = "A simple time tracking utility"
20
- gem.email = "felix@seconddrawer.com.au"
21
- gem.authors = ["Felix Hanley"]
22
- # Include your dependencies below. Runtime dependencies are required when using your gem,
23
- # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
- # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
- # gem.add_development_dependency 'rspec', '> 1.2.3'
26
- end
27
- Jeweler::RubygemsDotOrgTasks.new
28
-
29
- require 'rake/testtask'
30
- Rake::TestTask.new(:test) do |test|
31
- test.libs << 'lib' << 'test'
32
- test.pattern = 'test/**/test_*.rb'
33
- test.verbose = true
34
- end
35
-
36
- require 'rcov/rcovtask'
37
- Rcov::RcovTask.new do |test|
38
- test.libs << 'test'
39
- test.pattern = 'test/**/test_*.rb'
40
- test.verbose = true
41
- end
42
-
43
- task :default => :test
44
-
45
- require 'rake/rdoctask'
46
- Rake::RDocTask.new do |rdoc|
47
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
-
49
- rdoc.rdoc_dir = 'rdoc'
50
- rdoc.title = "timetrackr #{version}"
51
- rdoc.rdoc_files.include('README*')
52
- rdoc.rdoc_files.include('lib/**/*.rb')
3
+ require "rubygems/package_task"
4
+ require "rdoc/task"
5
+ require "rake/testtask"
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList["test/**/*_test.rb"]
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => ["test"]
13
+
14
+ # This builds the actual gem. For details of what all these options
15
+ # mean, and other ones you can add, check the documentation here:
16
+ #
17
+ # http://rubygems.org/read/chapter/20
18
+ #
19
+ spec = Gem::Specification.new do |s|
20
+
21
+ # Change these as appropriate
22
+ s.name = "timetrackr"
23
+ s.version = "0.2.0"
24
+ s.summary = "A simple time tracking utility"
25
+ s.author = "Felix Hanley"
26
+ s.email = "felix@seconddrawer.com.au"
27
+ s.homepage = "http://github.com/felix/timetrackr"
28
+
29
+ s.has_rdoc = true
30
+ s.extra_rdoc_files = %w(README)
31
+ s.rdoc_options = %w(--main README)
32
+
33
+ # Add any extra files to include in the gem
34
+ s.files = %w(Rakefile Gemfile Gemfile.lock LICENSE README CHANGELOG Manifest TODO) + Dir.glob("{bin,test,lib}/**/*")
35
+ s.executables = FileList["bin/**"].map { |f| File.basename(f) }
36
+ s.require_paths = ["lib"]
37
+
38
+ # If you want to depend on other gems, add them here, along with any
39
+ # relevant versions
40
+ # s.add_dependency("some_other_gem", "~> 0.1.0")
41
+
42
+ # If your tests use any gems, include them here
43
+ # s.add_development_dependency("mocha") # for example
44
+ end
45
+
46
+ desc 'Tag the repository in git with gem version number'
47
+ task :tag => [:gemspec, :package] do
48
+ if `git diff --cached`.empty?
49
+ if `git tag`.split("\n").include?("v#{spec.version}")
50
+ raise "Version #{spec.version} has already been released"
51
+ end
52
+ `git add #{File.expand_path("../#{spec.name}.gemspec",
53
+ __FILE__)}`
54
+ `git commit -m "Released version #{spec.version}"`
55
+ `git tag v#{spec.version}`
56
+ `git push --tags`
57
+ `git push`
58
+ else
59
+ raise "Unstaged changes still waiting to be committed"
60
+ end
61
+ end
62
+
63
+ desc "Tag and publish the gem to rubygems.org"
64
+ task :publish => :tag do
65
+ `gem push pkg/#{spec.name}-#{spec.version}.gem`
66
+ end
67
+
68
+ # This task actually builds the gem. We also regenerate a static
69
+ # .gemspec file, which is useful if something (i.e. GitHub) will
70
+ # be automatically building a gem for this project. If you're not
71
+ # using GitHub, edit as appropriate.
72
+ #
73
+ # To publish your gem online, install the 'gemcutter' gem; Read more
74
+ # about that here: http://gemcutter.org/pages/gem_docs
75
+ Gem::PackageTask.new(spec) do |pkg|
76
+ pkg.gem_spec = spec
77
+ end
78
+
79
+ desc "Build the gemspec file #{spec.name}.gemspec"
80
+ task :gemspec do
81
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
82
+ File.open(file, "w") {|f| f << spec.to_ruby }
83
+ end
84
+
85
+ # If you don't want to generate the .gemspec file, just remove this line. Reasons
86
+ # why you might want to generate a gemspec:
87
+ # - using bundler with a git source
88
+ # - building the gem without rake (i.e. gem build blah.gemspec)
89
+ # - maybe others?
90
+ task :package => :gemspec
91
+
92
+ # Generate documentation
93
+ RDoc::Task.new do |rd|
94
+ rd.main = "README"
95
+ rd.rdoc_files.include("README", "lib/**/*.rb")
96
+ rd.rdoc_dir = "rdoc"
97
+ end
98
+
99
+ desc 'Clear out RDoc and generated packages'
100
+ task :clean => [:clobber_rdoc, :clobber_package] do
101
+ rm "#{spec.name}.gemspec"
53
102
  end
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ - add some tests
2
+
data/lib/timetrackr.rb CHANGED
@@ -1,10 +1,5 @@
1
1
  module TimeTrackr
2
-
3
2
  require 'time'
4
3
  require 'timetrackr/database'
5
4
  require 'timetrackr/period'
6
-
7
- autoload 'YamlDatabase', 'timetrackr/yaml'
8
- autoload 'SqliteDatabase', 'timetrackr/sqlite'
9
- autoload 'JsonDatabase', 'timetrackr/json'
10
5
  end
@@ -1,9 +1,8 @@
1
1
  module TimeTrackr
2
2
  class CLI
3
3
  DEFAULTS = {
4
- 'backend' => 'yaml',
5
4
  'verbose' => false,
6
- 'single_task' => false,
5
+ 'single_task' => true,
7
6
  'path' => File.join(ENV['HOME'],'.timetrackr.db'),
8
7
  'relative_format' => "%2<hours>dh %2<minutes>dm %2<seconds>ds",
9
8
  'absolute_time' => "%H:%M",
@@ -38,8 +37,7 @@ module TimeTrackr
38
37
 
39
38
  def initialize(config)
40
39
  @config = config
41
- @verbose = config['verbose']
42
- @trackr = TimeTrackr::Database.create(config['backend'], config)
40
+ @trackr = TimeTrackr::Database.new(config)
43
41
  end
44
42
 
45
43
  #
@@ -56,17 +54,16 @@ module TimeTrackr
56
54
  @trackr.current.each { |t|
57
55
  @trackr.stop(t) unless t == task
58
56
  }
59
- puts "Switched to task '#{task}'" if @verbose
57
+ puts "Switched to task '#{task}'" if @config['verbose']
60
58
  else
61
- puts "Started task '#{task}'" if @verbose
59
+ puts "Started task '#{task}'" if @config['verbose']
62
60
  end
63
61
  @trackr.start(task, notes)
64
62
 
65
63
  when 'stop','out','kill','k'
66
- tasks = get_tasks(args)
67
- tasks.each do |task|
64
+ get_tasks(args).each do |task|
68
65
  @trackr.stop(task)
69
- puts "Stopped task '#{task}'" if @verbose
66
+ puts "Stopped task '#{task}'" if @config['verbose']
70
67
  end
71
68
 
72
69
  when 'switch','sw'
@@ -76,34 +73,44 @@ module TimeTrackr
76
73
  @trackr.stop(t) unless t == task
77
74
  end
78
75
  @trackr.start(task, notes)
79
- puts "Switched to task '#{task}'" if @verbose
76
+ puts "Switched to task '#{task}'" if @config['verbose']
80
77
 
81
78
  when 'time','status',nil
82
79
  tasks = get_tasks(args)
83
80
  puts create_log(tasks,'t')
84
81
 
85
82
  when 'log'
86
- group = args.shift[1] if ['-d','-t'].include?(args[0])
83
+ group = args.shift[1] if ['-d','-t','-s'].include?(args[0])
87
84
 
88
85
  tasks = get_tasks(args)
89
86
  puts create_log(tasks,group)
90
87
 
91
88
  when 'clear','delete','del'
92
- tasks = get_tasks(args)
93
- tasks.each do |task|
89
+ get_tasks(args).each do |task|
94
90
  @trackr.clear(task)
95
- puts "Task '#{task}' cleared" if @verbose
91
+ puts "Task '#{task}' cleared" if @config['verbose']
96
92
  end
97
93
 
98
94
  when 'rename','mv'
99
95
  from = args.shift
100
96
  to = args.shift
101
97
  @trackr.rename(from,to)
102
- puts "Renamed '#{from}' to '#{to}'" if @verbose
98
+ puts "Renamed '#{from}' to '#{to}'" if @config['verbose']
99
+
100
+ when 'mark','note','n'
101
+ notes = args.join(' ')
102
+ @trackr.current.each do |t|
103
+ @trackr.stop(t)
104
+ @trackr.start(t, notes)
105
+ end
106
+ puts "Annotated task(s) '#{@trackr.current.join(' ')}'" if @config['verbose']
103
107
 
104
108
  when 'help'
105
109
  show_help
106
110
 
111
+ when 'config'
112
+ puts @config.to_yaml
113
+
107
114
  else
108
115
  puts "'#{cmd}' is not a valid command"
109
116
  show_help
@@ -115,10 +122,12 @@ module TimeTrackr
115
122
  protected
116
123
 
117
124
  def get_tasks(args)
125
+ # if 'all' add them all to the start
118
126
  if args[0].nil? || args[0] == 'all' || args[0] == '-n'
119
127
  args.unshift(@trackr.tasks).flatten!.delete('all')
120
128
  end
121
129
 
130
+ # any negated tasks?
122
131
  split = args.index('-n') || args.length
123
132
  show = args.slice(0...split).compact.uniq
124
133
  ignore =[*args.slice(split+1..-1)].compact.uniq
@@ -136,40 +145,49 @@ module TimeTrackr
136
145
  end
137
146
 
138
147
  def create_log(tasks,group=nil)
139
- totals = Hash.new(0)
140
- days = {}
148
+ unless group.nil?
149
+ totals = Hash.new(0)
150
+ days = {}
151
+ end
141
152
  table = []
142
- # get all periods for selected tasks
143
- periods = tasks.each.collect{ |t| @trackr.history(t) }.flatten
144
153
  lastday = nil
145
- periods.sort{|x,y| x.start <=> y.start}.collect do |period|
154
+
155
+ # get all periods for selected tasks
156
+ tasks.each.collect{ |t| @trackr.history(t) }.flatten.sort{ |x,y| x.start <=> y.start }.collect do |period|
146
157
  currday = period.start.strftime(@config['absolute_day'])
147
158
  if currday == lastday
148
159
  day = ''
149
160
  else
150
161
  day = currday
151
- days[day] = Hash.new(0)
162
+ days[day] = Hash.new(0) unless group.nil?
152
163
  end
153
164
  lastday = currday
154
165
 
155
- start = period.start.strftime(@config['absolute_time'])
156
- stop = period.current? ? ' ' : period.stop.strftime(@config['absolute_time'])
157
- name = period.current? ? period.task+' *' : period.task
158
- notes = period.notes
159
- length = format_time(period.length, @config['relative_format'])
160
-
161
- totals[period.task] = totals[period.task] + period.length if group == 't'
162
- days[currday][period.task] = days[currday][period.task] + period.length if group == 'd'
163
- # for full log
164
- table << "#{day.ljust(12)} #{name.ljust(15)} #{start} - #{stop.ljust(5)} #{length} #{notes}" if group.nil?
166
+ if group.nil?
167
+ # full log
168
+ name = period.current? ? period.task+' *' : period.task
169
+ start = period.start.strftime(@config['absolute_time'])
170
+ stop = period.current? ? ' ' : period.stop.strftime(@config['absolute_time'])
171
+ length = format_time(period.length, @config['relative_format'])
172
+ notes = period.notes
173
+ table << "#{day.ljust(12)} #{name.ljust(15)} #{start} - #{stop.ljust(5)} #{length} #{notes}"
174
+
175
+ elsif group == 's'
176
+ days[currday]['summary'] = days[currday]['summary'] + period.length
177
+ else
178
+ totals[period.task] = totals[period.task] + period.length
179
+ days[currday][period.task] = days[currday][period.task] + period.length
180
+ end
165
181
  end
166
182
 
183
+ # build the table for groupings
167
184
  case group
168
185
  when 't'
169
186
  tasks.each do |task|
170
187
  name = @trackr.current.include?(task) ? task+' *' : task
171
188
  table << name.ljust(15) + format_time(totals[task],@config['relative_format'])
172
189
  end
190
+
173
191
  when 'd'
174
192
  prev_date = ''
175
193
  days.each_pair do |date,tasks|
@@ -180,7 +198,14 @@ module TimeTrackr
180
198
  table << "#{date_string.ljust(12)} #{name.ljust(15)} " + format_time(length, @config['relative_format'])
181
199
  end
182
200
  end
201
+
202
+ when 's'
203
+ days.each_pair do |date,day|
204
+ table << "#{date.ljust(12)} " + format_time(day['summary'], @config['relative_format'])
205
+ end
183
206
  end
207
+
208
+ # spit it out
184
209
  table
185
210
  end
186
211
 
@@ -193,11 +218,17 @@ module TimeTrackr
193
218
 
194
219
  Available commands:
195
220
 
196
- start [task] start a task
197
- stop [task] stop a task (or 'all')
198
- switch TASK switch tasks
199
- time [task] show time for a task (or 'all')
200
- log [task] show time log for a task (or 'all')
221
+ start TASK start a task
222
+ stop [TASK] stop a task (or 'all')
223
+ switch TASK switch tasks
224
+ log [TASK] show time log for a task (or 'all')
225
+ -d group by day
226
+ -t group by task
227
+ -s summary (by day, no tasks)
228
+ time [TASK] same as 'log -t'
229
+ mark NOTES add notes to all current tasks
230
+ rename OLD NEW rename a task
231
+ config current config
201
232
 
202
233
  Global options
203
234
  -h --help show this help
@@ -1,103 +1,109 @@
1
+ #
2
+ # keeps the following format in a yaml file:
3
+ #
4
+ # :current: []
5
+ #
6
+ # :tasks:
7
+ # foo:
8
+ # - :start: 2011-05-16 14:26:26.263449 +07:00
9
+ # :stop: 2011-05-16 14:26:27 +07:00
10
+ # :notes: "blah blah blah"
11
+ #
1
12
 
2
13
  module TimeTrackr
3
14
  class Database
4
- def self.create(type, options={})
5
- case type.to_s
6
- when 'yaml'
7
- begin
8
- require 'yaml'
9
- db = TimeTrackr::YamlDatabase.new(options['path'])
10
- puts 'Loaded YAML tracker' if options['verbose']
11
- rescue LoadError
12
- puts 'YAML not found'
15
+ def initialize(options={})
16
+ @options = options
17
+ begin
18
+ require 'yaml'
19
+ @log_path = options['path']
20
+ if !File.exist? @log_path
21
+ @db = {:current => [], :tasks => {}}
22
+ write_file
13
23
  end
14
-
15
- when 'sqlite'
16
- begin
17
- require 'sqlite3'
18
- db = TimeTrackr::SqliteDatabase.new(options['path'])
19
- puts 'Loaded sqlite tracker' if options['verbose']
20
- rescue LoadError
21
- puts 'Sqlite not found'
22
- end
23
-
24
- when 'json'
25
- begin
26
- require 'json'
27
- db = TimeTrackr::JsonDatabase.new(options['path'])
28
- puts 'Loaded JSON database' if options['verbose']
29
- rescue LoadError
30
- puts 'JSON not found'
31
- end
32
-
33
- else
34
- raise "Bad log type: #{type}"
24
+ @db = YAML.load_file(@log_path)
25
+ puts 'Loaded database' if options['verbose']
26
+ rescue LoadError
27
+ puts 'YAML not found'
35
28
  end
36
- db
37
29
  end
38
30
 
39
31
  #
40
32
  # return an array of current tasks
41
33
  #
42
34
  def current
43
- raise 'Not Implemented'
35
+ @db[:current]
44
36
  end
45
37
 
46
38
  #
47
- # start a period with optional notes
48
- #
49
- def start(task,notes)
50
- raise 'Not implemented'
51
- end
52
-
53
- #
54
- # stop a period
39
+ # return an array of all tasks
55
40
  #
56
- def stop(task)
57
- raise 'Not implemented'
41
+ def tasks
42
+ @db[:tasks].keys.compact.uniq || []
58
43
  end
59
44
 
60
45
  #
61
- # return an array of all tasks
46
+ # start a period with optional notes
62
47
  #
63
- def tasks
64
- raise 'Not Implemented'
48
+ def start(task, notes)
49
+ @db[:tasks][task] = Array[] unless @db[:tasks][task]
50
+ if !@db[:current].include?(task)
51
+ @db[:current].unshift(task)
52
+ @db[:tasks][task].push({:start => Time.now, :notes => notes})
53
+ end
65
54
  end
66
55
 
67
56
  #
68
- # time in task in seconds
57
+ # stop a period
69
58
  #
70
- def time(task)
71
- raise 'Not implemented'
59
+ def stop(task)
60
+ if @db[:current].include?(task)
61
+ @db[:current].delete(task)
62
+ @db[:tasks][task].last[:stop] = Time.now
63
+ end
72
64
  end
73
65
 
74
66
  #
75
67
  # get task history as an array of Periods
76
68
  #
77
- def history(task)
78
- raise 'Not Implemented'
69
+ def history(task, p_begin=nil, p_end=nil)
70
+ @db[:tasks][task].sort{|x,y| x[:start] <=> y[:start]}.collect {|p|
71
+ Period.new(task,p[:start],p[:stop],p[:notes])
72
+ } unless !@db[:tasks].include? task
79
73
  end
80
74
 
81
75
  #
82
76
  # rename a task
83
77
  #
84
78
  def rename(from, to)
85
- raise 'Not implemented'
79
+ @db[:tasks][to] = @db[:tasks].delete(from)
80
+ if @db[:current].delete(from)
81
+ @db[:current].unshift(to)
82
+ end
86
83
  end
87
84
 
88
85
  #
89
- # clear an task
86
+ # cleanup and close
90
87
  #
91
- def clear(task)
92
- raise 'Not Implemented'
88
+ def close
89
+ write_file
93
90
  end
94
91
 
95
92
  #
96
- # cleanup and close
93
+ # clear an task
97
94
  #
98
- def close
95
+ def clear(task)
96
+ @db[:current].delete(task)
97
+ @db[:tasks].delete(task)
99
98
  end
100
99
 
100
+ private
101
+
102
+ def write_file
103
+ File.open(@log_path,'w') do |fh|
104
+ YAML.dump(@db,fh)
105
+ puts 'Saved database' if @options['verbose']
106
+ end
107
+ end
101
108
  end
102
109
  end
103
-
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: timetrackr
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.6
5
+ version: 0.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Felix Hanley
@@ -10,109 +10,40 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-06-02 00:00:00 +07:00
14
- default_executable: timetrackr
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
17
- name: sqlite3
18
- requirement: &id001 !ruby/object:Gem::Requirement
19
- none: false
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
24
- type: :development
25
- prerelease: false
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: json
29
- requirement: &id002 !ruby/object:Gem::Requirement
30
- none: false
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: "0"
35
- type: :development
36
- prerelease: false
37
- version_requirements: *id002
38
- - !ruby/object:Gem::Dependency
39
- name: shoulda
40
- requirement: &id003 !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- version: "0"
46
- type: :development
47
- prerelease: false
48
- version_requirements: *id003
49
- - !ruby/object:Gem::Dependency
50
- name: bundler
51
- requirement: &id004 !ruby/object:Gem::Requirement
52
- none: false
53
- requirements:
54
- - - ~>
55
- - !ruby/object:Gem::Version
56
- version: 1.0.0
57
- type: :development
58
- prerelease: false
59
- version_requirements: *id004
60
- - !ruby/object:Gem::Dependency
61
- name: jeweler
62
- requirement: &id005 !ruby/object:Gem::Requirement
63
- none: false
64
- requirements:
65
- - - ~>
66
- - !ruby/object:Gem::Version
67
- version: 1.5.2
68
- type: :development
69
- prerelease: false
70
- version_requirements: *id005
71
- - !ruby/object:Gem::Dependency
72
- name: rcov
73
- requirement: &id006 !ruby/object:Gem::Requirement
74
- none: false
75
- requirements:
76
- - - ">="
77
- - !ruby/object:Gem::Version
78
- version: "0"
79
- type: :development
80
- prerelease: false
81
- version_requirements: *id006
82
- description: A simple time tracking utility
13
+ date: 2011-10-28 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description:
83
17
  email: felix@seconddrawer.com.au
84
18
  executables:
85
19
  - timetrackr
86
20
  extensions: []
87
21
 
88
22
  extra_rdoc_files:
89
- - LICENSE.txt
90
- - README.mkd
23
+ - README
91
24
  files:
25
+ - Rakefile
92
26
  - Gemfile
93
27
  - Gemfile.lock
94
- - LICENSE.txt
95
- - README.mkd
96
- - Rakefile
97
- - VERSION
28
+ - LICENSE
29
+ - README
30
+ - CHANGELOG
31
+ - Manifest
32
+ - TODO
98
33
  - bin/timetrackr
99
- - lib/timetrackr.rb
100
- - lib/timetrackr/cli.rb
101
- - lib/timetrackr/database.rb
102
- - lib/timetrackr/json.rb
103
- - lib/timetrackr/period.rb
104
- - lib/timetrackr/sqlite.rb
105
- - lib/timetrackr/yaml.rb
106
34
  - test/helper.rb
107
35
  - test/test_timetrackr.rb
108
- - timetrackr.gemspec
109
- has_rdoc: true
36
+ - lib/timetrackr/period.rb
37
+ - lib/timetrackr/database.rb
38
+ - lib/timetrackr/cli.rb
39
+ - lib/timetrackr.rb
110
40
  homepage: http://github.com/felix/timetrackr
111
- licenses:
112
- - MIT
113
- post_install_message:
114
- rdoc_options: []
41
+ licenses: []
115
42
 
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --main
46
+ - README
116
47
  require_paths:
117
48
  - lib
118
49
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -120,9 +51,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
120
51
  requirements:
121
52
  - - ">="
122
53
  - !ruby/object:Gem::Version
123
- hash: -4452594232215196430
124
- segments:
125
- - 0
126
54
  version: "0"
127
55
  required_rubygems_version: !ruby/object:Gem::Requirement
128
56
  none: false
@@ -133,10 +61,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
61
  requirements: []
134
62
 
135
63
  rubyforge_project:
136
- rubygems_version: 1.6.2
64
+ rubygems_version: 1.8.5
137
65
  signing_key:
138
66
  specification_version: 3
139
67
  summary: A simple time tracking utility
140
- test_files:
141
- - test/helper.rb
142
- - test/test_timetrackr.rb
68
+ test_files: []
69
+
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.1.6
@@ -1,68 +0,0 @@
1
- module TimeTrackr
2
- class JsonDatabase < TimeTrackr::Database
3
-
4
- def initialize(path)
5
- @log_path = path
6
- if !File.exist? @log_path
7
- @db = {'current' => [], 'tasks' => {}}
8
- write_file
9
- end
10
- File.open(@log_path,'r') do |fh|
11
- @db = JSON.load(fh)
12
- end
13
- end
14
-
15
- def current
16
- @db['current']
17
- end
18
-
19
- def tasks
20
- @db['tasks'].keys.compact.uniq || []
21
- end
22
-
23
- def start(task, notes)
24
- @db['tasks'][task] = Array[] unless @db['tasks'][task]
25
- if !@db['current'].include?(task)
26
- @db['current'].unshift(task)
27
- @db['tasks'][task].push({'start' => Time.now, 'notes' => notes})
28
- end
29
- end
30
-
31
- def stop(task)
32
- if @db['current'].include?(task)
33
- @db['current'].delete(task)
34
- @db['tasks'][task].last['stop'] = Time.now
35
- end
36
- end
37
-
38
- def history(task, p_begin=nil, p_end=nil)
39
- @db['tasks'][task].sort{|x,y| x['start'] <=> y['start']}.collect {|p|
40
- Period.new(task,p['start'],p['stop'],p['notes'])
41
- } unless !@db['tasks'].include? task
42
- end
43
-
44
- def rename(from, to)
45
- @db['tasks'][to] = @db['tasks'].delete(from)
46
- if @db['current'].delete(from)
47
- @db['current'].unshift(to)
48
- end
49
- end
50
-
51
- def close
52
- write_file
53
- end
54
-
55
- def clear(task)
56
- @db['current'].delete(task)
57
- @db['tasks'].delete(task)
58
- end
59
-
60
- private
61
-
62
- def write_file
63
- File.open(@log_path,'w') do |fh|
64
- JSON.dump(@db,fh)
65
- end
66
- end
67
- end
68
- end
@@ -1,71 +0,0 @@
1
- module TimeTrackr
2
- class SqliteDatabase < TimeTrackr::Database
3
-
4
- def initialize(path)
5
- @log_path = path
6
- if !File.exist? @log_path
7
- @db = SQLite3::Database.new(@log_path)
8
- sql_events = "CREATE TABLE events (
9
- id INTEGER PRIMARY KEY,
10
- task TEXT,
11
- start TIME,
12
- stop TIME,
13
- notes TEXT);"
14
- @db.execute(sql_events)
15
- else
16
- @db = SQLite3::Database.open(@log_path)
17
- end
18
- @db.type_translation = true
19
- end
20
-
21
- def current
22
- sql = "SELECT DISTINCT task FROM events WHERE stop IS NULL;"
23
- @db.execute(sql).collect{|row|
24
- row.first
25
- }
26
- end
27
-
28
- def tasks
29
- sql = "SELECT DISTINCT task FROM events;"
30
- @db.execute(sql).collect{ |row|
31
- row.first
32
- }
33
- end
34
-
35
- def start(task, notes)
36
- sql = "SELECT id FROM events WHERE task = :task AND stop IS NULL;"
37
- exists = @db.get_first_value(sql, 'task' => task)
38
- if !exists
39
- sql = "INSERT INTO events (task,start,notes) VALUES (:task,:start,:notes);"
40
- @db.execute(sql,'task' => task, 'start' => Time.now.to_s, 'notes' => notes)
41
- end
42
- end
43
-
44
- def stop(task)
45
- sql = "SELECT id FROM events WHERE task = :task AND stop IS NULL;"
46
- exists = @db.get_first_value(sql, 'task' => task)
47
- if exists
48
- sql = "UPDATE events SET stop = :stop WHERE id = :current;"
49
- @db.execute(sql, 'current' => exists, 'stop' => Time.now.to_s)
50
- end
51
- end
52
-
53
- def history(task, p_begin=nil, p_end=nil)
54
- sql = "SELECT start, stop, notes FROM events WHERE task = :task ORDER BY start;"
55
- @db.execute(sql,'task' => task).collect{ |row|
56
- Period.new(task,row[0],row[1],row[2])
57
- }
58
- end
59
-
60
- def rename(from, to)
61
- sql = "UPDATE events SET task = :to WHERE task = :from;"
62
- @db.execute(sql, 'to' => to, 'from' => from)
63
- end
64
-
65
- def clear(task)
66
- sql = "DELETE FROM events WHERE task = :task;"
67
- @db.execute(sql, 'task' => task)
68
- end
69
-
70
- end
71
- end
@@ -1,78 +0,0 @@
1
- #
2
- # keeps the following format in a yaml file:
3
- #
4
- # :current: []
5
- #
6
- # :tasks:
7
- # foo:
8
- # - :start: 2011-05-16 14:26:26.263449 +07:00
9
- # :stop: 2011-05-16 14:26:27 +07:00
10
- # :notes: "blah blah blah"
11
- #
12
-
13
- module TimeTrackr
14
- class YamlDatabase < TimeTrackr::Database
15
-
16
- def initialize(path)
17
- @log_path = path
18
- if !File.exist? @log_path
19
- @db = {:current => [], :tasks => {}}
20
- write_file
21
- end
22
- @db = YAML.load_file(@log_path)
23
- end
24
-
25
- def current
26
- @db[:current]
27
- end
28
-
29
- def tasks
30
- @db[:tasks].keys.compact.uniq || []
31
- end
32
-
33
- def start(task, notes)
34
- @db[:tasks][task] = Array[] unless @db[:tasks][task]
35
- if !@db[:current].include?(task)
36
- @db[:current].unshift(task)
37
- @db[:tasks][task].push({:start => Time.now, :notes => notes})
38
- end
39
- end
40
-
41
- def stop(task)
42
- if @db[:current].include?(task)
43
- @db[:current].delete(task)
44
- @db[:tasks][task].last[:stop] = Time.now
45
- end
46
- end
47
-
48
- def history(task, p_begin=nil, p_end=nil)
49
- @db[:tasks][task].sort{|x,y| x[:start] <=> y[:start]}.collect {|p|
50
- Period.new(task,p[:start],p[:stop],p[:notes])
51
- } unless !@db[:tasks].include? task
52
- end
53
-
54
- def rename(from, to)
55
- @db[:tasks][to] = @db[:tasks].delete(from)
56
- if @db[:current].delete(from)
57
- @db[:current].unshift(to)
58
- end
59
- end
60
-
61
- def close
62
- write_file
63
- end
64
-
65
- def clear(task)
66
- @db[:current].delete(task)
67
- @db[:tasks].delete(task)
68
- end
69
-
70
- private
71
-
72
- def write_file
73
- File.open(@log_path,'w') do |fh|
74
- YAML.dump(@db,fh)
75
- end
76
- end
77
- end
78
- end
data/timetrackr.gemspec DELETED
@@ -1,77 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{timetrackr}
8
- s.version = "0.1.6"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Felix Hanley"]
12
- s.date = %q{2011-06-02}
13
- s.default_executable = %q{timetrackr}
14
- s.description = %q{A simple time tracking utility}
15
- s.email = %q{felix@seconddrawer.com.au}
16
- s.executables = ["timetrackr"]
17
- s.extra_rdoc_files = [
18
- "LICENSE.txt",
19
- "README.mkd"
20
- ]
21
- s.files = [
22
- "Gemfile",
23
- "Gemfile.lock",
24
- "LICENSE.txt",
25
- "README.mkd",
26
- "Rakefile",
27
- "VERSION",
28
- "bin/timetrackr",
29
- "lib/timetrackr.rb",
30
- "lib/timetrackr/cli.rb",
31
- "lib/timetrackr/database.rb",
32
- "lib/timetrackr/json.rb",
33
- "lib/timetrackr/period.rb",
34
- "lib/timetrackr/sqlite.rb",
35
- "lib/timetrackr/yaml.rb",
36
- "test/helper.rb",
37
- "test/test_timetrackr.rb",
38
- "timetrackr.gemspec"
39
- ]
40
- s.homepage = %q{http://github.com/felix/timetrackr}
41
- s.licenses = ["MIT"]
42
- s.require_paths = ["lib"]
43
- s.rubygems_version = %q{1.6.2}
44
- s.summary = %q{A simple time tracking utility}
45
- s.test_files = [
46
- "test/helper.rb",
47
- "test/test_timetrackr.rb"
48
- ]
49
-
50
- if s.respond_to? :specification_version then
51
- s.specification_version = 3
52
-
53
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
- s.add_development_dependency(%q<sqlite3>, [">= 0"])
55
- s.add_development_dependency(%q<json>, [">= 0"])
56
- s.add_development_dependency(%q<shoulda>, [">= 0"])
57
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
58
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
59
- s.add_development_dependency(%q<rcov>, [">= 0"])
60
- else
61
- s.add_dependency(%q<sqlite3>, [">= 0"])
62
- s.add_dependency(%q<json>, [">= 0"])
63
- s.add_dependency(%q<shoulda>, [">= 0"])
64
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
65
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
66
- s.add_dependency(%q<rcov>, [">= 0"])
67
- end
68
- else
69
- s.add_dependency(%q<sqlite3>, [">= 0"])
70
- s.add_dependency(%q<json>, [">= 0"])
71
- s.add_dependency(%q<shoulda>, [">= 0"])
72
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
73
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
74
- s.add_dependency(%q<rcov>, [">= 0"])
75
- end
76
- end
77
-