paralines 1.0.0 → 1.1.0
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 +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 [](https://rubygems.org/gems/paralines)
|
2
|
+
|
3
|
+
Nice output to console/file from concurrent threads:
|
4
|
+
|
5
|
+

|
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.
|