paralines 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +21 -0
- data/README.md +126 -0
- data/lib/paralines.rb +32 -23
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed6bff64ad603e59c3cc6a32adf7bbaba2872a69bb7c84bbe4173434bd2165c8
|
4
|
+
data.tar.gz: faffc56b4a7f731fa92057d0e01daefb7f33c2252715df5fd604925a22bf5ec7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 169868a642b113e709e6e1b76b20a829971b46e525020f3ce61ab91bb9d0a50c17583a1818002676a64d3c3594568be31eac91dfdd21d5543fb7a89dc4e756df
|
7
|
+
data.tar.gz: fec478726daccb53dd2ec805ec0784a220e82c85a5ae2abe2c9dd686f31b9820b97186db0d2a59cf0d737b1458c19f8a4bc76587e72434223c76d4c981a77493
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2022 Inversion
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
# ParaLines Ruby Gem [![version](https://badge.fury.io/rb/paralines.svg)](https://rubygems.org/gems/paralines)
|
2
|
+
|
3
|
+
Nice output to console/file from concurrent threads:
|
4
|
+
|
5
|
+
![sample output](sample_output.gif)
|
6
|
+
|
7
|
+
#### Features:
|
8
|
+
- only 170 lines of code;
|
9
|
+
- no dependencies;
|
10
|
+
- works on Linux and Windows;
|
11
|
+
- if output to file and the script crashes in the middle — it is handled with at_exit and in the file, you will find partial output not an empty file.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
gem install paralines
|
16
|
+
|
17
|
+
or in your Gemfile
|
18
|
+
|
19
|
+
gem 'paralines'
|
20
|
+
|
21
|
+
## Sample with all the features (output is on the gif animation)
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'paralines'
|
25
|
+
|
26
|
+
puts '- start -'
|
27
|
+
|
28
|
+
ParaLines.new do |plines|
|
29
|
+
|
30
|
+
odd_line = plines.add_shared_line 'Odd: '
|
31
|
+
even_line = plines.add_shared_line 'Even: '
|
32
|
+
done_order_line = plines.add_shared_line 'Done order: '
|
33
|
+
|
34
|
+
workers = (0..9).map do |n|
|
35
|
+
Thread.new do
|
36
|
+
if n == 0
|
37
|
+
# special case with sub-tasks in sub-threads
|
38
|
+
shared_line = plines.add_shared_line "Worker_#{n}: "
|
39
|
+
(1..3).map do |sn|
|
40
|
+
Thread.new do
|
41
|
+
sleep 0.01
|
42
|
+
ticks_n = 5
|
43
|
+
part = shared_line.part_open "[subtask#{sn}…#{' '*(ticks_n-1)}] "
|
44
|
+
ticks_n.times do |n|
|
45
|
+
sleep rand
|
46
|
+
part.close '.' * (n+1)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end.each &:join
|
50
|
+
next
|
51
|
+
else
|
52
|
+
sleep n>5 ? 0.3 : 0.1 # make Worker_0 to be the first in the list
|
53
|
+
end
|
54
|
+
plines << "Worker_#{n}"
|
55
|
+
start = Time.now
|
56
|
+
n.odd? \
|
57
|
+
? (odd_part = odd_line.part_open "#{n}… ")
|
58
|
+
: (even_part = even_line.part_open "[#{n} ")
|
59
|
+
2.times do
|
60
|
+
sleep rand
|
61
|
+
plines << '.'
|
62
|
+
fail if rand < 0.07 if !:with_fail_chanse # remove ! here to test crashes
|
63
|
+
end
|
64
|
+
time = Time.now - start
|
65
|
+
plines << "done (in %.3fs)" % time
|
66
|
+
done_order_line << n
|
67
|
+
odd_part&.close '+'
|
68
|
+
even_part&.close ']'
|
69
|
+
end
|
70
|
+
.tap do
|
71
|
+
if n==5
|
72
|
+
sleep 0.2
|
73
|
+
plines.add_static_line '- 5 workers added'
|
74
|
+
elsif n==9
|
75
|
+
sleep 0.4
|
76
|
+
plines.add_static_line '- all workers added'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end.each &:join
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
puts '- ready -'
|
84
|
+
|
85
|
+
```
|
86
|
+
|
87
|
+
### Usage without a block
|
88
|
+
```ruby
|
89
|
+
require 'paralines'
|
90
|
+
|
91
|
+
plines = ParaLines.new
|
92
|
+
|
93
|
+
plines.add_static_line 'Gems latest versions'
|
94
|
+
plines.add_empty_line
|
95
|
+
|
96
|
+
gems = %w[sinatra rspec paralines rails hanami]
|
97
|
+
|
98
|
+
plines.add_static_line '- Random order:'
|
99
|
+
threads = gems.map do |name|
|
100
|
+
Thread.new do
|
101
|
+
plines << name.ljust(15, '.')
|
102
|
+
res = `gem list -r #{name} -e`
|
103
|
+
plines << 'v' + res[/\((.+)\)/, 1]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
sleep 0.2
|
107
|
+
plines.add_empty_line
|
108
|
+
plines.add_static_line '- Sorted:'
|
109
|
+
threads += gems.sort.map do |name|
|
110
|
+
sline = plines.add_shared_line name.ljust(15, '.')
|
111
|
+
Thread.new do
|
112
|
+
res = `gem list -r #{name} -e`
|
113
|
+
sline << 'v' + res[/\((.+)\)/, 1]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
threads.each &:join
|
118
|
+
```
|
119
|
+
|
120
|
+
## Contributing
|
121
|
+
|
122
|
+
Bug reports and pull requests are welcome on GitHub: https://github.com/Inversion-des/paralines
|
123
|
+
|
124
|
+
## License
|
125
|
+
|
126
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/lib/paralines.rb
CHANGED
@@ -1,20 +1,10 @@
|
|
1
|
-
# frozen_string_literal: true
|
1
|
+
# *frozen_string_literal: true — should not be used here to ensure unique object_id for ''
|
2
2
|
|
3
3
|
class ParaLines
|
4
|
-
C_mutex = Mutex.new
|
5
|
-
def C_mutex.sync_if_needed
|
6
|
-
if owned?
|
7
|
-
yield
|
8
|
-
else
|
9
|
-
synchronize do
|
10
|
-
yield
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
4
|
|
15
5
|
def initialize
|
16
6
|
set_flags!
|
17
|
-
@line_by_key = Hash.new {|h, key| h[key] = {line:h.length, col:1, text:''} }
|
7
|
+
@line_by_key = Hash.new {|h, key| h[key] = {line:h.length, col:1, text:''.freeze} }
|
18
8
|
|
19
9
|
# *ensure flush at exit
|
20
10
|
if @f_to_file
|
@@ -41,7 +31,7 @@ class ParaLines
|
|
41
31
|
# plines.add_static_line '- 5 workers added'
|
42
32
|
def add_static_line(text)
|
43
33
|
key = text.object_id
|
44
|
-
|
34
|
+
MUTEX.synchronize do
|
45
35
|
d = @line_by_key[key]
|
46
36
|
if @f_to_console
|
47
37
|
puts text
|
@@ -51,6 +41,11 @@ class ParaLines
|
|
51
41
|
end
|
52
42
|
end
|
53
43
|
|
44
|
+
# plines.add_empty_line
|
45
|
+
def add_empty_line
|
46
|
+
add_static_line ''
|
47
|
+
end
|
48
|
+
|
54
49
|
# done_order_line = plines.add_shared_line 'Done order: '
|
55
50
|
# done_order_line << 'some text'
|
56
51
|
# part = shared_line.part_open "#{n}… " + later: part.close '+'
|
@@ -73,9 +68,9 @@ class ParaLines
|
|
73
68
|
d = line_by_key[key]
|
74
69
|
part_col = nil
|
75
70
|
|
76
|
-
|
71
|
+
MUTEX.synchronize do
|
77
72
|
# *we replace placeholder chars like: … or _ or just the last char (order here needed for priority to be able to have _ in text and use … as a placeholder)
|
78
|
-
part_col = d[:col] + (text_.index('…') || text_.index('_') || text_.length-1)
|
73
|
+
part_col = d[:col] + (text_.index('…'.freeze) || text_.index('_'.freeze) || text_.length-1)
|
79
74
|
|
80
75
|
rel.send :output, key, text_
|
81
76
|
end
|
@@ -84,13 +79,15 @@ class ParaLines
|
|
84
79
|
Object.new.tap do |o|
|
85
80
|
o.define_singleton_method :close do |end_text|
|
86
81
|
# *print the closing chars in the saved position
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
82
|
+
MUTEX.synchronize do
|
83
|
+
if f_to_console
|
84
|
+
rel.send :print_in_line,
|
85
|
+
lines_up: line_by_key.count - d[:line],
|
86
|
+
col: part_col,
|
87
|
+
text: end_text
|
88
|
+
else # for file
|
89
|
+
d[:text][part_col-1, end_text.length] = end_text
|
90
|
+
end
|
94
91
|
end
|
95
92
|
end
|
96
93
|
end
|
@@ -118,7 +115,7 @@ class ParaLines
|
|
118
115
|
private \
|
119
116
|
def output(key, text)
|
120
117
|
text = text.to_s
|
121
|
-
|
118
|
+
MUTEX.sync_if_needed do
|
122
119
|
|
123
120
|
# add line
|
124
121
|
puts if @f_to_console && !@line_by_key.has_key?(key)
|
@@ -155,4 +152,16 @@ class ParaLines
|
|
155
152
|
OUT
|
156
153
|
end
|
157
154
|
|
155
|
+
|
156
|
+
MUTEX = Mutex.new
|
157
|
+
def MUTEX.sync_if_needed
|
158
|
+
if owned?
|
159
|
+
yield
|
160
|
+
else
|
161
|
+
synchronize do
|
162
|
+
yield
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
158
167
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paralines
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yura Babak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-01-
|
11
|
+
date: 2022-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -31,6 +31,8 @@ executables: []
|
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
|
+
- LICENSE.txt
|
35
|
+
- README.md
|
34
36
|
- lib/paralines.rb
|
35
37
|
homepage: https://github.com/Inversion-des/paralines
|
36
38
|
licenses:
|
@@ -44,14 +46,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
44
46
|
requirements:
|
45
47
|
- - ">="
|
46
48
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
49
|
+
version: '2.0'
|
48
50
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
51
|
requirements:
|
50
52
|
- - ">="
|
51
53
|
- !ruby/object:Gem::Version
|
52
54
|
version: '0'
|
53
55
|
requirements: []
|
54
|
-
rubygems_version: 3.
|
56
|
+
rubygems_version: 3.3.6
|
55
57
|
signing_key:
|
56
58
|
specification_version: 4
|
57
59
|
summary: Nice output to console/file from concurrent threads.
|