multi_progress_bar 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +11 -0
- data/Rakefile +27 -0
- data/examples/example.rb +35 -0
- data/examples/loop.rb +40 -0
- data/lib/multi_progress_bar/bar.rb +53 -0
- data/lib/multi_progress_bar/bar_renderer.rb +22 -0
- data/lib/multi_progress_bar/total_bar.rb +32 -0
- data/lib/multi_progress_bar.rb +59 -0
- metadata +63 -0
data/README.rdoc
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
== MultiProgressBar
|
2
|
+
|
3
|
+
Displays multiple progress bars using Ncurses. Useful for displaying the status of multiple test runs, say, distributed across different machines. Which is exactly why I wrote it.
|
4
|
+
|
5
|
+
Uses +ruby-progressbar+ to render the bars.
|
6
|
+
|
7
|
+
== Credits
|
8
|
+
|
9
|
+
* Codes by Peter Jaros.
|
10
|
+
* Thanks to Nick Evans for the inspiration (http://ekenosen.net/nick/devblog/2008/12/better-progress-bar-for-rspec/).
|
11
|
+
* Thanks to Satoru Takabayashi for +ruby-progressbar+ (http://0xcc.net/ruby-progressbar/index.html.en).
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
4
|
+
gemspec.name = "multi_progress_bar"
|
5
|
+
gemspec.summary = "Displays multiple progress bars using Ncurses."
|
6
|
+
gemspec.description = "Displays multiple progress bars using Ncurses. Useful for displaying the status of multiple test runs, say, distributed across different machines. Which is exactly why I wrote it."
|
7
|
+
gemspec.email = "peter.a.jaros@gmail.com"
|
8
|
+
gemspec.homepage = "http://github.com/Peeja/multi_progress_bar/tree/master/"
|
9
|
+
gemspec.authors = ["Peter Jaros"]
|
10
|
+
end
|
11
|
+
rescue LoadError
|
12
|
+
puts "Jeweler not available. For gem tasks, install it with: sudo gem install jeweler"
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
begin
|
17
|
+
require 'hanna/rdoctask'
|
18
|
+
rescue LoadError
|
19
|
+
require 'rake/rdoctask'
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Generate RDoc documentation.'
|
23
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
24
|
+
rdoc.main = "README.rdoc"
|
25
|
+
rdoc.rdoc_dir = 'doc'
|
26
|
+
rdoc.options << '--webcvs=http://github.com/Peeja/multi_progress_bar/tree/master/'
|
27
|
+
end
|
data/examples/example.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)+"/../lib"
|
6
|
+
require 'multi_progress_bar'
|
7
|
+
|
8
|
+
|
9
|
+
begin
|
10
|
+
MultiProgressBar.start
|
11
|
+
|
12
|
+
# Demo.
|
13
|
+
make_machine_bar = lambda { MultiProgressBar::Bar.new("(Waiting...)", 100) }
|
14
|
+
machine_bars = [make_machine_bar[], make_machine_bar[]]
|
15
|
+
total = MultiProgressBar::TotalBar.new("-Total-")
|
16
|
+
|
17
|
+
machine_names = ["bleeker", "montrose"]
|
18
|
+
|
19
|
+
until machine_bars.all? { |bar| bar.current == bar.total }
|
20
|
+
sleep(0.1)
|
21
|
+
|
22
|
+
# Simulate machines becoming available.
|
23
|
+
machine_bars.each do |bar|
|
24
|
+
if bar.title == "(Waiting...)"
|
25
|
+
bar.title = machine_names.pop if rand(10) == 0
|
26
|
+
else
|
27
|
+
bar.inc(rand(10))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
MultiProgressBar.log(rand(2000))
|
32
|
+
end
|
33
|
+
ensure
|
34
|
+
MultiProgressBar.end
|
35
|
+
end
|
data/examples/loop.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# Not actually an example, but a script to run the example every
|
4
|
+
# time a file changes, for testing.
|
5
|
+
#
|
6
|
+
# example/loop example/example.rb
|
7
|
+
|
8
|
+
command = ARGV.shift
|
9
|
+
file_patterns_to_watch = (ARGV.length > 0 ? ARGV : ['**/*.rb'])
|
10
|
+
|
11
|
+
files = {}
|
12
|
+
|
13
|
+
file_patterns_to_watch.each do |arg|
|
14
|
+
Dir[arg].each { |file|
|
15
|
+
files[file] = File.mtime(file)
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
trap('INT') do
|
20
|
+
puts "\nQuitting..."
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
loop do
|
26
|
+
system command
|
27
|
+
|
28
|
+
loop do
|
29
|
+
sleep 0.1
|
30
|
+
|
31
|
+
changed_file, last_changed = files.find { |file, last_changed|
|
32
|
+
File.mtime(file) > last_changed
|
33
|
+
}
|
34
|
+
|
35
|
+
if changed_file
|
36
|
+
files[changed_file] = File.mtime(changed_file)
|
37
|
+
break
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module MultiProgressBar
|
2
|
+
# Represents a progress bar at the bottom of the screen.
|
3
|
+
#
|
4
|
+
# +Bar+ exposes the same interface as +ProgressBar+ from the +progressbar+
|
5
|
+
# gem which backs its display.
|
6
|
+
#
|
7
|
+
# file_progress = MultiProgressBar::Bar.new("file_1", 2596)
|
8
|
+
# file_progress.inc # Increment value by 1.
|
9
|
+
# file_progress.inc(10) # Increment value by 10.
|
10
|
+
# file_progress.set(30) # Set value to 30.
|
11
|
+
#
|
12
|
+
# # Change bar format.
|
13
|
+
# file_progress.format = "%-14s (%s) %3d%% %s"
|
14
|
+
# file_progress.format_arguments = [:title, :stat, :percentage, :bar].
|
15
|
+
#
|
16
|
+
# See the +ruby-progressbar+ gem (http://0xcc.net/ruby-progressbar/index.html.en)
|
17
|
+
# for more details.
|
18
|
+
class Bar < DelegateClass(BarRenderer)
|
19
|
+
# Create a new Bar with a +title+ and a +total+ value.
|
20
|
+
def initialize(title, total)
|
21
|
+
MultiProgressBar.add_bar(self)
|
22
|
+
|
23
|
+
@observers = []
|
24
|
+
|
25
|
+
@renderer = BarRenderer.new(title, total, MultiProgressBar.width) do |rendered_bar|
|
26
|
+
MultiProgressBar.update_bar(self, rendered_bar)
|
27
|
+
end
|
28
|
+
|
29
|
+
super @renderer
|
30
|
+
end
|
31
|
+
|
32
|
+
# Increment the current value of the bar.
|
33
|
+
def inc(step = 1)
|
34
|
+
super
|
35
|
+
notify_observers
|
36
|
+
end
|
37
|
+
|
38
|
+
# Set the current value of the bar absolutely.
|
39
|
+
def set(count)
|
40
|
+
super
|
41
|
+
notify_observers
|
42
|
+
end
|
43
|
+
|
44
|
+
def observe(&b) #:nodoc:
|
45
|
+
@observers << b
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def notify_observers
|
50
|
+
@observers.each { |b| b.call(self) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module MultiProgressBar
|
2
|
+
class BarRenderer < ProgressBar #:nodoc:
|
3
|
+
attr_writer :title
|
4
|
+
|
5
|
+
def initialize(title, total, width, &block)
|
6
|
+
@block = block
|
7
|
+
@buffer = StringIO.new
|
8
|
+
@width = width
|
9
|
+
super(title, total, @buffer)
|
10
|
+
end
|
11
|
+
|
12
|
+
def show
|
13
|
+
super
|
14
|
+
@block.call(@buffer.string)
|
15
|
+
@buffer.string = ""
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_width
|
19
|
+
@width
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MultiProgressBar
|
2
|
+
# Works just like +Bar+, but displays the total of other bars.
|
3
|
+
# TotalBar#inc and TotalBar#set don't work.
|
4
|
+
class TotalBar < Bar
|
5
|
+
# Create a new TotalBar. +bars+ is an array of Bar objects, and defaults to
|
6
|
+
# all existing bars.
|
7
|
+
def initialize(title, bars = MultiProgressBar.bars.dup)
|
8
|
+
@bars = bars
|
9
|
+
|
10
|
+
@bars.each do |bar|
|
11
|
+
bar.observe do
|
12
|
+
update_total
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
total_total = @bars.inject(0) { |sum, bar| sum + bar.total }
|
17
|
+
super title, total_total
|
18
|
+
end
|
19
|
+
|
20
|
+
[:inc, :set].each do |name|
|
21
|
+
define_method(name) do
|
22
|
+
raise NoMethodError, "NoMethodError: private method `#{name}' called for #{self}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def update_total
|
28
|
+
total_current = @bars.inject(0) { |sum, bar| sum + bar.current }
|
29
|
+
@renderer.set(total_current)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'ncurses'
|
2
|
+
require 'progressbar'
|
3
|
+
require 'delegate'
|
4
|
+
require 'abstraction'
|
5
|
+
|
6
|
+
module MultiProgressBar
|
7
|
+
class << self
|
8
|
+
attr_reader :bars
|
9
|
+
|
10
|
+
# Set up the screen. Always call +MultiProgressBar.start+ before using progress bars.
|
11
|
+
def start
|
12
|
+
@bars = [].freeze
|
13
|
+
|
14
|
+
Ncurses.initscr
|
15
|
+
Ncurses.curs_set(0)
|
16
|
+
|
17
|
+
@bars_window = Ncurses::WINDOW.new(1, 0, Ncurses.LINES-1, 0)
|
18
|
+
@log_window = Ncurses::WINDOW.new(Ncurses.LINES-1, 0, 0, 0)
|
19
|
+
@log_window.scrollok(true)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Restore the terminal to normal function. Always call this before exiting.
|
23
|
+
def end
|
24
|
+
Ncurses.endwin
|
25
|
+
puts
|
26
|
+
end
|
27
|
+
|
28
|
+
# Write +text+ to the space above the progress bars.
|
29
|
+
def log(text)
|
30
|
+
@log_window.addstr("#{text}\n")
|
31
|
+
@log_window.refresh
|
32
|
+
end
|
33
|
+
|
34
|
+
def width #:nodoc:
|
35
|
+
@bars_window.getmaxx
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_bar(bar) #:nodoc:
|
39
|
+
@bars += [bar]
|
40
|
+
|
41
|
+
@bars_window.mvwin(Ncurses.LINES-bars.size, @bars_window.getbegx)
|
42
|
+
@bars_window.resize(bars.size, @bars_window.getmaxx)
|
43
|
+
@bars_window.refresh
|
44
|
+
|
45
|
+
@log_window.resize(Ncurses.LINES-bars.size, @log_window.getmaxx)
|
46
|
+
@log_window.refresh
|
47
|
+
end
|
48
|
+
|
49
|
+
def update_bar(bar, rendered_bar) #:nodoc:
|
50
|
+
@bars_window.move(bars.index(bar), 0)
|
51
|
+
@bars_window.addstr(rendered_bar)
|
52
|
+
@bars_window.refresh
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
require 'multi_progress_bar/bar_renderer'
|
58
|
+
require 'multi_progress_bar/bar'
|
59
|
+
require 'multi_progress_bar/total_bar'
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: multi_progress_bar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Peter Jaros
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-15 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Displays multiple progress bars using Ncurses. Useful for displaying the status of multiple test runs, say, distributed across different machines. Which is exactly why I wrote it.
|
17
|
+
email: peter.a.jaros@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- README.rdoc
|
26
|
+
- Rakefile
|
27
|
+
- examples/example.rb
|
28
|
+
- examples/loop.rb
|
29
|
+
- lib/multi_progress_bar.rb
|
30
|
+
- lib/multi_progress_bar/bar.rb
|
31
|
+
- lib/multi_progress_bar/bar_renderer.rb
|
32
|
+
- lib/multi_progress_bar/total_bar.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://github.com/Peeja/multi_progress_bar/tree/master/
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --charset=UTF-8
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
requirements: []
|
55
|
+
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.3.5
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: Displays multiple progress bars using Ncurses.
|
61
|
+
test_files:
|
62
|
+
- examples/example.rb
|
63
|
+
- examples/loop.rb
|