tempo-cli 0.2.4 → 0.2.5

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: 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