Class: String
- Inherits:
-
Object
- Object
- String
- Defined in:
- lib/core_ext/string_wrap.rb
Overview
This is a monkey patch to the String class which is okay in this context since this program is a stand-alone terminal utility. Otherwise we would use a refinement or a namespace to keep this from impact other code.
Instance Method Summary collapse
Instance Method Details
#wrap(line_width: nil, indent: 0) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/core_ext/string_wrap.rb', line 12 def wrap(line_width: nil, indent: 0) # If line_width is not given, try to detect the terminal width line_width ||= IO.console ? IO.console.winsize[1] : 80 # Prepare the prefix based on the type of the indent parameter prefix = indent.is_a?(String) ? indent : ' ' * indent.to_i # Split the string into paragraphs first, preserve paragraph breaks paragraphs = self.split(/\n{2,}/) # Create an empty array that will hold all wrapped paragraphs wrapped_paragraphs = [] # Process each paragraph separately paragraphs.each do |paragraph| wrapped_lines = [] # Create an empty array for wrapped lines of the current paragraph # Split the paragraph into lines first, in case there are single newlines lines = paragraph.split(/(?<=\n)/) # Process each line separately to maintain single newlines lines.each do |line| words = line.split current_line = "" words.each do |word| if word.include?("\n") && !word.strip.empty? # If the word contains a newline, split and process as separate lines parts = word.split(/(?<=\n)/) parts.each_with_index do |part, index| if part == "\n" wrapped_lines << prefix + current_line current_line = "" else current_line << " " unless current_line.empty? or index == 0 current_line << part.strip end end elsif current_line.length + word.length + 1 > line_width - prefix.length wrapped_lines << prefix + current_line.rstrip current_line = word else current_line << " " unless current_line.empty? current_line << word end end # Don't forget to add the last line unless it's empty wrapped_lines << prefix + current_line unless current_line.empty? end # Preserve the paragraph structure by joining the wrapped lines and append to the wrapped_paragraphs array wrapped_paragraphs << wrapped_lines.join("\n") end # Join wrapped paragraphs with double newlines into a single string wrapped_paragraphs.join("\n\n") end |