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.
@@ -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
@@ -45,7 +45,11 @@ module TheFox
45
45
  :units => 2,
46
46
  }
47
47
  h = ChronicDuration.output(@seconds, dur_opt)
48
-
48
+ end
49
+
50
+ # Convert to_human to a String when nil.
51
+ def to_human_s
52
+ h = to_human
49
53
  h ? h : '---'
50
54
  end
51
55
 
@@ -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
 
@@ -82,6 +82,14 @@ module TheFox
82
82
  changed
83
83
  end
84
84
 
85
+ # Remove all Tracks from Stack.
86
+ def reset
87
+ @tracks = Array.new
88
+
89
+ # Mark Stack as changed.
90
+ changed
91
+ end
92
+
85
93
  # Check Track on Stack.
86
94
  def on_stack?(track)
87
95
  unless track.is_a?(Track)
@@ -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.to_human
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.to_human
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.to_human]
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.to_human
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
- def formatted(format, prefix = '%')
946
- format
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}d", self.description ? self.description : '')
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
@@ -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
- if self.is_billed
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
- if !self.is_billed
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.to_human]
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.to_human
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
- def formatted(format)
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(formatted_s, '%T')
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(formatted_s, '%T')
575
+ formatted_s = tmp_task.formatted(task_formating_options)
544
576
  end
545
577
 
546
578
  formatted_s
@@ -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 Track to file.
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 Track to file.
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 Track to file.
428
+ # Save Task to file.
387
429
  task.save_to_file(task_file_path)
388
430
 
389
431
  # Leave Stack untouched.
@@ -2,8 +2,8 @@
2
2
  module TheFox
3
3
  module Timr
4
4
  NAME = 'Timr'
5
- VERSION = '0.5.0'
6
- DATE = '2017-04-16'
5
+ VERSION = '0.6.0'
6
+ DATE = '2017-04-17'
7
7
  HOMEPAGE = 'https://github.com/TheFox/timr'
8
8
 
9
9
  MODEL_DATETIME_FORMAT = '%FT%T%z'
@@ -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