class ParaLines

*frozen_string_literal: true — should not be used here to ensure unique object_id for ”

Constants

MUTEX

Public Class Methods

new() { |self| ... } click to toggle source
# File lib/paralines.rb, line 5
def initialize
        set_flags!
        @line_by_key = Hash.new {|h, key| h[key] = {line:h.length, col:1, text:''.freeze} }

        # *ensure flush at exit
        if @f_to_file
                at_exit do
                        flush
                end
        end

        if block_given?
                begin
                        yield self
                ensure
                        flush
                end
        end
end

Public Instance Methods

<<(text) click to toggle source

plines << “done (#{n})”

# File lib/paralines.rb, line 26
def << (text)
        key = Thread.current
        output key, text
end
add_empty_line() click to toggle source

plines.add_empty_line

# File lib/paralines.rb, line 45
def add_empty_line
        add_static_line ''
end
add_shared_line(text) click to toggle source

done_order_line = plines.add_shared_line ‘Done order: ’ done_order_line << ‘some text’ part = shared_line.part_open “#{n}… ” + later: part.close ‘+’ *can output part progress by adding dots: [LS ] [cloud2… ] –> [LS.…] [cloud2… ] — call .close(‘.’ * done_count) multiple times with increasing number of dots *this line can be used by many threads

# File lib/paralines.rb, line 54
def add_shared_line(text)
        key = text.object_id
        output key, text
        # < helper obj with the << and .part_open methods
        Object.new.tap do |o|
                rel = self
                line_by_key = @line_by_key
                f_to_console = @f_to_console

                o.define_singleton_method :<< do |text|
                        rel.send :output, key, text
                end

                o.define_singleton_method :part_open do |text_|
                        d = line_by_key[key]
                        part_col = nil

                        MUTEX.synchronize do
                                # *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)
                                part_col = d[:col] + (text_.index('…'.freeze) || text_.index('_'.freeze) || text_.length-1)

                                rel.send :output, key, text_
                        end

                        # < helper obj with the .close method
                        Object.new.tap do |o|
                                o.define_singleton_method :close do |end_text|
                                        # *print the closing chars in the saved position
                                        MUTEX.synchronize do
                                                if f_to_console
                                                        rel.send :print_in_line,
                                                                lines_up: line_by_key.count - d[:line],
                                                                col: part_col,
                                                                text: end_text
                                                else  # for file
                                                        d[:text][part_col-1, end_text.length] = end_text
                                                end
                                        end
                                end
                        end
                end
        end
end
add_static_line(text) click to toggle source

plines.add_static_line ‘- 5 workers added’

# File lib/paralines.rb, line 32
def add_static_line(text)
        key = text.object_id
        MUTEX.synchronize do
                d = @line_by_key[key]
                if @f_to_console
                        puts text
                else  # for file
                        d[:text] += text.to_s
                end
        end
end
flush() click to toggle source

plines.flush *needed only when @f_to_file *can be called manually if the block form was not used and all the threads are finished

# File lib/paralines.rb, line 101
def flush
        puts @line_by_key.map {|key, d| d[:text] }  if @f_to_file
        @line_by_key.clear
end

Private Instance Methods

output(key, text) click to toggle source
# File lib/paralines.rb, line 116
def output(key, text)
        text = text.to_s
        MUTEX.sync_if_needed do

                # add line
                puts if @f_to_console && !@line_by_key.has_key?(key)

                d = @line_by_key[key]

                if @f_to_console
                        print_in_line(
                                lines_up: @line_by_key.count - d[:line],
                                col: d[:col],
                                text: text
                        )
                else  # for file
                        d[:text] += text
                end

                d[:col] += text.length
        end
end
print_in_line(lines_up:, col:, text:) click to toggle source
set_flags!() click to toggle source

*needed for rewriting in tests

# File lib/paralines.rb, line 109
def set_flags!
        @f_to_console = $>.tty?
        @f_to_file = !$>.tty?
end