interactive-logger 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 72a04135369c640aab4c63048eafb80e669ed895
4
- data.tar.gz: 8b983336a11ced1edbd6ff4624505c90e3801c32
3
+ metadata.gz: 0c5636a0534a2b4c303e9b6b3f83cdb0e1791dc6
4
+ data.tar.gz: f11583fe28d1b0757f8a73edeb82d52d0d8b8bf6
5
5
  SHA512:
6
- metadata.gz: 87f61383fff19a07ec26acaa805b3f05cfc10c283bdc9d68fdd85710f7c6a08b3760d0106724c280cdb423eeb0d36cbccece45ce759403f3b89df030f4a1ec4e
7
- data.tar.gz: 60fa6e6384f7d20ee5dde568723b90cb5a3102aaa5a942dc094ac0c7505ef736956ee4562db33eccc8e80e925cf677546aa3b6612cff170184c2809c9157625c
6
+ metadata.gz: 3156898ce2975d594b9799bcfe0abef48d68db309e7cc2b07345e61306c97994314e890ecb3ad72dcc447ef0e1df499525cf9ca21efc3b5e0e6730389ac5cc33
7
+ data.tar.gz: 4136d190ac320d7e5f9d60100d1ad84a9783fba4c7c053fcc5ba6c43499533e538c6e7ef8c54db4114b6de45079195e4de7451f45dc19c156943e6ed0b9c4a57
@@ -1,62 +1,99 @@
1
1
  # coding: utf-8
2
2
  require 'colorize'
3
3
  require 'ruby-duration'
4
+ require 'thread'
4
5
 
5
6
  # A logger that shows activity for each step without spamming to stdout.
6
7
  class InteractiveLogger
7
- class Step
8
- PROGRESS_SYMBOLS = %w(- \\ | /)
9
- FAILURE_SYMBOL = '✗'.red
10
- SUCCESS_SYMBOL = '✓'.green
11
- LB = '['.light_black
12
- RB = ']'.light_black
13
-
14
- def initialize(str, show_time: true)
15
- @orig_str = str
16
- @start = Time.now
17
- @show_time = show_time
18
- @pos = 0
19
- print_msg(in_progress_prefix << str)
20
- end
8
+ require_relative 'interactive_logger/step'
9
+ require_relative 'interactive_logger/threaded_step_interface'
21
10
 
22
- def continue(str = nil)
23
- @pos += 1
24
- print_msg("\r" << in_progress_prefix << (str || @orig_str))
25
- end
11
+ def initialize(debug: false)
12
+ @debug = debug
13
+ @current_step = nil
14
+ end
26
15
 
27
- def failure(str = nil)
28
- print_msg("\r" << prefix(FAILURE_SYMBOL) << (str || @orig_str))
29
- end
16
+ def debug?; @debug == true end
30
17
 
31
- def success(str = nil)
32
- print_msg("\r" << prefix(SUCCESS_SYMBOL) << (str || @orig_str))
33
- end
18
+ # Start a step.
19
+ def start(str)
20
+ @current_step = Step.new(str)
21
+ yield @current_step
22
+ print "\n"
23
+ rescue => e
24
+ @current_step.failure "Error while performing step: #{str}\n #{e.class}: #{e.message}"
25
+ print "\n"
26
+ raise
27
+ ensure
28
+ @current_step = nil
29
+ end
34
30
 
35
- private
31
+ # Use a threaded interface, to keep the UI updated even on a long-running
32
+ # process.
33
+ def start_threaded(str)
34
+ @current_step = Step.new(str)
35
+ queue = Queue.new
36
36
 
37
- def in_progress_prefix
38
- prefix(PROGRESS_SYMBOLS[@pos % PROGRESS_SYMBOLS.size].yellow)
37
+ Thread.abort_on_exception = true
38
+ child = Thread.new do
39
+ yield ThreadedStepInterface.new(queue)
39
40
  end
40
41
 
41
- def prefix(str)
42
- show_time = ''
43
- if @show_time
44
- show_time = Duration.new(Time.now.to_i - @start.to_i)
45
- .format(" #{LB} %tmm %ss #{RB}")
42
+ loop do
43
+ if queue.empty?
44
+ @current_step.continue # Keep the UI updating regardless of actual process.
45
+ else
46
+ until queue.empty?
47
+ msg = queue.pop
48
+ @current_step.send(msg.shift, *msg)
49
+ end
46
50
  end
47
- "#{LB} #{str} #{RB}#{show_time} "
48
- end
49
51
 
50
- def print_msg(str)
51
- @max_str = [str.uncolorize.size, @max_str || 0].max
52
- str << ' ' * (@max_str - str.uncolorize.size)
53
- print str
52
+ break unless child.alive?
53
+ sleep 0.5
54
54
  end
55
+
56
+ puts
57
+ child.join
58
+
59
+ @current_step.nil?
60
+ rescue => e
61
+ @current_step.failure "Error while performing step: #{str}\n #{e.class}: #{e.message}"
62
+ print "\n"
63
+ raise
64
+ ensure
65
+ @current_step = nil
55
66
  end
56
67
 
57
- # Start a step.
58
- def start(str)
59
- yield Step.new(str)
68
+ # Post a debug message above the current step output, if debugging is enabled.
69
+ def debug(str)
70
+ return unless debug?
71
+
72
+ @current_step.blank if @current_step
73
+ print '--> '.yellow
74
+ puts str
75
+ @current_step.repaint if @current_step
76
+ end
77
+ # Post an informative message above the current step output.
78
+ def info(str)
79
+ @current_step.blank if @current_step
80
+ print '--> '.green
81
+ puts str
82
+ @current_step.repaint if @current_step
83
+ end
84
+
85
+ # Post an error message above the current step output.
86
+ def error(str)
87
+ @current_step.blank if @current_step
88
+ print '--> '.red
89
+ puts str
90
+ @current_step.repaint if @current_step
91
+ end
92
+
93
+ # Post a single message, without any progress tracking.
94
+ def msg(str)
95
+ c = Step.new(str)
96
+ c.success
60
97
  print "\n"
61
98
  end
62
99
  end
@@ -0,0 +1,68 @@
1
+ # coding: utf-8
2
+ class InteractiveLogger
3
+ class Step
4
+ PROGRESS_SYMBOLS = %w(- \\ | /)
5
+ FAILURE_SYMBOL = '✗'.red
6
+ SUCCESS_SYMBOL = '✓'.green
7
+ LB = '['.light_black
8
+ RB = ']'.light_black
9
+
10
+ def initialize(str, show_time: true)
11
+ @last_str = str
12
+ @start = Time.now
13
+ @show_time = show_time
14
+ @pos = 0
15
+ print_msg(in_progress_prefix << str)
16
+ end
17
+
18
+ def continue(str = nil)
19
+ @pos += 1
20
+ @last_str = str if str
21
+ print_msg(in_progress_prefix << @last_str)
22
+ end
23
+
24
+ def failure(str = nil)
25
+ @last_str = str if str
26
+ print_msg(prefix(FAILURE_SYMBOL) << @last_str)
27
+ end
28
+
29
+ def success(str = nil)
30
+ @last_str = str if str
31
+ print_msg(prefix(SUCCESS_SYMBOL) << @last_str)
32
+ end
33
+
34
+ # Blank out the current line.
35
+ def blank
36
+ print "\r"
37
+ if @last_print_msg
38
+ print ' ' * @last_print_msg.uncolorize.size
39
+ end
40
+ print "\r"
41
+ end
42
+
43
+ def repaint
44
+ print @last_print_msg
45
+ end
46
+
47
+ private
48
+
49
+ def in_progress_prefix
50
+ prefix(PROGRESS_SYMBOLS[@pos % PROGRESS_SYMBOLS.size].yellow)
51
+ end
52
+
53
+ def prefix(str)
54
+ show_time = ''
55
+ if @show_time
56
+ show_time = Duration.new(Time.now.to_i - @start.to_i)
57
+ .format(" #{LB} %tmm %ss #{RB}")
58
+ end
59
+ "#{LB} #{str} #{RB}#{show_time} "
60
+ end
61
+
62
+ def print_msg(str)
63
+ blank
64
+ @last_print_msg = str
65
+ print str
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,23 @@
1
+ require 'thread'
2
+
3
+ class InteractiveLogger
4
+ # A interface-match for Step, but used simply to communicate with the main
5
+ # thread, which actually manipulates the Step.
6
+ class ThreadedStepInterface
7
+ def initialize(queue)
8
+ @queue = queue
9
+ end
10
+
11
+ def continue(str = nil)
12
+ @queue.push([:continue, str])
13
+ end
14
+
15
+ def failure(str = nil)
16
+ @queue.push([:failure, str])
17
+ end
18
+
19
+ def success(str = nil)
20
+ @queue.push([:success, str])
21
+ end
22
+ end
23
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interactive-logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Smith <askreet@gmail.com>
@@ -51,6 +51,8 @@ extensions: []
51
51
  extra_rdoc_files: []
52
52
  files:
53
53
  - lib/interactive-logger.rb
54
+ - lib/interactive_logger/step.rb
55
+ - lib/interactive_logger/threaded_step_interface.rb
54
56
  homepage: https://github.com/askreet/interactive-logger
55
57
  licenses:
56
58
  - MIT