tempo-cli 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 020b9afac83811fcaf37f57bf03ba5553677134f
4
- data.tar.gz: 90c5735ba9f705f1a8428a7c99cdcb0dcb74cf3f
3
+ metadata.gz: 6f1e31cb5d21c90343bf98498d67ece6b53532fe
4
+ data.tar.gz: 22380af6098cebe55438b9878a5324f4024d414b
5
5
  SHA512:
6
- metadata.gz: f1acba9a88b45b4e2f4ba85a301da99e4b880c4681b46fcb0bf2c552f074c865bc66abeab6919c6687f839d4c00157522abff3fa531b466255a86152f781fcca
7
- data.tar.gz: e5820580c779d3b956ac57ad7c9d799da3951c1cd9b58682aaecd024cdc0208a708f4b758515fce905a5f55176f537adea024e05658b0f45c336fc7512a14824
6
+ metadata.gz: 4cd63f381d1b7267e0951a2aa3f709fffadc25db098c7581e929254c28fe36ca334c849243b79d22e407ea41c582f642d44ad4784617b01373ba5fb535e77507
7
+ data.tar.gz: 64038cd234cecf689e3f48c20719de6d1c9843c87952570bb73ffb74c70eaea4a4548ba2532e813ff087d5ad5bbe1722e3f919dbb17ca8decfe2ea584b3b6dad
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tempo-cli (0.2.3)
4
+ tempo-cli (0.2.5)
5
5
  chronic (~> 0.10)
6
6
  gli (~> 2.10)
7
7
 
data/README.md CHANGED
@@ -68,13 +68,14 @@ Time record ids are on a per-day basis, and begin again with an id of 1 on the n
68
68
 
69
69
  ##### command options
70
70
 
71
- --add - Add a Project
72
- --delete=title - Delete a Project
73
- --exact - Exact Match
74
- --id - List by or perform command by project Id
75
- --list - List Projects
76
- --tag=tagword - Tag a Project
77
- --untag=tagword - Untag a Project
71
+ --add - Add a Project
72
+ --child - Add a Project as a child of the current Project
73
+ --delete=title - Delete a Project (default: none)
74
+ --exact - Exact Match
75
+ --id - List by or perform command by project id
76
+ --list - List Projects
77
+ --tag=tagword - Tag a Project (default: none)
78
+ --untag=tagword - Untag a Project (default: none)
78
79
 
79
80
 
80
81
  Manage the Projects that timed tasks are assigned to. By default, lists the current project, or with --list tag, lists all projects. The active project will be marked by an asterisk.
@@ -148,15 +149,15 @@ New projects are added as root projects by default. Use arrange to arrange exist
148
149
  tempo [global options] start [command options] description
149
150
 
150
151
  ##### command options
151
- --at=time
152
- --end=time
153
- --restart
152
+ --at=time - start the entry at a given time (default: none)
153
+ --end=time - end the entry at a given time (default: none)
154
+ --resume - start an entry using the last description and project
154
155
 
155
156
  Starts a new time entry, and closes out any running time entries.
156
157
 
157
158
  You can also add a description of the time entry.
158
159
 
159
- To start a time entry at a time other than the current, pass it in as an argument to the --at flag. This will accept a number of human readable formats, multiple word time formats should be enclosed in quotes
160
+ To start a time entry at a time other than the current, pass it in as an argument to the --at flag. This will accept a number of human readable formats, multiple-word time formats should be enclosed in quotes
160
161
 
161
162
  ##### examples:
162
163
 
@@ -198,7 +199,7 @@ New projects are added as root projects by default. Use arrange to arrange exist
198
199
  --id=number - Select by Id
199
200
  --on=date - Select On Date
200
201
  --project - Update to the active project
201
- --running - Set the last project back to running (reopen the end-time)
202
+ --running - Change the last time entry back to actively running (ignores all other options)
202
203
  --start=time - Update the Start Time
203
204
 
204
205
  update the project, start time, or end time for a time entry.
data/bin/tempo CHANGED
@@ -112,6 +112,9 @@ command [:project, :p] do |c|
112
112
  c.arg_name 'tagword'
113
113
  c.flag [:u, :untag]
114
114
 
115
+ c.desc 'Add a Project as a child of the current Project'
116
+ c.switch [:c, :child], negatable: false
117
+
115
118
  c.action do |global_options, options, args|
116
119
 
117
120
  controller = Tempo::Controllers::Projects
@@ -457,10 +460,6 @@ command [:update, :u] do |c|
457
460
  end
458
461
 
459
462
  pre do |global,command,options,args|
460
- # Return true to proceed; false to abort and not call the
461
- # chosen command
462
- # Use skips_pre before a command to skip this block
463
- # on that command only
464
463
 
465
464
  # add reporting of all arguments
466
465
  if global[:v]
@@ -480,25 +479,22 @@ pre do |global,command,options,args|
480
479
  # TODO: send formats in through global options, and then:
481
480
  # Tempo::Views::Reporter.add_formats
482
481
 
482
+ # Return true to proceed; false to abort
483
483
  true
484
484
  end
485
485
 
486
486
  post do |global,command,options,args|
487
- # Post logic here
488
- # Use skips_post before a command to skip this
489
- # block on that command only
490
487
 
491
488
  Tempo::Views::Reporter.report
492
489
 
493
490
  end
494
491
 
495
492
  on_error do |exception|
496
- # Error logic here
497
- # return false to skip default error handling
498
493
 
499
- # remove before distribution:
500
- puts exception.backtrace
494
+ # run DEBUG=true tempo ... to see verbose exceptions
495
+ puts exception.backtrace if ENV['DEBUG'] == "true"
501
496
 
497
+ # return false to skip default error handling
502
498
  true
503
499
  end
504
500
 
data/features/end.feature CHANGED
@@ -51,12 +51,13 @@ Feature: End Command ends the current time record
51
51
  @pending
52
52
  Scenario: Ending a time record with tags
53
53
  Given an existing project file
54
+
54
55
  @pending
55
- Scenario: Ending a time record on a previous day
56
+ Scenario: Ending a time record on a previous day creates a record on each day
56
57
  Given an existing project file
57
58
  When I run `tempo start --at "1-1-2014 7:00"`
58
59
  And I run `tempo end --at "1-3-2014 10:00"`
59
- Then the stdout should contain "time record ended"
60
+ Then the stderr should contain "time record ended"
60
61
  And the time record 20140101 should contain ":end_time: 2014-01-01 23:59" at line 5
61
62
  And the time record 20140102 should contain ":end_time: 2014-01-01 23:59" at line 5
62
63
  And the time record 20140103 should contain ":end_time: 2014-01-01 10:00" at line 5
@@ -102,6 +102,13 @@ Feature: Project Command manages a list of projects
102
102
  Then the stdout should contain "added project:\nhang gliding\n"
103
103
  And the project file should contain ":title: hang gliding"
104
104
 
105
+ Scenario: Adding a project as a child of the current
106
+ Given an existing project file
107
+ When I successfully run `tempo project --child hang gliding`
108
+ Then the stdout should contain "added project:\nhang gliding\n"
109
+ And the project file should contain "- 7" at line 7
110
+ And the project file should contain ":parent: 1" at line 52
111
+
105
112
  Scenario: Attempting to add an existing project
106
113
  Given an existing project file
107
114
  When I run `tempo project "basement mushrooms"`
@@ -70,6 +70,41 @@ 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: Adding a future days time record should warn about complications
74
+ Given an existing project file
75
+ When I run `tempo start --at "1-1-2033 10:00"`
76
+ Then the stdout should contain "WARNING"
77
+ And the time record 20330101 should contain ":start_time: 2033-01-01 10:00" at line 4
78
+
79
+ Scenario: Adding a record to a previous day works
80
+ Given an existing project file
81
+ When I run `tempo start --at "7/2/14 10:00" existing entry`
82
+ And I run `tempo start --at "7/1/14 10:00" -e "7/1/2014 11:00" previous entry 1`
83
+ And I run `tempo start --at "7/1/14 11:00" previous entry 2`
84
+ Then the time record 20140701 should contain "previous entry 1" at line 3
85
+ And the time record 20140701 should contain "11:00" at line 5
86
+ And the time record 20140701 should contain "previous entry 2" at line 11
87
+ And the time record 20140701 should contain "23:59" at line 13
88
+
89
+ Scenario: Adding a record to a previous day works
90
+ Given an existing project file
91
+ When I run `tempo start --at "7/2/14 10:00" existing entry`
92
+ And I run `tempo start --at "7/1/14 10:00" previous entry 1`
93
+ And I run `tempo start --at "7/1/14 11:00" previous entry 2`
94
+ Then the stderr should contain "error: time <11:00> conflicts with existing record"
95
+ And the time record 20140701 should contain "previous entry 1" at line 3
96
+ And the time record 20140701 should contain "23:59" at line 5
97
+
98
+ Scenario: Adding a record to a future day works
99
+ Given an existing project file
100
+ When I run `tempo start --at "7/2/33 10:00" existing entry`
101
+ And I run `tempo start --at "7/1/33 10:00" -e "7/1/2033 11:00" previous entry 1`
102
+ And I run `tempo start --at "7/1/33 11:00" previous entry 2`
103
+ Then the time record 20330701 should contain "previous entry 1" at line 3
104
+ And the time record 20330701 should contain "11:00" at line 5
105
+ And the time record 20330701 should contain "previous entry 2" at line 11
106
+ And the time record 20330701 should contain "23:59" at line 13
107
+
73
108
  Scenario: Resuming the last time record
74
109
  Given an existing project file
75
110
  When I run `tempo start --at "1-1-2014 10:00" tweezing the cactus`
@@ -53,6 +53,10 @@ module Tempo
53
53
 
54
54
  if @projects.index.length == 1
55
55
  @projects.current = project
56
+
57
+ # arrange the project as the child of the current project
58
+ elsif options[:child]
59
+ @projects.current << project
56
60
  end
57
61
 
58
62
  @projects.save_to_file options
@@ -13,24 +13,29 @@ module Tempo
13
13
  return Views.project_assistance if Model::Project.index.empty?
14
14
 
15
15
  if not options[:at]
16
- time_in = Time.new()
16
+ start_time = Time.new()
17
17
  else
18
- time_in = Time.parse options[:at]
18
+ start_time = Time.parse options[:at]
19
19
  end
20
20
 
21
- return Views.no_match_error( "valid timeframe", options[:at], false ) if time_in.nil?
21
+ return Views.no_match_error( "valid timeframe", options[:at], false ) if start_time.nil?
22
22
 
23
- opts = { start_time: time_in }
23
+ if start_time > Time.new()
24
+ Views.warning("WARNING: logging time in the future may cause trouble maintaining running records")
25
+ end
26
+
27
+ opts = { start_time: start_time }
24
28
  opts[:description] = reassemble_the args
25
29
 
26
30
  if options[:end]
27
- time_out = Time.parse options[:end]
28
- return Views.no_match_error( "valid timeframe", options[:end], false ) if time_out.nil?
29
- opts[:end_time] = time_out
31
+ end_time = Time.parse options[:end]
32
+ return Views.no_match_error( "valid timeframe", options[:end], false ) if end_time.nil?
33
+ opts[:end_time] = end_time
30
34
  end
31
35
 
32
- @time_records.load_last_day options
36
+ load_records(start_time, options)
33
37
 
38
+ # Restart the last time record
34
39
  if options[:resume]
35
40
  last_record = @time_records.last_record
36
41
 
@@ -44,6 +49,7 @@ module Tempo
44
49
 
45
50
  record = @time_records.new(opts)
46
51
 
52
+ # Add a new time record
47
53
  else
48
54
  record = @time_records.new(opts)
49
55
  end
@@ -51,10 +57,27 @@ module Tempo
51
57
  @time_records.save_to_file options
52
58
 
53
59
  Views.start_time_record_view record
60
+ end
61
+
62
+ private
63
+
64
+ # Load all records necessary to start a new record
65
+ def load_records(start_time, options)
54
66
 
67
+ last_day = @time_records.last_day(options)
68
+
69
+ # No records exits yet
70
+ return if !last_day
71
+
72
+ if start_time.same_day?(last_day) || start_time > last_day
73
+ @time_records.load_last_day options
74
+ else
75
+ @time_records.load_days_records(start_time, last_day, options)
76
+ end
55
77
  end
56
78
 
57
79
  end #class << self
80
+
58
81
  end
59
82
  end
60
83
  end
@@ -59,7 +59,8 @@ module Tempo
59
59
  end
60
60
 
61
61
  # returns the loaded record with the latest start time
62
- # Only loads records if options[:load] is true
62
+ # Only loads records if options[:load] is true,
63
+ # otherwise assumes records are already loaded
63
64
  def last_record(options={})
64
65
  load_last_day(options) if options[:load]
65
66
  sort_by_start_time.last
@@ -99,17 +100,25 @@ module Tempo
99
100
  (days + 1).times { |i| load_day_record(time_1.add_days(i), options)}
100
101
  end
101
102
 
102
- # load the records for the most recently recorded day
103
- #
104
- def load_last_day(options={})
103
+ # Return a Time object for the last record's date
104
+ def last_day(options={})
105
105
  reg = /(\d+)\.yaml/
106
- recs = records(options)
106
+ recs = records options
107
107
  if recs.last
108
108
  d_id = reg.match(recs.last)[1]
109
109
  time = day_id_to_time d_id if d_id
110
- load_day_record time, options
111
110
  return time
112
111
  end
112
+ return nil
113
+ end
114
+
115
+ # load the records for the most recently recorded day
116
+ #
117
+ def load_last_day(options={})
118
+ time = last_day options
119
+ return nil unless time
120
+ load_day_record time, options
121
+ return time
113
122
  end
114
123
 
115
124
  # delete the file for a single day
@@ -157,7 +166,7 @@ module Tempo
157
166
  days_index[dsym].delete instance
158
167
  @ids[dsym].delete id
159
168
  end
160
- end
169
+ end # class << self
161
170
 
162
171
  def initialize(options={})
163
172
  @start_time = options.fetch(:start_time, Time.now)
@@ -1,5 +1,5 @@
1
1
  # Time Record is an extension of the Log Model,
2
- # it adds and end time, and verifies that no records overlap
2
+ # it adds an end time, and verifies that no records overlap
3
3
  # in their time periods. Additionally, one, and only on record
4
4
  # can be running at any given time, and it can only be the most
5
5
  # recent record.
data/lib/tempo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tempo
2
- VERSION = '0.2.4'
2
+ VERSION = '0.2.5'
3
3
  end
@@ -52,6 +52,10 @@ module Tempo
52
52
  ViewRecords::Message.new message, category: :info
53
53
  end
54
54
 
55
+ def warning(message)
56
+ ViewRecords::Message.new message, category: :warning
57
+ end
58
+
55
59
  def error(message)
56
60
  ViewRecords::Message.new message, category: :error
57
61
  end
@@ -18,7 +18,7 @@ module Tempo
18
18
  case m.category
19
19
  when :error
20
20
  raise m.message
21
- when :info, :debug
21
+ when :info, :warning, :debug
22
22
  puts m.message
23
23
  end
24
24
  m.message
@@ -32,4 +32,9 @@ class Time
32
32
  raise ArgumentError if ! date.kind_of? Time
33
33
  Time.new(date.year, date.month, date.day, self.hour, self.min, self.sec)
34
34
  end
35
+
36
+ def same_day?(date)
37
+ raise ArgumentError if ! date.kind_of? Time
38
+ Time.new(date.year, date.month, date.day) == Time.new(self.year, self.month, self.day)
39
+ end
35
40
  end
@@ -92,6 +92,14 @@ describe Tempo do
92
92
  Tempo::Model::MessageLog.index[0].message.must_equal "day 1 pet the sheep"
93
93
  end
94
94
 
95
+ it "knows the date of the last record" do
96
+ log_record_factory
97
+ last_day = Tempo::Model::MessageLog.last_day
98
+ match_day = Time.new(2014, 1, 2)
99
+ Tempo::Model::MessageLog.ids( match_day ).must_equal [] # should not load any records
100
+ last_day.must_equal match_day
101
+ end
102
+
95
103
  it "loads records for most recent and return day" do
96
104
  log_record_factory
97
105
  last_day = Tempo::Model::MessageLog.load_last_day
@@ -101,7 +109,7 @@ describe Tempo do
101
109
  Tempo::Model::MessageLog.ids( time_1 ).must_equal []
102
110
  Tempo::Model::MessageLog.ids( time_2 ).must_equal [1,2,3]
103
111
  Tempo::Model::MessageLog.index[0].message.must_equal "day 2 pet the sheep"
104
- last_day.must_equal Time.new(2014, 1, 2)
112
+ last_day.must_equal time_2
105
113
  end
106
114
 
107
115
  it "loads the records for a time frame" do
@@ -0,0 +1,26 @@
1
+ require "test_helper"
2
+
3
+ describe Time do
4
+
5
+ it "returns nil on invalid information" do
6
+ Time.parse("t").must_equal nil
7
+ end
8
+
9
+ it "rounds to the nearest whole minute" do
10
+ Time.new(2015,6,18,11,33,25).round.must_equal Time.new(2015,6,18,11,33)
11
+ Time.new(2015,6,18,11,33,45).round.must_equal Time.new(2015,6,18,11,34)
12
+ end
13
+
14
+ it "adds days to time" do
15
+ Time.new(2015,6,18,11,33,45).add_days(5).must_equal Time.new(2015,6,23,11,33,45)
16
+ end
17
+
18
+ it "moves time to a different day" do
19
+ Time.new(2015,6,18,11,33,45).on_date(Time.new(2015,6,23)).must_equal Time.new(2015,6,23,11,33,45)
20
+ end
21
+
22
+ it "verifies two times occur on the same day" do
23
+ Time.new(2015,6,18,11,33,45).same_day?(Time.new(2015,6,18,16,22,30)).must_equal true
24
+ Time.new(2015,6,18,11,33,45).same_day?(Time.new(2015,6,17,16,22,30)).must_equal false
25
+ end
26
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tempo-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Gabel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-18 00:00:00.000000000 Z
11
+ date: 2014-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -189,6 +189,7 @@ files:
189
189
  - test/lib/tempo/views/view_records/log_test.rb
190
190
  - test/lib/tempo/views/view_records/project_test.rb
191
191
  - test/lib/tempo/views/view_records/time_record_test.rb
192
+ - test/lib/time_utilities_test.rb
192
193
  - test/support/factories.rb
193
194
  - test/support/helpers.rb
194
195
  - test/test_helper.rb