timr 0.5.0 → 0.6.0
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/README.md +8 -0
- data/bin/.gitignore +1 -0
- data/bin/build_man.sh +1 -0
- data/bin/dev_data.sh +57 -0
- data/bin/dev_setup.sh +2 -0
- data/bin/test.sh +3 -1
- data/bin/test_report.sh +82 -0
- data/bin/timr_bash_completion.sh +13 -1
- data/lib/timr.rb +1 -0
- data/lib/timr/command/basic_command.rb +2 -0
- data/lib/timr/command/log_command.rb +3 -3
- data/lib/timr/command/report_command.rb +109 -71
- data/lib/timr/command/reset_command.rb +75 -0
- data/lib/timr/duration.rb +5 -1
- data/lib/timr/exception/timr_error.rb +4 -0
- data/lib/timr/model/stack.rb +8 -0
- data/lib/timr/model/task.rb +41 -9
- data/lib/timr/model/track.rb +47 -15
- data/lib/timr/timr.rb +45 -3
- data/lib/timr/version.rb +2 -2
- data/man/index.txt +1 -0
- data/man/timr-report.1 +66 -21
- data/man/timr-report.1.ronn +30 -1
- data/man/timr-reset.1 +41 -0
- data/man/timr-reset.1.ronn +33 -0
- data/man/timr.1 +3 -0
- data/man/timr.1.ronn +1 -0
- metadata +7 -2
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module TheFox
|
5
|
+
module Timr
|
6
|
+
module Command
|
7
|
+
|
8
|
+
# Remove current running Track. Paused commands will not be deleted.
|
9
|
+
#
|
10
|
+
# Man page: [timr-reset(1)](../../../../man/timr-reset.1.html)
|
11
|
+
class ResetCommand < BasicCommand
|
12
|
+
|
13
|
+
include TheFox::Timr::Error
|
14
|
+
|
15
|
+
# Path to man page.
|
16
|
+
MAN_PATH = 'man/timr-reset.1'
|
17
|
+
|
18
|
+
def initialize(argv = Array.new)
|
19
|
+
super()
|
20
|
+
|
21
|
+
@help_opt = false
|
22
|
+
@stack_opt = false
|
23
|
+
|
24
|
+
loop_c = 0 # Limit the loop.
|
25
|
+
while loop_c < 1024 && argv.length > 0
|
26
|
+
loop_c += 1
|
27
|
+
arg = argv.shift
|
28
|
+
|
29
|
+
case arg
|
30
|
+
when '-h', '--help'
|
31
|
+
@help_opt = true
|
32
|
+
when '-s', '--stack'
|
33
|
+
@stack_opt = true
|
34
|
+
else
|
35
|
+
raise ResetCommandError, "Unknown argument '#{arg}'. See 'timr report --help'."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# See BasicCommand#run.
|
41
|
+
def run
|
42
|
+
if @help_opt
|
43
|
+
help
|
44
|
+
return
|
45
|
+
end
|
46
|
+
|
47
|
+
@timr = Timr.new(@cwd)
|
48
|
+
|
49
|
+
track = @timr.stack.current_track
|
50
|
+
if track && track.running?
|
51
|
+
puts '--- RESET ---'
|
52
|
+
puts track.to_compact_str
|
53
|
+
puts
|
54
|
+
end
|
55
|
+
|
56
|
+
@timr.reset({:stack => @stack_opt})
|
57
|
+
|
58
|
+
puts @timr.stack
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def help
|
64
|
+
puts 'usage: timr reset [-s|--stack]'
|
65
|
+
puts
|
66
|
+
puts 'Options'
|
67
|
+
puts ' -s, --stack Clean the Stack.'
|
68
|
+
puts
|
69
|
+
end
|
70
|
+
|
71
|
+
end # class TrackCommand
|
72
|
+
|
73
|
+
end # module Command
|
74
|
+
end # module Timr
|
75
|
+
end # module TheFox
|
data/lib/timr/duration.rb
CHANGED
@@ -22,6 +22,7 @@ module TheFox
|
|
22
22
|
# - PopCommandError
|
23
23
|
# - PushCommandError
|
24
24
|
# - ReportCommandError
|
25
|
+
# - ResetCommandError
|
25
26
|
# - StartCommandError
|
26
27
|
# - StatusCommandError
|
27
28
|
# - StopCommandError
|
@@ -82,6 +83,9 @@ module TheFox
|
|
82
83
|
class ReportCommandError < CommandError
|
83
84
|
end
|
84
85
|
|
86
|
+
class ResetCommandError < CommandError
|
87
|
+
end
|
88
|
+
|
85
89
|
class StartCommandError < CommandError
|
86
90
|
end
|
87
91
|
|
data/lib/timr/model/stack.rb
CHANGED
data/lib/timr/model/task.rb
CHANGED
@@ -124,6 +124,15 @@ module TheFox
|
|
124
124
|
true
|
125
125
|
end
|
126
126
|
|
127
|
+
def reset
|
128
|
+
if @current_track
|
129
|
+
@current_track = nil
|
130
|
+
|
131
|
+
# Mark Task as changed.
|
132
|
+
changed
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
127
136
|
# Select Track by Time Range and/or Status.
|
128
137
|
#
|
129
138
|
# Options:
|
@@ -464,7 +473,7 @@ module TheFox
|
|
464
473
|
# Get estimation as String.
|
465
474
|
def estimation_s
|
466
475
|
if @estimation
|
467
|
-
@estimation.
|
476
|
+
@estimation.to_human_s
|
468
477
|
else
|
469
478
|
'---'
|
470
479
|
end
|
@@ -630,9 +639,8 @@ module TheFox
|
|
630
639
|
#
|
631
640
|
# Options:
|
632
641
|
#
|
633
|
-
# - `:billed`
|
642
|
+
# - `:billed` (Boolean)
|
634
643
|
def duration(options = Hash.new)
|
635
|
-
|
636
644
|
billed_opt = options.fetch(:billed, nil)
|
637
645
|
|
638
646
|
duration = Duration.new
|
@@ -678,7 +686,7 @@ module TheFox
|
|
678
686
|
def remaining_time_s
|
679
687
|
rmt = remaining_time
|
680
688
|
if rmt
|
681
|
-
rmt.
|
689
|
+
rmt.to_human_s
|
682
690
|
else
|
683
691
|
'---'
|
684
692
|
end
|
@@ -804,7 +812,7 @@ module TheFox
|
|
804
812
|
to_ax << 'Description: %s' % [self.description]
|
805
813
|
end
|
806
814
|
if self.estimation
|
807
|
-
to_ax << 'Estimation: %s' % [self.estimation.
|
815
|
+
to_ax << 'Estimation: %s' % [self.estimation.to_human_s]
|
808
816
|
end
|
809
817
|
to_ax
|
810
818
|
end
|
@@ -839,7 +847,7 @@ module TheFox
|
|
839
847
|
end
|
840
848
|
|
841
849
|
# Duration
|
842
|
-
duration_human = self.duration.
|
850
|
+
duration_human = self.duration.to_human_s
|
843
851
|
to_ax << 'Duration: %s' % [duration_human]
|
844
852
|
|
845
853
|
duration_man_days = self.duration.to_man_days
|
@@ -937,18 +945,42 @@ module TheFox
|
|
937
945
|
|
938
946
|
# Return formatted String.
|
939
947
|
#
|
948
|
+
# Options:
|
949
|
+
#
|
950
|
+
# - `:format`
|
951
|
+
# - `:prefix` - Default: `%`
|
952
|
+
#
|
953
|
+
# Format:
|
954
|
+
#
|
940
955
|
# - `%id` - ID
|
941
956
|
# - `%sid` - Short ID
|
942
957
|
# - `%fid` - Foreign ID
|
943
958
|
# - `%n` - Name
|
944
959
|
# - `%d` - Description
|
945
|
-
|
946
|
-
|
960
|
+
# - `%ds` - Duration Seconds
|
961
|
+
# - `%dh` - Duration Human Format
|
962
|
+
def formatted(options = Hash.new)
|
963
|
+
format = options.fetch(:format, '')
|
964
|
+
prefix = options.fetch(:prefix, '%')
|
965
|
+
|
966
|
+
formatted_s = format
|
947
967
|
.gsub("#{prefix}id", self.id)
|
948
968
|
.gsub("#{prefix}sid", self.short_id ? self.short_id : '')
|
949
969
|
.gsub("#{prefix}fid", self.foreign_id ? self.foreign_id : '')
|
950
970
|
.gsub("#{prefix}n", self.name ? self.name : '')
|
951
|
-
.gsub("#{prefix}
|
971
|
+
.gsub("#{prefix}ds", self.duration(options).to_s)
|
972
|
+
|
973
|
+
duration_human = self.duration(options).to_human
|
974
|
+
if duration_human
|
975
|
+
formatted_s.gsub!('%dh', duration_human)
|
976
|
+
else
|
977
|
+
formatted_s.gsub!('%dh', '')
|
978
|
+
end
|
979
|
+
|
980
|
+
# Must not before %dh and %ds.
|
981
|
+
formatted_s.gsub!("#{prefix}d", self.description ? self.description : '')
|
982
|
+
|
983
|
+
formatted_s
|
952
984
|
end
|
953
985
|
|
954
986
|
def inspect
|
data/lib/timr/model/track.rb
CHANGED
@@ -223,9 +223,17 @@ module TheFox
|
|
223
223
|
#
|
224
224
|
# - `:from` (Time), `:to` (Time)
|
225
225
|
# Limit the begin and end datetimes to a specific range.
|
226
|
+
# - `:billed` (Boolean)
|
226
227
|
def duration(options = Hash.new)
|
227
228
|
from_opt = options.fetch(:from, nil)
|
228
229
|
to_opt = options.fetch(:to, nil)
|
230
|
+
billed_opt = options.fetch(:billed, nil)
|
231
|
+
|
232
|
+
unless billed_opt.nil?
|
233
|
+
if @is_billed != billed_opt
|
234
|
+
return Duration.new(0)
|
235
|
+
end
|
236
|
+
end
|
229
237
|
|
230
238
|
if @begin_datetime
|
231
239
|
bdt = @begin_datetime.utc
|
@@ -258,20 +266,12 @@ module TheFox
|
|
258
266
|
|
259
267
|
# Alias method.
|
260
268
|
def billed_duration(options = Hash.new)
|
261
|
-
|
262
|
-
duration(options)
|
263
|
-
else
|
264
|
-
Duration.new(0)
|
265
|
-
end
|
269
|
+
duration(options.merge({:billed => true}))
|
266
270
|
end
|
267
271
|
|
268
272
|
# Alias method.
|
269
273
|
def unbilled_duration(options = Hash.new)
|
270
|
-
|
271
|
-
duration(options)
|
272
|
-
else
|
273
|
-
Duration.new(0)
|
274
|
-
end
|
274
|
+
duration(options.merge({:billed => false}))
|
275
275
|
end
|
276
276
|
|
277
277
|
# When begin_datetime is `2017-01-01 01:15`
|
@@ -312,6 +312,11 @@ module TheFox
|
|
312
312
|
Status.new(short_status)
|
313
313
|
end
|
314
314
|
|
315
|
+
# Is the Track running?
|
316
|
+
def running?
|
317
|
+
status.short_status == 'R' # running
|
318
|
+
end
|
319
|
+
|
315
320
|
# Is the Track stopped?
|
316
321
|
def stopped?
|
317
322
|
status.short_status == 'S' # stopped
|
@@ -434,7 +439,7 @@ module TheFox
|
|
434
439
|
end
|
435
440
|
|
436
441
|
if self.duration && self.duration.to_i > 0
|
437
|
-
to_ax << 'Duration: %s' % [self.duration.
|
442
|
+
to_ax << 'Duration: %s' % [self.duration.to_human_s]
|
438
443
|
end
|
439
444
|
|
440
445
|
to_ax << 'Status: %s' % [self.status.colorized]
|
@@ -479,7 +484,7 @@ module TheFox
|
|
479
484
|
end
|
480
485
|
|
481
486
|
if self.duration && self.duration.to_i > 0
|
482
|
-
duration_human = self.duration.
|
487
|
+
duration_human = self.duration.to_human_s
|
483
488
|
to_ax << 'Duration: %s' % [duration_human]
|
484
489
|
|
485
490
|
duration_man_days = self.duration.to_man_days
|
@@ -511,6 +516,12 @@ module TheFox
|
|
511
516
|
|
512
517
|
# Return formatted String.
|
513
518
|
#
|
519
|
+
# Options:
|
520
|
+
#
|
521
|
+
# - `:format`
|
522
|
+
#
|
523
|
+
# Format:
|
524
|
+
#
|
514
525
|
# - `%id` - ID
|
515
526
|
# - `%sid` - Short ID
|
516
527
|
# - `%t` - Title generated from message.
|
@@ -521,7 +532,13 @@ module TheFox
|
|
521
532
|
# - `%edt` - End DateTime
|
522
533
|
# - `%ed` - End Date
|
523
534
|
# - `%et` - End Time
|
524
|
-
|
535
|
+
# - `%ds` - Duration Seconds
|
536
|
+
# - `%dh` - Duration Human Format
|
537
|
+
# - `%bi` - Billed Integer
|
538
|
+
# - `%bh` - Billed Human Format (YES, NO)
|
539
|
+
def formatted(options = Hash.new)
|
540
|
+
format = options.fetch(:format, '')
|
541
|
+
|
525
542
|
formatted_s = format
|
526
543
|
.gsub('%id', self.id)
|
527
544
|
.gsub('%sid', self.short_id)
|
@@ -533,14 +550,29 @@ module TheFox
|
|
533
550
|
.gsub('%edt', self.end_datetime ? self.end_datetime.strftime('%F %H:%M') : '')
|
534
551
|
.gsub('%ed', self.end_datetime ? self.end_datetime.strftime('%F') : '')
|
535
552
|
.gsub('%et', self.end_datetime ? self.end_datetime.strftime('%H:%M') : '')
|
553
|
+
.gsub('%ds', self.duration.to_s)
|
554
|
+
.gsub('%bi', self.is_billed.to_i.to_s)
|
555
|
+
.gsub('%bh', self.is_billed ? 'YES' : 'NO')
|
556
|
+
|
557
|
+
duration_human = self.duration.to_human
|
558
|
+
if duration_human
|
559
|
+
formatted_s.gsub!('%dh', self.duration.to_human)
|
560
|
+
else
|
561
|
+
formatted_s.gsub!('%dh', '')
|
562
|
+
end
|
563
|
+
|
564
|
+
task_formating_options = {
|
565
|
+
:format => formatted_s,
|
566
|
+
:prefix => '%T',
|
567
|
+
}
|
536
568
|
|
537
569
|
if @task
|
538
|
-
formatted_s = @task.formatted(
|
570
|
+
formatted_s = @task.formatted(task_formating_options)
|
539
571
|
else
|
540
572
|
tmp_task = Task.new
|
541
573
|
tmp_task.id = ''
|
542
574
|
|
543
|
-
formatted_s = tmp_task.formatted(
|
575
|
+
formatted_s = tmp_task.formatted(task_formating_options)
|
544
576
|
end
|
545
577
|
|
546
578
|
formatted_s
|
data/lib/timr/timr.rb
CHANGED
@@ -157,7 +157,7 @@ module TheFox
|
|
157
157
|
# Task Path
|
158
158
|
task_file_path = BasicModel.create_path_by_id(@tasks_path, task.id)
|
159
159
|
|
160
|
-
# Save
|
160
|
+
# Save Task to file.
|
161
161
|
task.save_to_file(task_file_path)
|
162
162
|
|
163
163
|
@stack.start(track)
|
@@ -341,7 +341,7 @@ module TheFox
|
|
341
341
|
# Task Path
|
342
342
|
task_file_path = BasicModel.create_path_by_id(@tasks_path, task.id)
|
343
343
|
|
344
|
-
# Save
|
344
|
+
# Save Task to file.
|
345
345
|
task.save_to_file(task_file_path)
|
346
346
|
|
347
347
|
@stack.push(track)
|
@@ -359,6 +359,48 @@ module TheFox
|
|
359
359
|
continue(options)
|
360
360
|
end
|
361
361
|
|
362
|
+
# Remove current running Track.
|
363
|
+
#
|
364
|
+
# Options:
|
365
|
+
#
|
366
|
+
# - `:stack` (Boolean) Reset the Stack.
|
367
|
+
def reset(options = Hash.new)
|
368
|
+
stack_opt = options.fetch(:stack, false)
|
369
|
+
|
370
|
+
track = @stack.current_track
|
371
|
+
if track && track.running?
|
372
|
+
task = track.task
|
373
|
+
if task
|
374
|
+
task.reset
|
375
|
+
end
|
376
|
+
|
377
|
+
track.remove
|
378
|
+
|
379
|
+
# Save Task to file.
|
380
|
+
task.save_to_file
|
381
|
+
|
382
|
+
@stack.remove(track)
|
383
|
+
end
|
384
|
+
|
385
|
+
if stack_opt
|
386
|
+
@stack.tracks.each do |track|
|
387
|
+
task = track.task
|
388
|
+
if task
|
389
|
+
task.reset
|
390
|
+
|
391
|
+
# Save Task to file.
|
392
|
+
task.save_to_file
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
@stack.reset
|
397
|
+
end
|
398
|
+
|
399
|
+
@stack.save_to_file
|
400
|
+
|
401
|
+
nil
|
402
|
+
end
|
403
|
+
|
362
404
|
# Create a new [Task](rdoc-ref:TheFox::Timr::Model::Task) based on the `options` Hash. Will not be started or something else.
|
363
405
|
#
|
364
406
|
# Uses [Task#create_task_from_hash](rdoc-ref:TheFox::Timr::Model::Task::create_task_from_hash) to create a new Task instance and [BasicModel#create_path_by_id](rdoc-ref:TheFox::Timr::Model::BasicModel.create_path_by_id) to create a new file path.
|
@@ -383,7 +425,7 @@ module TheFox
|
|
383
425
|
# Task Path
|
384
426
|
task_file_path = BasicModel.create_path_by_id(@tasks_path, task.id)
|
385
427
|
|
386
|
-
# Save
|
428
|
+
# Save Task to file.
|
387
429
|
task.save_to_file(task_file_path)
|
388
430
|
|
389
431
|
# Leave Stack untouched.
|
data/lib/timr/version.rb
CHANGED
data/man/index.txt
CHANGED
@@ -6,6 +6,7 @@ timr-pause(1) timr-pause.1.ronn
|
|
6
6
|
timr-pop(1) timr-pop.1.ronn
|
7
7
|
timr-push(1) timr-push.1.ronn
|
8
8
|
timr-report(1) timr-report.1.ronn
|
9
|
+
timr-reset(1) timr-reset.1.ronn
|
9
10
|
timr-start(1) timr-start.1.ronn
|
10
11
|
timr-status(1) timr-status.1.ronn
|
11
12
|
timr-stop(1) timr-stop.1.ronn
|