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