class Montoc::DocBox

Attributes

format[R]
text[R]

Public Class Methods

know(docbox) click to toggle source
# File lib/montoc.rb, line 27
def self.know docbox
        fresh_key = docbox.object_id.to_s(36).to_sym
        @original_text[fresh_key] = docbox.instance_eval {@text}
end
new(text = "") { |self| ... } click to toggle source
# File lib/montoc.rb, line 10
def initialize text = ""
        @text = text
        @format = :virgin
        yield self if block_given?
        DocBox.know self
end
recall(docbox) click to toggle source
# File lib/montoc.rb, line 32
def self.recall docbox
        fresh_key = docbox.object_id.to_s(36).to_sym
        return @original_text[fresh_key]
end

Public Instance Methods

+(string) click to toggle source
# File lib/montoc.rb, line 37
def + string
        @text = squeeze_space
                @text << string.to_s
        @format = :left if @format == :virgin
        method(@format.id2name + "!").call
        return self
end
center() click to toggle source
# File lib/montoc.rb, line 189
def center
        new_text = squeeze_space.split("\n").map do |line|
                line = line.chomp.strip.rjust columns-(columns-line.length)/2
                line = line.ljust columns
        end .join "\n"
        return DocBox.new(new_text)
end
column(col_no = 1) click to toggle source

Find the contents of a specific column of a text. @note Should be used in matricized text, otherwise it could return some

nil even though the column number specified less than the longest line.
The specified number should start from 1 to number of columns. It will 
return nil if it's more than the total number of columns and raise 
ArgumentError if lower than 1.

@param col_no [Fixnum] Specific column number, between 1 and total number

of rows.

@return [String] Return string at specified column of matricized text

# File lib/montoc.rb, line 99
def column col_no = 1
        raise ArgumentError, "Column number cannot be lower than 1." \
        if col_no < 1 
matricize
        if col_no > columns
                return nil
        end
        column_text = ""
        @text.each_line do |line|
                column_text << line.to_s.chomp[col_no-1]
        end
        return column_text
end
columns() click to toggle source

Find the length of the longest line or number of columns in a matricized text. @return [Fixnum] Number of columns in a text

# File lib/montoc.rb, line 86
def columns
        return longest_line.length
        end
justify(left_align_EOP = true) click to toggle source
# File lib/montoc.rb, line 251
def justify left_align_EOP = true
        spacing_priority = {}
        space_weight.each do |line, weights|
                spacing_priority[line] = weights.sort_by do |position, weight|
                        weight
                end .reverse.to_h.map do |position, weight|
                        position
                end
        end
        # Result example:
        #            {0=>[2, 0, 1], 1=>[1, 0], 2=>[0], 3=>[2, 1, 0], 4=>[0]}

        squeezed_text = squeeze_space
        end_of_para = []
        # Get lines that end paragraphs
        squeezed_text.each_line.with_index do |line, line_index|
                if line =~ /^\s*$/ && line_index != 0
                        end_of_para.push(line_index - 1)
                end
        end

        inter_text = ""
        squeezed_text.each_line.with_index do |line, line_index|
                words_arr = line.split
                words_arr_length = words_arr.length < 2 ? 1 : words_arr.length-1
                spaces_arr = (" ,"*words_arr_length).split(",")
                space_needed = columns-line.tr("\n", "").length
                (0...space_needed).each do |i|
                        spaces_arr.length == 0 ? index = i : index = i % spaces_arr.length
                        spaces_arr[spacing_priority[line_index][index]] += " "
                end

                (0...words_arr.length).each do |j|
                        inter_text << words_arr[j]
                        inter_text << spaces_arr[j] unless j == words_arr.length - 1
                end

                inter_text << "\n"
        end

        if left_align_EOP == true
                text_arr = inter_text.split("\n")
                inter_text.each_line.with_index do |line, line_index|
                        if end_of_para.include?(line_index) || line == inter_text.lines[-1]
                                text_arr[line_index] = line.strip.squeeze(" ").ljust(columns)
                        end
                end
                inter_text = text_arr.join("\n")
        end

        new_text = ""
        inter_text.each_line do |line|
                line = line.tr("\n","")
                line = " ".ljust(columns) if line =~ /^\s*$/
                new_text << line + "\n"
        end

        # In case line contains only one word, this will add trailing spaces
        newer_text = ""
        new_text.each_line do |line|
                newer_text << line.strip.ljust(columns) + "\n"
        end
        newer_text.chomp!

        # return new object with new text
        return DocBox.new(newer_text)
end
justify!(left_align_EOP = true) click to toggle source
# File lib/montoc.rb, line 319
def justify! left_align_EOP = true
        @text = justify(left_align_EOP).text
        @format = :justify
        return self
end
left() click to toggle source
# File lib/montoc.rb, line 175
def left
        new_text = squeeze_space.split("\n").map do |line|
                line = line.to_s.ljust columns
        end .join "\n"
        return DocBox.new(new_text)
end
longest_line() click to toggle source

Find the longest lines in text and return the first match. to_s is called from the longest_line to avoid chomp being called from nil, in the case of text = “” @note Should be used when the @format is still in the :virgin state. @return [String] Return the first longest line in text

# File lib/montoc.rb, line 55
def longest_line
        longest_line = squeeze_space.lines.max_by(&:length)
        longest_line = longest_line.to_s.chomp
        return longest_line
end
longest_word() click to toggle source
# File lib/montoc.rb, line 325
def longest_word
        longest_word = squeeze_space.split.max_by(&:length)
        return longest_word
end
matricize(align = :left, column_width = 72) click to toggle source

Make the object plain text into a rectangular (two dimensional

matrix) text by filling the empty spaces with spaces.

@note This will do nothing if the text is already a matrix @param align [Symbol] The alignment or format state, the default

is `:left`

@param columns [Fixnum] Number of columns to which the plain text

converted.

@return [DocBox, nil] The DocBox object after the content/text made

into matrix or nil if the text is already a matrix before this
method called.
# File lib/montoc.rb, line 123
        def matricize align = :left, column_width = 72
        if !matrix?
                reflow! column_width
                method(align.id2name + "!").call
        end
end
matricize!(align = :left, column_width = 72) click to toggle source

Force making/remaking an object text into a matrix no matter it’s already a matrix or not. @param (see matricize) @return [DocBox] The DocBox object after the content/text made into

matrix.
# File lib/montoc.rb, line 135
def matricize! align = :left, column_width = 72
        squeeze_space!
        matricize align, column_width
end
matrix(align = :left, columns = 72) click to toggle source

Make two dimensional array of chars from the current object text @param (see matricize) @return [Array] Return two dimensional array of chars from the

current object text
# File lib/montoc.rb, line 154
def matrix align = :left, columns = 72
        matricize align, columns
        matrix_arr = []
        @text.each_line.with_index do |line, index|
                matrix_arr[index] = line.chomp.split("")
        end
        return matrix_arr
end
matrix?() click to toggle source

Check if the object text is already a matrix. @return [Boolean] Return ‘true` if the text already a matrix and

`false` if not.
# File lib/montoc.rb, line 143
def matrix?
        @text.each_line do |line|
                return false if line.to_s.chomp.length != columns
        end
        return true
end
reflow(column_width = 72) click to toggle source
# File lib/montoc.rb, line 330
def reflow column_width = 72
        raise ArgumentError, "Columns cannot be shorter than the longest word." \
                if columns < longest_word.length
        new_text = ""
        text_arr = @text.split(/\n\s*\n/)
        new_paragraph = []
        text_arr.each do |paragraph|
                para = []
                para_arr = paragraph.split(" ")
                while para_arr.length > 0
                        line_arr = []
                        para_arr.take_while do |word|
                                line_arr.push(word)
                                line_arr.join(" ").length <= column_width
                        end
                        line_arr.pop if line_arr.join(" ").length > column_width
                        len = line_arr.length
                        para_arr.shift(len)
                        line = line_arr.join(" ")
                        para << line + " \n"
                end
                new_paragraph << para.join
        end
        new_text = new_paragraph.join("\n")

        unless @format == :virgin
                new_text = DocBox.new(new_text).method(@format).call.text
        else
                return DocBox.new(new_text).left # default alignment
        end

        return DocBox.new(new_text)
end
reflow!(column_width = 72) click to toggle source
# File lib/montoc.rb, line 364
def reflow! column_width = 72
        obj = reflow(column_width)
        @text = obj.text
        @format = obj.format
        return self
end
right() click to toggle source
# File lib/montoc.rb, line 182
def right
        new_text = squeeze_space.split("\n").map do |line|
                line = line.chomp.strip.rjust columns
        end .join "\n"
        return DocBox.new(new_text)
end
row(row_no = 1) click to toggle source

Find the contents of a specific row or line of a text. @note The specified number should start from 1 to number of rows. It will

return nil if it's more than the total number of rows and raise 
ArgumentError if lower than 1.

@param row_no [Fixnum] Specific row number, between 1 and total number

of rows.

@return [String] Return line at specified row

# File lib/montoc.rb, line 75
def row row_no = 1
        raise ArgumentError, "Row number cannot be lower than 1." \
                if row_no < 1 
        matricize
        row_text = text.lines[row_no-1]
        return row_text
end
rows() click to toggle source

Find the number of lines in a text or the number of rows if you see it as a two dimensional matrix of chars. @return [Fixnum] Number of lines in a text

# File lib/montoc.rb, line 64
def rows
        return @text.lines.length
end
space_weight() click to toggle source
# File lib/montoc.rb, line 212
def space_weight
        # Initialize space position at line 0 as 0
        space_weight = {0=>0}

        i = 0
        squeeze_space.each_line do |line|
                # Initialize weight carried by a space at space position 0 as 0
                weight = {0=>0}

                # Space position index in each line starting from 0
                j = 0
                
                # Capture weight carried by each space in each line
                # Weight means the total number of characters to the left and right
                # of a space.
                line.tr("\n","").split.each_cons(2) do |left_word, right_word|
                        weight[j] = left_word.length + right_word.length if left_word

                        # Move index to next space position
                        j += 1
                end

                # Copy space weight per line to overall space weight hash
                space_weight[i] = weight
                i +=1
        end

        return space_weight
        # Return format:
        #   {line number => {space number => weight, next space number => weight, ...},
        #     next line number => {space number => weight, ...},
        #    ...}
        # Return example:
        #   {0=>{0=>6, 1=>3, 2=>8}, 1=>{0=>4, 1=>8}, 2=>{0=>0}, 3=>{0=>8, 1=>8, 2=>9}}
        # Meaning:
        #   Line 0 has 3 spaces with the first and the last space has weight of 6 and
        #   8, respectively. Line 2 is an empty line.
end
squeeze_space() click to toggle source
# File lib/montoc.rb, line 197
def squeeze_space
        inter_text = @text
        new_text = "".to_s
        # strip extra space between non-space characters
        inter_text.each_line do |line|
                new_text << line.strip.squeeze(" ") + "\n"
        end

        return new_text
end
squeeze_space!() click to toggle source
# File lib/montoc.rb, line 208
def squeeze_space!
        @text = squeeze_space
end
text=(string) click to toggle source
# File lib/montoc.rb, line 45
def text= string
        @text = string
        DocBox.know self
end
to_s() click to toggle source

Override Object#to_s, so that puts or other methods call this method to get the string representation of this object

@return [String] Return @text as the string representation of

DocBox object.
# File lib/montoc.rb, line 22
def to_s
        return @text
end
virgin?() click to toggle source
# File lib/montoc.rb, line 169
def virgin?
        return true if @format == :virgin
        return false
end
virginize() click to toggle source
# File lib/montoc.rb, line 163
def virginize
        @format = :virgin
        @text = DocBox.recall self
        return self
end