Class: Montoc::DocBox
- Inherits:
-
Object
- Object
- Montoc::DocBox
- Defined in:
- lib/montoc.rb
Instance Attribute Summary collapse
-
#format ⇒ Object
readonly
Returns the value of attribute format.
-
#text ⇒ Object
Returns the value of attribute text.
Class Method Summary collapse
Instance Method Summary collapse
- #+(string) ⇒ Object
- #center ⇒ Object
-
#column(col_no = 1) ⇒ String
Return string at specified column of matricized text.
-
#columns ⇒ Fixnum
Find the length of the longest line or number of columns in a matricized text.
-
#initialize(text = "") {|_self| ... } ⇒ DocBox
constructor
A new instance of DocBox.
- #justify(left_align_EOP = true) ⇒ Object
- #justify!(left_align_EOP = true) ⇒ Object
- #left ⇒ Object
-
#longest_line ⇒ String
Find the longest lines in text and return the first match.
- #longest_word ⇒ Object
-
#matricize(align = :left, column_width = 72) ⇒ DocBox?
Make the object plain text into a rectangular (two dimensional matrix) text by filling the empty spaces with spaces.
-
#matricize!(align = :left, column_width = 72) ⇒ Object
matrix.
-
#matrix(align = :left, columns = 72) ⇒ Array
Make two dimensional array of chars from the current object text.
-
#matrix? ⇒ Boolean
Check if the object text is already a matrix.
- #reflow(column_width = 72) ⇒ Object
- #reflow!(column_width = 72) ⇒ Object
- #right ⇒ Object
-
#row(row_no = 1) ⇒ String
Find the contents of a specific row or line of a text.
-
#rows ⇒ Fixnum
Find the number of lines in a text or the number of rows if you see it as a two dimensional matrix of chars.
- #space_weight ⇒ Object
- #squeeze_space ⇒ Object
- #squeeze_space! ⇒ Object
-
#to_s ⇒ String
Override Object#to_s, so that puts or other methods call this method to get the string representation of this object.
- #virgin? ⇒ Boolean
- #virginize ⇒ Object
Constructor Details
Instance Attribute Details
#format ⇒ Object (readonly)
Returns the value of attribute format.
8 9 10 |
# File 'lib/montoc.rb', line 8 def format @format end |
#text ⇒ Object
Returns the value of attribute text.
8 9 10 |
# File 'lib/montoc.rb', line 8 def text @text end |
Class Method Details
.know(docbox) ⇒ Object
27 28 29 30 |
# 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 |
.recall(docbox) ⇒ Object
32 33 34 35 |
# 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 |
Instance Method Details
#+(string) ⇒ Object
37 38 39 40 41 42 43 |
# 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 ⇒ Object
189 190 191 192 193 194 195 |
# 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) ⇒ String
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.
Return string at specified column of matricized text
99 100 101 102 103 104 105 106 107 108 109 110 111 |
# 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 ⇒ Fixnum
Find the length of the longest line or number of columns in a matricized text.
86 87 88 |
# File 'lib/montoc.rb', line 86 def columns return longest_line.length end |
#justify(left_align_EOP = true) ⇒ Object
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
# 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) ⇒ Object
319 320 321 322 323 |
# File 'lib/montoc.rb', line 319 def justify! left_align_EOP = true @text = justify(left_align_EOP).text @format = :justify return self end |
#left ⇒ Object
175 176 177 178 179 180 |
# 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 ⇒ String
Should be used when the @format is still in the :virgin state.
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 = “”
55 56 57 58 59 |
# 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 ⇒ Object
325 326 327 328 |
# 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) ⇒ DocBox?
This will do nothing if the text is already a matrix
Make the object plain text into a rectangular (two dimensional matrix) text by filling the empty spaces with spaces.
123 124 125 126 127 128 |
# 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) ⇒ Object
matrix.
135 136 137 138 |
# 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) ⇒ Array
Make two dimensional array of chars from the current object text
154 155 156 157 158 159 160 161 |
# 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? ⇒ Boolean
Check if the object text is already a matrix.
143 144 145 146 147 148 |
# 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) ⇒ Object
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# 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) ⇒ Object
364 365 366 367 368 369 |
# 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 ⇒ Object
182 183 184 185 186 187 |
# 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) ⇒ String
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.
Find the contents of a specific row or line of a text.
75 76 77 78 79 80 81 |
# 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 ⇒ Fixnum
Find the number of lines in a text or the number of rows if you see it as a two dimensional matrix of chars.
64 65 66 |
# File 'lib/montoc.rb', line 64 def rows return @text.lines.length end |
#space_weight ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# 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 ⇒ Object
197 198 199 200 201 202 203 204 205 206 |
# 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! ⇒ Object
208 209 210 |
# File 'lib/montoc.rb', line 208 def squeeze_space! @text = squeeze_space end |
#to_s ⇒ String
Override Object#to_s, so that puts or other methods call this method to get the string representation of this object
22 23 24 |
# File 'lib/montoc.rb', line 22 def to_s return @text end |
#virgin? ⇒ Boolean
169 170 171 172 |
# File 'lib/montoc.rb', line 169 def virgin? return true if @format == :virgin return false end |