timr 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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