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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +13 -12
- data/bin/tempo +7 -11
- data/features/end.feature +3 -2
- data/features/project.feature +7 -0
- data/features/start.feature +35 -0
- data/lib/tempo/controllers/projects_controller.rb +4 -0
- data/lib/tempo/controllers/start_controller.rb +31 -8
- data/lib/tempo/models/log.rb +16 -7
- data/lib/tempo/models/time_record.rb +1 -1
- data/lib/tempo/version.rb +1 -1
- data/lib/tempo/views/base.rb +4 -0
- data/lib/tempo/views/formatters/screen.rb +1 -1
- data/lib/time_utilities.rb +5 -0
- data/test/lib/tempo/models/log_test.rb +9 -1
- data/test/lib/time_utilities_test.rb +26 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f1e31cb5d21c90343bf98498d67ece6b53532fe
|
4
|
+
data.tar.gz: 22380af6098cebe55438b9878a5324f4024d414b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4cd63f381d1b7267e0951a2aa3f709fffadc25db098c7581e929254c28fe36ca334c849243b79d22e407ea41c582f642d44ad4784617b01373ba5fb535e77507
|
7
|
+
data.tar.gz: 64038cd234cecf689e3f48c20719de6d1c9843c87952570bb73ffb74c70eaea4a4548ba2532e813ff087d5ad5bbe1722e3f919dbb17ca8decfe2ea584b3b6dad
|
data/Gemfile.lock
CHANGED
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
|
72
|
-
--
|
73
|
-
--
|
74
|
-
--
|
75
|
-
--
|
76
|
-
--
|
77
|
-
--
|
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
|
-
--
|
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
|
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 -
|
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
|
-
#
|
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
|
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
|
data/features/project.feature
CHANGED
@@ -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"`
|
data/features/start.feature
CHANGED
@@ -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`
|
@@ -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
|
-
|
16
|
+
start_time = Time.new()
|
17
17
|
else
|
18
|
-
|
18
|
+
start_time = Time.parse options[:at]
|
19
19
|
end
|
20
20
|
|
21
|
-
return Views.no_match_error( "valid timeframe", options[:at], false ) if
|
21
|
+
return Views.no_match_error( "valid timeframe", options[:at], false ) if start_time.nil?
|
22
22
|
|
23
|
-
|
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
|
-
|
28
|
-
return Views.no_match_error( "valid timeframe", options[:end], false ) if
|
29
|
-
opts[:end_time] =
|
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
|
-
|
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
|
data/lib/tempo/models/log.rb
CHANGED
@@ -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
|
-
#
|
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
|
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
|
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
data/lib/tempo/views/base.rb
CHANGED
data/lib/time_utilities.rb
CHANGED
@@ -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
|
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
|
+
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-
|
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
|