outputhandler 0.1.3beta
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 +7 -0
- data/.gitignore +50 -0
- data/HISTORY +7 -0
- data/LICENSE +29 -0
- data/README.md +49 -0
- data/Rakefile +6 -0
- data/features/01-outputhandler_new.feature +37 -0
- data/features/02-outputhandler_pause.feature +33 -0
- data/features/03-outputhandler_opts.feature +15 -0
- data/features/04-outputhandler_output.feature +31 -0
- data/features/step_definitions/01-outputhandler_new_steps.rb +47 -0
- data/features/step_definitions/02-outputhander_pause.steps.rb +57 -0
- data/features/step_definitions/03-outputhandler_opts_steps.rb +22 -0
- data/features/step_definitions/04-outputhandler_output_steps.rb +37 -0
- data/features/support/env.rb +6 -0
- data/lib/outputhandler.rb +171 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fa2c1260ae74bb1f296417d69cd039fa429029d8a1d5058002045bb68133e4d6
|
4
|
+
data.tar.gz: 75fe96764a08dd4b11be692cbf161953c0975fc775b18dcaba0f3895e55ebeb7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 31978d557201555266b1ee15c48d01664c3c04db51bd521fc61a7a69c51e917bfd82aa2e30a772a0047f44bf7d2882b8b01578db472829a27ce7ed325983561f
|
7
|
+
data.tar.gz: 9b8708f025c23602dcb99f8a5caf7027cc62801b04cbe5a7f42bb277f95914ac0edea0a78884a9ed066915d4dee618d2169a4f9a31b1b282e075452723ddef94
|
data/.gitignore
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
# Gemfile.lock
|
46
|
+
# .ruby-version
|
47
|
+
# .ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
data/HISTORY
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
BSD 3-Clause License
|
2
|
+
|
3
|
+
Copyright (c) 2019, Donkeybridge
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
8
|
+
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
10
|
+
list of conditions and the following disclaimer.
|
11
|
+
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
14
|
+
and/or other materials provided with the distribution.
|
15
|
+
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
17
|
+
contributors may be used to endorse or promote products derived from
|
18
|
+
this software without specific prior written permission.
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# OutputHandler
|
2
|
+
|
3
|
+
A wrapper class for ruby, that allows output to be paused. Output can be send to console, to a logfile or both.
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
An OutputHandler instance provides #print and #puts, behaving like commonly used IO::print and IO::puts,
|
8
|
+
except that these do not accept _\*args_ but only one chunk to be output.
|
9
|
+
And it behaves this way as long as #pause is not triggered. With output being paused, chunks sent to the
|
10
|
+
instance will wait until either #unpause or #flush are triggered.
|
11
|
+
|
12
|
+
At any time, using #print! or #puts! will output directly.
|
13
|
+
|
14
|
+
When using #pause(_limit_), the output is paused for _limit_ seconds (e.g. when printing a help message in a
|
15
|
+
fluent stream).
|
16
|
+
|
17
|
+
\#print(!) and \#puts(!) allow a second argument of type Boolean, that adds a carriage return to the beginning of the chunk (e.g. for displaying a progressbar). Please note, that alike IO::print, you probably want to add whitespace to overwrite the entire previous output.
|
18
|
+
|
19
|
+
OutputHandler.new is the same as OutputHandler.new(console: true, logfile: nil).
|
20
|
+
|
21
|
+
To discard currently queued output, use #flush(_true_).
|
22
|
+
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
gem install outputhandler
|
27
|
+
|
28
|
+
## Usage example:
|
29
|
+
|
30
|
+
user:~/$ irb
|
31
|
+
"Loading irbrc"
|
32
|
+
2.5.1 :001 > require 'outputhandler'
|
33
|
+
2.5.1 :002 > o = OutputHandler.new
|
34
|
+
2.5.1 :003 > o.print "01: Lore ipsum dolor sit amet"
|
35
|
+
01: Lore ipsum dolor sit amet2.5.1 :004 > o.pause
|
36
|
+
2.5.1 :005 > o.puts "02: consectetuer adipiscing elit"
|
37
|
+
2.5.1 :006 > o.puts! "03: Aliquam hendrerit mi posuere lectus"
|
38
|
+
03: Aliquam hendrerit mi posuere lectus
|
39
|
+
2.5.1 :007 > o.flush
|
40
|
+
02: consectetuer adipiscing elit
|
41
|
+
2.5.1 :008 > o.puts "04: Vestibulum enim wisi"
|
42
|
+
2.5.1 :009 > o.puts! "05: viverra nec, fringilla in"
|
43
|
+
05: viverra nec, fringilla in
|
44
|
+
2.5.1 :010 > o.unpause
|
45
|
+
04: Vestibulum enim wisi
|
46
|
+
2.5.1 :011 > o.puts "06: laoreet vitae, risus."
|
47
|
+
06: laoreet vitae, risus.
|
48
|
+
|
49
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
Feature: Initialization
|
2
|
+
|
3
|
+
Scenario: Create a new OutputHandler from scratch without any options
|
4
|
+
Given a new OutputHandler is created without options
|
5
|
+
Then it should return an object of class OutputHandler
|
6
|
+
Then it should have an instance variable "@outputQueue"
|
7
|
+
And "@outputQueue" should be a "Queue"
|
8
|
+
And it should have an instance variable "@console"
|
9
|
+
And "@console" should be a Boolean
|
10
|
+
And it should have an instance variable "@file"
|
11
|
+
And "@file" should be a Boolean
|
12
|
+
And it should have an instance variable "@logfile"
|
13
|
+
And "@logfile" should be nil
|
14
|
+
And it should be not paused?
|
15
|
+
And it should not respond to #foo
|
16
|
+
And #out! should send output with newline to console
|
17
|
+
And #out should send output with newline to console
|
18
|
+
And #out! should send output to console without newline when added parameter false
|
19
|
+
And #out should send output to console without newline when added parameter false
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
Scenario Outline: Checking whether it is responding to methods
|
24
|
+
Given a new OutputHandler is created
|
25
|
+
Then it should respond to "<method>"
|
26
|
+
Examples:
|
27
|
+
| method |
|
28
|
+
| paused? |
|
29
|
+
| pause |
|
30
|
+
| unpause |
|
31
|
+
| out |
|
32
|
+
| out! |
|
33
|
+
| flush |
|
34
|
+
| puts |
|
35
|
+
| puts! |
|
36
|
+
| print |
|
37
|
+
| print! |
|
@@ -0,0 +1,33 @@
|
|
1
|
+
Feature: Pausing and unpausing the Outputhandler
|
2
|
+
|
3
|
+
Scenario: Creating and pausing the outputhandler should send output via #out! but not via #out
|
4
|
+
Given a new instance is created
|
5
|
+
And it is paused
|
6
|
+
Then #out! should send output
|
7
|
+
But #out should not send output
|
8
|
+
|
9
|
+
Scenario: Creating and pausing the outputHandler should not send output via #out, but after unpausing it should
|
10
|
+
|
11
|
+
Given a new instance is created
|
12
|
+
And it is paused
|
13
|
+
Then #out should not send immediate output
|
14
|
+
And #out should send immediate output when unpausing
|
15
|
+
|
16
|
+
Scenario: Creating and pausing the outputHandler for 2 second should not print anything, but after 2 seconds it should
|
17
|
+
|
18
|
+
Given a new instance is created
|
19
|
+
And it is paused for 2 seconds
|
20
|
+
Then #out should not send immediate output
|
21
|
+
But should arrive after 2 seconds
|
22
|
+
|
23
|
+
Scenario: Creating and pausing the outputhandler, output should not be sent immediately, but upon #flush
|
24
|
+
Given a new instance is created
|
25
|
+
And it is paused
|
26
|
+
And output is send to #out
|
27
|
+
And output is send to #out
|
28
|
+
Then it should send immediate upon #flush
|
29
|
+
Given output is send to #out
|
30
|
+
Then it should not send immediate upon silent #flush
|
31
|
+
And #out should not send immediate output when unpausing
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Feature: A new OutputHandler can react to options hash
|
2
|
+
|
3
|
+
Scenario: Only Hash as Parameter is accepted
|
4
|
+
Given a OutputHandler will be created
|
5
|
+
Then with a String as parameter is should raise a TypeError
|
6
|
+
Then with a Hash as parameter it should not raise
|
7
|
+
|
8
|
+
Scenario: Parameter "console: false" disables default console output
|
9
|
+
Given an OutputHandler is created with parameter "console" set to "false"
|
10
|
+
Then #out should not send output
|
11
|
+
|
12
|
+
Scenario: Parameter "logile: filename" enables output to filename
|
13
|
+
Given an OutputHandler is created with parameter "logfile" set to "/tmp/foofile"
|
14
|
+
And output "ramses" is send to #out
|
15
|
+
Then file "/tmp/foofile" should contain output "ramses"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Feature: outputhandler should be aware of CR and NL
|
2
|
+
|
3
|
+
Scenario: #puts and #puts! should send with newline but without CR
|
4
|
+
Given a new instance is created
|
5
|
+
Then output should contain a NL but no CR when sent to "puts"
|
6
|
+
Then output should contain a NL but no CR when sent to "puts!"
|
7
|
+
|
8
|
+
|
9
|
+
Scenario: #puts(true) and #puts!(true) should send with NL but also with CR
|
10
|
+
Given a new instance is created
|
11
|
+
Then output should contain a NL with leading CR when sent to "puts" with param true
|
12
|
+
Then output should contain a NL with leading CR when sent to "puts!" with param true
|
13
|
+
|
14
|
+
|
15
|
+
Scenario: #print and #print! should send without newline
|
16
|
+
Given a new instance is created
|
17
|
+
Then output should contain neither NL nor CR when sent to "print"
|
18
|
+
Then output should contain neither NL nor CR when sent to "print!"
|
19
|
+
|
20
|
+
Scenario: #print(true) and #print!(true) should send without NL but with CR
|
21
|
+
Given a new instance is created
|
22
|
+
Then output should contain a leading CR but no NL when sent to "print" with param true
|
23
|
+
Then output should contain a leading CR but no NL when sent to "print!" with param true
|
24
|
+
|
25
|
+
Scenario: #print(true) overwrite former #print(true)
|
26
|
+
Given an OutputHandler is created with parameter "logfile" set to "/tmp/barfile"
|
27
|
+
And "foo" is sent to the handler with print
|
28
|
+
Then file "/tmp/barfile" should contain output "foo"
|
29
|
+
And "bar" is sent to the handler with print and param true
|
30
|
+
Then file "/tmp/barfile" should contain output "bar"
|
31
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
Given /a new OutputHandler is created/ do
|
2
|
+
require './lib/outputhandler.rb'
|
3
|
+
@output_handler = OutputHandler.new
|
4
|
+
end
|
5
|
+
|
6
|
+
Then "it should return an object of class OutputHandler" do
|
7
|
+
expect(@output_handler).to be_instance_of(OutputHandler)
|
8
|
+
end
|
9
|
+
|
10
|
+
Then /^it should have an instance variable "([^"]*)"$/ do |var|
|
11
|
+
expect(@output_handler.instance_variable_defined?(var.to_sym)).to be true
|
12
|
+
end
|
13
|
+
|
14
|
+
Then /^"([^"]*)" should be a Boolean$/ do |var|
|
15
|
+
expect(@output_handler.instance_variable_get(var.to_sym)).to be_instance_of(TrueClass).or be_instance_of(FalseClass)
|
16
|
+
end
|
17
|
+
|
18
|
+
Then /^"([^"]*)" should be nil$/ do |var|
|
19
|
+
expect(@output_handler.instance_variable_get(var.to_sym)).to be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^"([^"]*)" should be a "([^"]*)"$/ do |var, klass|
|
23
|
+
expect(@output_handler.instance_variable_get(var.to_sym)).to be_instance_of(Object.const_get(klass))
|
24
|
+
end
|
25
|
+
|
26
|
+
Then "it should be not paused?" do
|
27
|
+
expect(@output_handler.paused?).to be false
|
28
|
+
end
|
29
|
+
|
30
|
+
Then "it should not respond to #foo" do
|
31
|
+
expect(@output_handler).not_to respond_to(:foo)
|
32
|
+
end
|
33
|
+
|
34
|
+
Then /^it should respond to "([^"]*)"$/ do |method|
|
35
|
+
expect(@output_handler).to respond_to(method.to_sym)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
Then /^#(out!?) should send output with newline to console$/ do |method|
|
40
|
+
expect{@output_handler.send(method.to_sym,"foo"); sleep 0.25}.to output("foo\n").to_stdout_from_any_process
|
41
|
+
end
|
42
|
+
|
43
|
+
Then /^#(out!?) should send output to console without newline when added parameter false$/ do |method|
|
44
|
+
expect{@output_handler.send(method.to_sym,"foo",false); sleep 0.1}.to output("foo").to_stdout
|
45
|
+
end
|
46
|
+
|
47
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
Given("a new instance is created") do
|
2
|
+
require './lib/outputhandler.rb'
|
3
|
+
@output_handler = OutputHandler.new
|
4
|
+
end
|
5
|
+
|
6
|
+
Given("it is paused") do
|
7
|
+
@output_handler.pause
|
8
|
+
end
|
9
|
+
|
10
|
+
Then("#out! should send output") do
|
11
|
+
expect { @output_handler.out!("foo")}.to output("foo\n").to_stdout
|
12
|
+
end
|
13
|
+
|
14
|
+
Then("#out should not send output") do
|
15
|
+
expect { @output_handler.out("foo")}.not_to output().to_stdout_from_any_process
|
16
|
+
end
|
17
|
+
|
18
|
+
Given("output is send to #out") do
|
19
|
+
@output_handler.out("foo")
|
20
|
+
end
|
21
|
+
|
22
|
+
Given /^output "([^"]*)" is send to #out$/ do |str|
|
23
|
+
@output_handler.out(str)
|
24
|
+
sleep 0.1
|
25
|
+
end
|
26
|
+
|
27
|
+
Then "#out should not send immediate output" do
|
28
|
+
expect { @output_handler.out("foo"); sleep 0.25 }.not_to output.to_stdout_from_any_process
|
29
|
+
end
|
30
|
+
|
31
|
+
Then "#out should send immediate output when unpausing" do
|
32
|
+
expect { @output_handler.unpause; sleep 0.25 }.to output("foo\n").to_stdout_from_any_process
|
33
|
+
end
|
34
|
+
|
35
|
+
Given /^it is paused for (\d+) seconds$/ do |seconds|
|
36
|
+
@output_handler.pause(seconds)
|
37
|
+
end
|
38
|
+
|
39
|
+
Then /^should arrive after (\d+) seconds$/ do |seconds|
|
40
|
+
expect{ sleep seconds; }.to output("foo\n").to_stdout_from_any_process
|
41
|
+
end
|
42
|
+
|
43
|
+
Then "it should send immediate upon #flush" do
|
44
|
+
expect { @output_handler.flush; sleep 0.25 }.to output("foo\nfoo\n").to_stdout_from_any_process
|
45
|
+
end
|
46
|
+
|
47
|
+
Then "it should not send immediate upon silent #flush" do
|
48
|
+
expect { @output_handler.flush(true); sleep 0.25 }.not_to output.to_stdout_from_any_process
|
49
|
+
end
|
50
|
+
|
51
|
+
Then "#out should not send immediate output when unpausing" do
|
52
|
+
expect { @output_handler.unpause; sleep 0.25}.not_to output.to_stdout_from_any_process
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require './lib/outputhandler.rb'
|
2
|
+
|
3
|
+
Given "a OutputHandler will be created" do
|
4
|
+
end
|
5
|
+
|
6
|
+
But "with a String as parameter is should raise a TypeError" do
|
7
|
+
expect { OutputHandler.new("foo")}.to raise_error(TypeError)
|
8
|
+
end
|
9
|
+
|
10
|
+
But "with a Hash as parameter it should not raise" do
|
11
|
+
expect { OutputHandler.new({})}.not_to raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
Given /^an OutputHandler is created with parameter "([^"]*)" set to "([^"]*)"$/ do |param, value|
|
15
|
+
File.open(value, "w"){|f| f.write "" } if param == "logfile"
|
16
|
+
eval "@output_handler = OutputHandler.new(#{param}:\"#{value}\")"
|
17
|
+
end
|
18
|
+
|
19
|
+
Then /^file "([^"]*)" should contain output "([^"]*)"$/ do |filename, str|
|
20
|
+
expect( `cat #{filename} | tail -n1`.split("\r").last.chomp).to eq(str.chomp)
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require './lib/outputhandler.rb'
|
2
|
+
|
3
|
+
Then /^output should contain a NL but no CR when sent to "([^"]*)"$/ do |method|
|
4
|
+
expect { @output_handler.send(method.to_sym, "foo"); sleep 0.25}.
|
5
|
+
to output("foo\n").to_stdout_from_any_process
|
6
|
+
end
|
7
|
+
|
8
|
+
Then /^output should contain a NL with leading CR when sent to "([^"]*)" with param true$/ do |method|
|
9
|
+
expect { @output_handler.send(method.to_sym, "foo", true); sleep 0.25}.
|
10
|
+
to output("\rfoo\n").to_stdout_from_any_process
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^output should contain neither NL nor CR when sent to "([^"]*)"$/ do |method|
|
14
|
+
expect { @output_handler.send(method.to_sym, "foo"); sleep 0.25 }.
|
15
|
+
to output("foo").to_stdout_from_any_process
|
16
|
+
end
|
17
|
+
|
18
|
+
Then /^output should contain a leading CR but no NL when sent to "([^"]*)" with param true$/ do |method|
|
19
|
+
expect { @output_handler.send(method.to_sym, "foo", true); sleep 0.25 }.
|
20
|
+
to output("\rfoo").to_stdout_from_any_process
|
21
|
+
end
|
22
|
+
|
23
|
+
Given "{string} is sent to the handler with print" do |string|
|
24
|
+
puts "sent str is #{string}"
|
25
|
+
@output_handler.print(string)
|
26
|
+
sleep 0.1
|
27
|
+
end
|
28
|
+
|
29
|
+
Given "{string} is sent to the handler with print and param true" do |string|
|
30
|
+
puts "sent string is #{string}"
|
31
|
+
@output_handler.print(string, true)
|
32
|
+
sleep 0.1
|
33
|
+
end
|
34
|
+
|
35
|
+
#Then /^file "([^"]*)" should contain "([^"]*)"$/ do |filename, str|
|
36
|
+
# expect(File.read(filename)).to eq("\r#{str}")
|
37
|
+
#end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
#The main class of this gem
|
2
|
+
class OutputHandler
|
3
|
+
|
4
|
+
# Aliasing puts and print, as they are included / inherited (?) from IO
|
5
|
+
alias_method :superputs, :puts
|
6
|
+
# Aliasing puts and print, as they are included / inherited (?) from IO
|
7
|
+
alias_method :superprint, :print
|
8
|
+
|
9
|
+
# Creates a new instance of OutputHandler. It accepts an options hash.
|
10
|
+
#
|
11
|
+
# @param opts [Hash]
|
12
|
+
# @option opts [Boolean] :console If set to true (default), the handler will output to STDOUT.
|
13
|
+
# @option opts [String] :logfile If set to a target and the target is valid, the handler will output to logfile.
|
14
|
+
#
|
15
|
+
def initialize(opts = {}, *args, &block)
|
16
|
+
raise TypeError unless opts.is_a? Hash
|
17
|
+
@outputQueue = Queue.new
|
18
|
+
@console = opts[:console].nil? ? true : opts[:console]
|
19
|
+
@logfile = opts[:logfile].nil? ? nil : opts[:logfile]
|
20
|
+
@file = @logfile.nil? ? false : true
|
21
|
+
@paused = false
|
22
|
+
@outputMonitor = Monitor.new
|
23
|
+
system("touch #{@logfile}") unless @logfile.nil?
|
24
|
+
self.spawn_output
|
25
|
+
end
|
26
|
+
|
27
|
+
# Convenience method, accepts a second parameter to force carriage return
|
28
|
+
# (while \\r in-line also is accepted)
|
29
|
+
#
|
30
|
+
# @param chunk [printable Object]
|
31
|
+
# @param cr [Boolean] for carriage return
|
32
|
+
def puts(chunk = "", cr = false)
|
33
|
+
self.out(chunk, true, cr)
|
34
|
+
end
|
35
|
+
|
36
|
+
# (see #puts)
|
37
|
+
def puts!(chunk = "", cr = false)
|
38
|
+
self.out!(chunk, true, cr)
|
39
|
+
end
|
40
|
+
|
41
|
+
# (see #puts)
|
42
|
+
def print(chunk = "", cr = false)
|
43
|
+
self.out(chunk, false, cr)
|
44
|
+
end
|
45
|
+
|
46
|
+
# (see #puts)
|
47
|
+
def print!(chunk = "", cr = false)
|
48
|
+
self.out!(chunk, false, cr)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns whether output currently is paused.
|
52
|
+
#
|
53
|
+
# @return [Boolean]
|
54
|
+
def paused?
|
55
|
+
@paused
|
56
|
+
end
|
57
|
+
|
58
|
+
# Pauses the output. If parameter is sent, output will autoresume after delay. Overrides currently
|
59
|
+
# set delay.
|
60
|
+
#
|
61
|
+
# @param limit [Numeric] Time to pause.
|
62
|
+
def pause(limit = 0)
|
63
|
+
unless self.paused?
|
64
|
+
Thread.kill(@outputThread)
|
65
|
+
@paused = true
|
66
|
+
self.spawn_output
|
67
|
+
end
|
68
|
+
if limit > 0
|
69
|
+
Thread.new do
|
70
|
+
sleep limit
|
71
|
+
@paused = false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Unpauses currently paused output regardless of any set delay.
|
77
|
+
def unpause
|
78
|
+
@paused = false
|
79
|
+
end
|
80
|
+
|
81
|
+
# Flushes currently suspended output.
|
82
|
+
#
|
83
|
+
# @param silent [Boolean] If set to true, flushes to /dev/null, else
|
84
|
+
# to configured output(s).
|
85
|
+
def flush(silent = false)
|
86
|
+
while not @outputQueue.empty?
|
87
|
+
el = @outputQueue.pop
|
88
|
+
self.out!(el[:chunk], el[:newline], el[:cr]) unless silent
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Sends next chunk to outputs. Will be queued if #paused, otherwise
|
93
|
+
# sent to output(s).
|
94
|
+
#
|
95
|
+
# @param chunk [printable Object]
|
96
|
+
# @param newline [Boolean] Indicates whether (default) or not to end
|
97
|
+
# line with a newline character.
|
98
|
+
def out(chunk = "", newline = true, cr = false)
|
99
|
+
el = { chunk: chunk, newline: newline, cr: cr}
|
100
|
+
@outputQueue << el
|
101
|
+
end
|
102
|
+
|
103
|
+
# Sends next chunk to output(s) directly, regardless of #paused.
|
104
|
+
#
|
105
|
+
# @param (see #out)
|
106
|
+
def out!(chunk = "", newline = true, cr = false)
|
107
|
+
superprint "#{cr ? "\r" : ""
|
108
|
+
}#{chunk.chomp
|
109
|
+
}#{newline ? "\n" : ""}" if @console
|
110
|
+
File.open(@logfile,'a+'){|f| f.write "#{cr ? "\r" : ""
|
111
|
+
}#{chunk.chomp
|
112
|
+
}#{newline ? "\n" : "" }" } if @file
|
113
|
+
end
|
114
|
+
|
115
|
+
# Spawns output thread
|
116
|
+
# @!visibility private
|
117
|
+
def spawn_output
|
118
|
+
@outputThread = Thread.new do
|
119
|
+
loop do
|
120
|
+
if self.paused?
|
121
|
+
sleep 0.1
|
122
|
+
else
|
123
|
+
o = @outputQueue.pop
|
124
|
+
superprint "#{o[:cr] ? "\r" : ""
|
125
|
+
}#{o[:chunk]
|
126
|
+
}#{o[:newline] ? "\n" : ""}" if @console
|
127
|
+
File.open(@logfile,'a+') do |f|
|
128
|
+
f.write "#{o[:cr] ? "\r" : ""
|
129
|
+
}#{o[:chunk]
|
130
|
+
}#{o[:newline] ? "\n" : "" }"
|
131
|
+
end if @file
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Provides inspection
|
138
|
+
#
|
139
|
+
# @!visibility private
|
140
|
+
def inspect
|
141
|
+
arr = []
|
142
|
+
tmpQueue = Queue.new
|
143
|
+
while not @outputQueue.empty?
|
144
|
+
el = @outputQueue.pop
|
145
|
+
arr << el
|
146
|
+
tmpQueue << el
|
147
|
+
end
|
148
|
+
@outputQueue = tmpQueue
|
149
|
+
return "<#OutputHandler:0x#{self.object_id.to_s(16)}, paused: #{@paused}, queueLength: #{@outputQueue.size}, outputQueue: #{arr.inspect}>"
|
150
|
+
end
|
151
|
+
|
152
|
+
# Spawns a thread that creates some random output
|
153
|
+
#
|
154
|
+
# @!visibility private
|
155
|
+
def random_output
|
156
|
+
if @random_out_thread.nil?
|
157
|
+
@random_out_thread = Thread.new do
|
158
|
+
loop do
|
159
|
+
o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
|
160
|
+
string = (0...50).map { o[rand(o.length)] }.join
|
161
|
+
@outputQueue << { s: string, newline: true }
|
162
|
+
sleep 5
|
163
|
+
end
|
164
|
+
end
|
165
|
+
else
|
166
|
+
Thread.kill @random_out_thread
|
167
|
+
@random_out_thread = nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: outputhandler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3beta
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Benjamin L. Tischendorf
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-04-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: cucumber
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.9'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.9'
|
55
|
+
description: 'Wrapper class that enables asynchronious output (pausing / unpausing) '
|
56
|
+
email: github@jtown.eu
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- ".gitignore"
|
62
|
+
- HISTORY
|
63
|
+
- LICENSE
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- features/01-outputhandler_new.feature
|
67
|
+
- features/02-outputhandler_pause.feature
|
68
|
+
- features/03-outputhandler_opts.feature
|
69
|
+
- features/04-outputhandler_output.feature
|
70
|
+
- features/step_definitions/01-outputhandler_new_steps.rb
|
71
|
+
- features/step_definitions/02-outputhander_pause.steps.rb
|
72
|
+
- features/step_definitions/03-outputhandler_opts_steps.rb
|
73
|
+
- features/step_definitions/04-outputhandler_output_steps.rb
|
74
|
+
- features/support/env.rb
|
75
|
+
- lib/outputhandler.rb
|
76
|
+
homepage: https://github.com/donkeybridge/outputhandler
|
77
|
+
licenses:
|
78
|
+
- BSD-4-Clause
|
79
|
+
metadata: {}
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '2.0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">"
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.3.1
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.7.8
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: Wrapper class that enables asynchronious output (pausing / unpausing)
|
100
|
+
test_files: []
|