tempo-cli 0.2.3 → 0.2.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea6cc8f7f2251d38ac0f1302e37a0f2cf93fa3d4
4
- data.tar.gz: 2e8cce29f69bbc7468034c872084ff4e0952e5e2
3
+ metadata.gz: 020b9afac83811fcaf37f57bf03ba5553677134f
4
+ data.tar.gz: 90c5735ba9f705f1a8428a7c99cdcb0dcb74cf3f
5
5
  SHA512:
6
- metadata.gz: 516fe4c8216081c83a2ce43436cce83827aecccba3823956e236ed7f1bc0e86f67cde7c63537dab655ae60e4dc7610a1e5649858474bb118926ded4aed3ee5e6
7
- data.tar.gz: 8c0b3784dfd824eb13343662c061eaf6f4f7ec308458a2f706127ee5388d00d1b20983e5cc0df0e13ce0c170204b70720cefc8164135d948caf8bd85ffedfffe
6
+ metadata.gz: f1acba9a88b45b4e2f4ba85a301da99e4b880c4681b46fcb0bf2c552f074c865bc66abeab6919c6687f839d4c00157522abff3fa531b466255a86152f781fcca
7
+ data.tar.gz: e5820580c779d3b956ac57ad7c9d799da3951c1cd9b58682aaecd024cdc0208a708f4b758515fce905a5f55176f537adea024e05658b0f45c336fc7512a14824
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tempo-cli (0.2.2)
4
+ tempo-cli (0.2.3)
5
5
  chronic (~> 0.10)
6
6
  gli (~> 2.10)
7
7
 
data/README.md CHANGED
@@ -150,6 +150,7 @@ New projects are added as root projects by default. Use arrange to arrange exist
150
150
  ##### command options
151
151
  --at=time
152
152
  --end=time
153
+ --restart
153
154
 
154
155
  Starts a new time entry, and closes out any running time entries.
155
156
 
@@ -197,6 +198,7 @@ New projects are added as root projects by default. Use arrange to arrange exist
197
198
  --id=number - Select by Id
198
199
  --on=date - Select On Date
199
200
  --project - Update to the active project
201
+ --running - Set the last project back to running (reopen the end-time)
200
202
  --start=time - Update the Start Time
201
203
 
202
204
  update the project, start time, or end time for a time entry.
data/Rakefile CHANGED
@@ -4,6 +4,7 @@ require 'rubygems/package_task'
4
4
  require 'rdoc/task'
5
5
  require 'cucumber'
6
6
  require 'cucumber/rake/task'
7
+ require "fileutils"
7
8
 
8
9
  Rake::RDocTask.new do |rd|
9
10
  rd.rdoc_files.include("lib/**/*.rb","bin/**/*")
@@ -62,4 +63,4 @@ task :clean => [:tests_setup, :tests_teardown]
62
63
 
63
64
  task :default => [:tests_setup, :run_tests, :features, :tests_teardown]
64
65
 
65
- task 'features:focus' => [:tests_setup, :run_tests, 'cucumber:focus', :tests_teardown]
66
+ task 'features:focus' => [:tests_setup, :run_tests, 'cucumber:focus']
data/bin/tempo CHANGED
@@ -261,6 +261,10 @@ To start a time entry at a time other than the current, pass it in as an argumen
261
261
  to the --at flag. This will accept a number of human readable formats, multiple
262
262
  word time formats should be enclosed in quotes.
263
263
 
264
+ Use the --resume flag to start a new time entry with the last used project and description.
265
+
266
+ To reopen the last time entry (change the end time back to 'running') see `tempo update --running`
267
+
264
268
  examples:
265
269
 
266
270
  # start a new time record at the current time with no description
@@ -275,6 +279,9 @@ $ tempo start learning how to do the Hustle --at 'yesterday at 8:00 in the eveni
275
279
  arg_name 'description'
276
280
  command [:start, :s] do |c|
277
281
 
282
+ c.desc 'start an entry using the last description and project'
283
+ c.switch [:r, :resume], negatable: false
284
+
278
285
  c.desc 'end the entry at a given time'
279
286
  c.arg_name 'time'
280
287
  c.flag [:e, :end]
@@ -432,6 +439,9 @@ command [:update, :u] do |c|
432
439
  c.arg_name 'time'
433
440
  c.flag [:s, :start]
434
441
 
442
+ c.desc 'Change the last time entry back to actively running (ignores all other options)'
443
+ c.switch [:r, :running], negatable: false
444
+
435
445
  c.desc 'Update the End Time'
436
446
  c.arg_name 'time'
437
447
  c.flag [:e, :end]
@@ -487,7 +497,7 @@ on_error do |exception|
487
497
  # return false to skip default error handling
488
498
 
489
499
  # remove before distribution:
490
- # puts exception.backtrace
500
+ puts exception.backtrace
491
501
 
492
502
  true
493
503
  end
data/features/end.feature CHANGED
@@ -40,6 +40,7 @@ Feature: End Command ends the current time record
40
40
  And I run `tempo end --at "1-5-2014 15:00"`
41
41
  Then the stdout should contain "time record ended"
42
42
  And the output should match /7:00 - 15:00/
43
+
43
44
  @pending
44
45
  Scenario: Attempting to end after the beginning time
45
46
  Given an existing project file
@@ -59,7 +60,3 @@ Feature: End Command ends the current time record
59
60
  And the time record 20140101 should contain ":end_time: 2014-01-01 23:59" at line 5
60
61
  And the time record 20140102 should contain ":end_time: 2014-01-01 23:59" at line 5
61
62
  And the time record 20140103 should contain ":end_time: 2014-01-01 10:00" at line 5
62
-
63
-
64
-
65
-
@@ -70,6 +70,29 @@ Feature: Start Command starts a new time record
70
70
  Then the stdout should contain "time record started"
71
71
  And the time record 20140101 should contain ":end_time: 2014-01-01 10:00" at line 5
72
72
 
73
+ Scenario: Resuming the last time record
74
+ Given an existing project file
75
+ When I run `tempo start --at "1-1-2014 10:00" tweezing the cactus`
76
+ And I run `tempo end --at "1-1-2014 12:00"`
77
+ And I successfully run `tempo start --resume --at "1-1-2014 13:00"`
78
+ Then the stdout should contain "time record started"
79
+ And the time record 20140101 should contain ":description: tweezing the cactus" at line 11
80
+
81
+ Scenario: Resuming the last time record with a different project checked out ignores current project
82
+ Given an existing project file
83
+ When I run `tempo start --at "1-1-2014 10:00" tweezing the cactus`
84
+ And I run `tempo end --at "1-1-2014 12:00"`
85
+ And I run `tempo checkout basement mushrooms`
86
+ And I successfully run `tempo start --resume --at "1-1-2014 13:00"`
87
+ Then the stdout should contain "time record started"
88
+ And the time record 20140101 should contain ":project_title: horticulture" at line 10
89
+
90
+ Scenario: Attempting to resume the last project when one is running
91
+ Given an existing project file
92
+ When I run `tempo start --at "1-1-2014 10:00"`
93
+ And I run `tempo start --resume`
94
+ Then the stderr should contain "error: cannot resume last time record when it is still running"
95
+
73
96
  Scenario: Adding an earlier day time record should immediately close out
74
97
  Given an existing project file
75
98
  When I run `tempo start --at "1-5-2014 7:00"`
@@ -48,6 +48,14 @@ Feature: Update Command manages edits to the time records
48
48
  Then the stdout should contain "time record updated:\n13:32 - 16:35 [3:03] nano aquarium: trimming the coral"
49
49
  And the time record 20140101 should contain ":end_time: 2014-01-01 16:35:00" at line 37
50
50
 
51
+ Scenario: Restarting the last time record
52
+ Given an existing project file
53
+ When I run `tempo start --at "1-5-2015 7:00"`
54
+ And I run `tempo end --at "1-5-2015 15:00"`
55
+ And I run `tempo update --running`
56
+ Then the stdout should contain "time record updated"
57
+ And the time record 20150105 should contain ":end_time: :running" at line 5
58
+
51
59
  Scenario: Updating to the project for the last time record
52
60
  Given an existing project file
53
61
  And an existing time record file
@@ -73,3 +81,22 @@ Feature: Update Command manages edits to the time records
73
81
  Then the stdout should contain "time record updated:\n07:00 - 08:35 [1:35] horticulture: raking leaves"
74
82
  And the time record 20131201 should contain ":end_time: 2013-12-01 08:35:00" at line 5
75
83
 
84
+ Scenario: Updating the start time on an earlier day passing only time no date
85
+ Given an existing project file
86
+ And an existing time record file
87
+ When I run `tempo start --at "12/1/2013 7:00" --end "12/1/2013 8:00" raking leaves`
88
+ And I run `tempo start --at "12/1/2013 9:00" --end "12/1/2013 10:00" counting rosebuds`
89
+ When I successfully run `tempo update --on "12/1/2013" --id 1 --start "7:35"`
90
+ Then the stdout should contain "time record updated:\n07:35 - 08:00 [0:25] horticulture: raking leaves"
91
+ And the time record 20131201 should contain ":start_time: 2013-12-01 07:35:00" at line 4
92
+
93
+ Scenario: Updating the end time on an earlier day passing only time no date
94
+ Given an existing project file
95
+ And an existing time record file
96
+ When I run `tempo start --at "12/1/2013 7:00" --end "12/1/2013 8:00" raking leaves`
97
+ And I run `tempo start --at "12/1/2013 9:00" --end "12/1/2013 10:00" counting rosebuds`
98
+ When I successfully run `tempo update --on "12/1/2013" --id 1 --end "8:35"`
99
+ Then the stdout should contain "time record updated:\n07:00 - 08:35 [1:35] horticulture: raking leaves"
100
+ And the time record 20131201 should contain ":end_time: 2013-12-01 08:35:00" at line 5
101
+
102
+
@@ -30,7 +30,24 @@ module Tempo
30
30
  end
31
31
 
32
32
  @time_records.load_last_day options
33
- record = @time_records.new(opts)
33
+
34
+ if options[:resume]
35
+ last_record = @time_records.last_record
36
+
37
+ return Views.error("cannot resume last time record when it is still running") if last_record.running?
38
+
39
+ opts[:description] = last_record.description
40
+
41
+ # we use the last used project, but don't save it as current
42
+ # in case a different project has been checked out.
43
+ @projects.current = @projects.find_by_id(last_record.project)
44
+
45
+ record = @time_records.new(opts)
46
+
47
+ else
48
+ record = @time_records.new(opts)
49
+ end
50
+
34
51
  @time_records.save_to_file options
35
52
 
36
53
  Views.start_time_record_view record
@@ -8,12 +8,27 @@ module Tempo
8
8
 
9
9
  class << self
10
10
 
11
+ def running(options, args)
12
+ @time_records.load_last_day options
13
+
14
+ if @time_records.last_record.running?
15
+ Views.message "Last time record is currently running"
16
+ else
17
+ @time_records.last_record.running!
18
+ @time_records.save_to_file options
19
+ Views.update_time_record_view @time_records.last_record
20
+ end
21
+ end
22
+
11
23
  def parse(options, args)
12
24
 
13
25
  reassemble_the args
14
26
 
15
27
  return Views.project_assistance if Model::Project.index.empty?
16
28
 
29
+ # Reopen last record and ignore all other values if passed --running switch
30
+ return running(options, args) if options[:running]
31
+
17
32
  # Load last day, or specific day if options includes an on-date
18
33
  if options[:on]
19
34
  day = Time.parse options[:on]
@@ -52,9 +67,13 @@ module Tempo
52
67
  start_time = Time.parse options[:start]
53
68
  return Views.no_match_error( "valid timeframe", options[:at], false ) if start_time.nil?
54
69
 
55
- # TODO: add "today " to start time and try again if not valid
56
70
  if record.valid_start_time? start_time
57
71
  record.start_time = start_time
72
+
73
+ # try to update the time on the day, to handle updating with time params only
74
+ elsif record.valid_start_time? start_time.on_date(record.start_time)
75
+ record.start_time = start_time.on_date(record.start_time)
76
+
58
77
  else
59
78
  return Views::ViewRecords::Message.new "cannot change start time to #{start_time.strftime('%H:%M')}", category: :error
60
79
  end
@@ -68,6 +87,11 @@ module Tempo
68
87
  # TODO: add "today " to end time and try again if not valid
69
88
  if record.valid_end_time? end_time
70
89
  record.end_time = end_time
90
+
91
+ # try to update the time on the day, to handle updating with time params only
92
+ elsif record.valid_end_time? end_time.on_date(record.end_time)
93
+ record.end_time = end_time.on_date(record.end_time)
94
+
71
95
  else
72
96
  return Views::ViewRecords::Message.new "cannot change end time to #{end_time.strftime('%H:%M')}", category: :error
73
97
  end
@@ -58,6 +58,13 @@ module Tempo
58
58
  FileRecord::FileUtility.new(self, options).log_records
59
59
  end
60
60
 
61
+ # returns the loaded record with the latest start time
62
+ # Only loads records if options[:load] is true
63
+ def last_record(options={})
64
+ load_last_day(options) if options[:load]
65
+ sort_by_start_time.last
66
+ end
67
+
61
68
  # send alternate directory through options
62
69
  def save_to_file(options={})
63
70
  FileRecord::Record.save_log(self, options)
@@ -65,6 +65,7 @@ module Tempo
65
65
 
66
66
  # end time cannot be set to :running, only to a
67
67
  # valid Time object
68
+ # Use running! to restart a time record
68
69
  #
69
70
  def end_time=time
70
71
  raise ArgumentError if !time.kind_of? Time
@@ -154,6 +155,11 @@ module Tempo
154
155
  @end_time == :running
155
156
  end
156
157
 
158
+ def running!
159
+ raise "only the most recent record can be reopened" unless self == self.class.last_record
160
+ @end_time = :running
161
+ end
162
+
157
163
  def freeze_dry
158
164
  record = super
159
165
  record[:project_title] = project_title
@@ -181,7 +187,7 @@ module Tempo
181
187
 
182
188
  private
183
189
 
184
- #close current at the end time, or on the last minute
190
+ # close current at the end time, or on the last minute
185
191
  # of the day if end time is another day
186
192
  #
187
193
  def self.close_current(end_time)
data/lib/tempo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tempo
2
- VERSION = '0.2.3'
2
+ VERSION = '0.2.4'
3
3
  end
@@ -48,6 +48,14 @@ module Tempo
48
48
  end
49
49
  end
50
50
 
51
+ def message(message)
52
+ ViewRecords::Message.new message, category: :info
53
+ end
54
+
55
+ def error(message)
56
+ ViewRecords::Message.new message, category: :error
57
+ end
58
+
51
59
  def no_match_error(items, request, plural=true)
52
60
  match = plural ? "match" : "matches"
53
61
  ViewRecords::Message.new "no #{items} #{match} the request: #{request}", category: :error
@@ -27,4 +27,9 @@ class Time
27
27
  def add_days(days)
28
28
  t = self + days * 86400 # 24 * 60 * 60
29
29
  end
30
+
31
+ def on_date(date)
32
+ raise ArgumentError if ! date.kind_of? Time
33
+ Time.new(date.year, date.month, date.day, self.hour, self.min, self.sec)
34
+ end
30
35
  end
@@ -11,21 +11,21 @@ describe Tempo::TimeConflictError do
11
11
 
12
12
  it "can create a message with a target duration" do
13
13
  @exception = Tempo::TimeConflictError.new @start_time, @end_time, @target_start_time, @target_end_time
14
- @exception.to_s.must_equal "time <08:15 - 08:45> conflicts with existing record: 07:15 - 09:15"
14
+ @exception.to_s.must_equal "time <08:15 - 08:45> conflicts with existing record: 07:15 - 09:15 on Jan 02, 2014"
15
15
  end
16
16
 
17
17
  it "can create a message with a target time" do
18
18
  @exception = Tempo::TimeConflictError.new @start_time, @end_time, @target_start_time
19
- @exception.to_s.must_equal "time <08:15> conflicts with existing record: 07:15 - 09:15"
19
+ @exception.to_s.must_equal "time <08:15> conflicts with existing record: 07:15 - 09:15 on Jan 02, 2014"
20
20
  end
21
21
 
22
22
  it "can create a message without a target time" do
23
23
  @exception = Tempo::TimeConflictError.new @start_time, @end_time
24
- @exception.to_s.must_equal "time conflicts with existing record: 07:15 - 09:15"
24
+ @exception.to_s.must_equal "time conflicts with existing record: 07:15 - 09:15 on Jan 02, 2014"
25
25
  end
26
26
 
27
27
  it "can handle running time entries" do
28
28
  @exception = Tempo::TimeConflictError.new @start_time, :running, @target_start_time
29
- @exception.to_s.must_equal "time <08:15> conflicts with existing record: 07:15 - running"
29
+ @exception.to_s.must_equal "time <08:15> conflicts with existing record: 07:15 - running on Jan 02, 2014"
30
30
  end
31
- end
31
+ end
@@ -17,7 +17,6 @@ describe Tempo do
17
17
  it "inherits the freeze-dry method" do
18
18
  log_factory
19
19
  frozen = @log_4.freeze_dry
20
- binding.pry if @log_4.id != 1
21
20
  frozen.must_equal({ :start_time=>Time.new(2014, 01, 02, 07, 15),
22
21
  :id=>1, :message=>"day 2 pet the sheep"})
23
22
  end
@@ -182,5 +181,10 @@ describe Tempo do
182
181
  Tempo::Model::MessageLog.days_index[:"20140101"].length.must_equal 2
183
182
  Tempo::Model::MessageLog.days_index[:"20140102"].length.must_equal 3
184
183
  end
184
+
185
+ it "can return the last record" do
186
+ log_factory
187
+ Tempo::Model::MessageLog.last_record.must_equal @log_6
188
+ end
185
189
  end
186
190
  end
@@ -73,6 +73,19 @@ describe Tempo do
73
73
  @record_6.running?.must_equal true
74
74
  end
75
75
 
76
+ it "has a running! method for last record only" do
77
+ time_record_factory
78
+ @record_6.end_time = Time.new(2014, 1, 2, 19, 00 )
79
+ @record_6.running!
80
+ Tempo::Model::TimeRecord.current.must_equal @record_6
81
+ end
82
+
83
+ it "running! method succeeds on last record only" do
84
+ time_record_factory
85
+ proc { @record_1.running!}.must_raise RuntimeError
86
+ end
87
+
88
+
76
89
  it "has a next record method" do
77
90
  time_record_factory
78
91
  @record_1.next_record.must_equal @record_2
@@ -155,7 +168,7 @@ describe Tempo do
155
168
 
156
169
  it "errors when end time is before start time" do
157
170
  Tempo::Model::TimeRecord.clear_all
158
- proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 12 ), end_time: Time.new(2014, 1, 1, 10 ) }) }.must_raise ArgumentError
171
+ proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 12 ), end_time: Time.new(2014, 1, 1, 10 ) }) }.must_raise Tempo::EndTimeError
159
172
  end
160
173
 
161
174
  it "accepts and end time equal to start time" do
@@ -173,7 +186,7 @@ describe Tempo do
173
186
 
174
187
  it "errors when end time is on a different day" do
175
188
  Tempo::Model::TimeRecord.clear_all
176
- proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 10 ), end_time: Time.new(2014, 1, 2, 12 ) }) }.must_raise ArgumentError
189
+ proc { Tempo::Model::TimeRecord.new({ start_time: Time.new(2014, 1, 1, 10 ), end_time: Time.new(2014, 1, 2, 12 ) }) }.must_raise Tempo::DifferentDaysError
177
190
  end
178
191
 
179
192
  it "errors when end time in existing record" do
@@ -212,7 +225,7 @@ describe Tempo do
212
225
  @record = Tempo::Model::TimeRecord.new({project: @project_1,
213
226
  start_time: Time.new(2014, 1, 1, 8 ),
214
227
  end_time: Time.new(2014, 1, 1, 10 ) })
215
- proc { @record.start_time = Time.new(2014, 1, 1, 11 )}.must_raise ArgumentError
228
+ proc { @record.start_time = Time.new(2014, 1, 1, 11 )}.must_raise Tempo::EndTimeError
216
229
 
217
230
  @record.start_time = Time.new(2014, 1, 1, 9 )
218
231
  @record.start_time.must_equal Time.new(2014, 1, 1, 9 )
@@ -225,7 +238,7 @@ describe Tempo do
225
238
  start_time: Time.new(2014, 1, 1, 8 ),
226
239
  end_time: Time.new(2014, 1, 1, 10 ) })
227
240
 
228
- proc { @record.end_time = Time.new(2014, 1, 1, 7 )}.must_raise ArgumentError
241
+ proc { @record.end_time = Time.new(2014, 1, 1, 7 )}.must_raise Tempo::EndTimeError
229
242
  @record.end_time = Time.new(2014, 1, 1, 11 )
230
243
  @record.end_time.must_equal Time.new(2014, 1, 1, 11 )
231
244
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tempo-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Gabel