paralines 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +126 -0
  4. data/lib/paralines.rb +32 -23
  5. metadata +6 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 529c8563443dc4d0433a4e969ad894b76ded11e579a8f1781d859bd004e83464
4
- data.tar.gz: 4f96bf28dfcc1726a27fe770f558b82b1ae7d77f4216abf818df34c970043fc0
3
+ metadata.gz: ed6bff64ad603e59c3cc6a32adf7bbaba2872a69bb7c84bbe4173434bd2165c8
4
+ data.tar.gz: faffc56b4a7f731fa92057d0e01daefb7f33c2252715df5fd604925a22bf5ec7
5
5
  SHA512:
6
- metadata.gz: 849db8748f0ffac034e984a3083ff6feab2e238a01b23b8c8ce77059ae804349413870444077d374eab0570e261fcb855b425dd7e94905ff289a9d72affd9527
7
- data.tar.gz: 87cc010c941f8a029ed86f5a8b1945e5ce37cfbb0661cb90052874b74cb81e023ea68eab46ed2ccd4db06e81100c58f03b135ec6b1c0f8d169a3401eaf916f6c
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
- C_mutex.synchronize do
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
- C_mutex.synchronize do
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
- if f_to_console
88
- rel.send :print_in_line,
89
- lines_up: line_by_key.count - d[:line],
90
- col: part_col,
91
- text: end_text
92
- else # for file
93
- d[:text][part_col-1, end_text.length] = end_text
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
- C_mutex.sync_if_needed do
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.0.0
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-27 00:00:00.000000000 Z
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.2.22
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.