Module: Philiprehberger::WordWrap
- Defined in:
- lib/philiprehberger/word_wrap.rb,
lib/philiprehberger/word_wrap/version.rb
Constant Summary collapse
- ANSI_PATTERN =
/\e\[[0-9;]*m/- VERSION =
'0.5.0'
Class Method Summary collapse
-
.center(text, width: 80) ⇒ String
Center text within a given width.
-
.columns(texts, widths:, separator: ' ') ⇒ String
Format multiple strings into parallel columns.
-
.fit(text, width:, height:, omission: '...') ⇒ String
Wrap text to width, then truncate to at most height lines.
-
.hanging_indent(text, width, indent:) ⇒ String
Wrap text with a hanging indent where the first line is flush left and subsequent lines are indented.
-
.indent_lines(text, indent, first_indent: nil) ⇒ String
Prepend an indent to every line of
text. -
.paragraphs(text, width, spacing: 1) ⇒ String
Split on double newlines, wrap each paragraph independently, and rejoin with spacing blank lines.
-
.strip_ansi(text) ⇒ String
Remove ANSI escape codes from text, returning the plain visible string.
- .truncate(text, width: 80, omission: '...') ⇒ Object
-
.unwrap(text) ⇒ String
Remove single newlines within paragraphs (rejoin soft-wrapped text) while preserving paragraph boundaries (double newlines).
- .visible_width(text) ⇒ Object
- .wrap(text, width: 80, indent: nil, first_indent: nil, justify: false) ⇒ Object
Class Method Details
.center(text, width: 80) ⇒ String
Center text within a given width
50 51 52 53 54 55 56 |
# File 'lib/philiprehberger/word_wrap.rb', line 50 def center(text, width: 80) text.split("\n").map do |line| vis_width = visible_width(line.strip) padding = [(width - vis_width) / 2, 0].max "#{' ' * padding}#{line.strip}" end.join("\n") end |
.columns(texts, widths:, separator: ' ') ⇒ String
Format multiple strings into parallel columns
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/philiprehberger/word_wrap.rb', line 64 def columns(texts, widths:, separator: ' ') wrapped = texts.each_with_index.map do |text, i| wrap(text, width: widths[i]).split("\n") end max_lines = wrapped.map(&:length).max || 0 (0...max_lines).map do |line_idx| wrapped.each_with_index.map do |col_lines, col_idx| line = col_lines[line_idx] || '' pad_width = widths[col_idx] vis = visible_width(line) line + (' ' * [(pad_width - vis), 0].max) end.join(separator) end.join("\n") end |
.fit(text, width:, height:, omission: '...') ⇒ String
Wrap text to width, then truncate to at most height lines
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/philiprehberger/word_wrap.rb', line 119 def fit(text, width:, height:, omission: '...') wrapped = wrap(text, width: width) lines = wrapped.split("\n") return wrapped if lines.length <= height truncated_lines = lines[0...height] last_line = truncated_lines.last omission_width = visible_width(omission) available = width - omission_width truncated_lines[-1] = if available <= 0 omission[0...width] elsif visible_width(last_line) > available truncate_at_word_boundary(last_line, available) + omission else "#{last_line}#{omission}" end truncated_lines.join("\n") end |
.hanging_indent(text, width, indent:) ⇒ String
Wrap text with a hanging indent where the first line is flush left and subsequent lines are indented
88 89 90 91 |
# File 'lib/philiprehberger/word_wrap.rb', line 88 def hanging_indent(text, width, indent:) indent_str = ' ' * indent wrap(text, width: width, first_indent: '', indent: indent_str) end |
.indent_lines(text, indent, first_indent: nil) ⇒ String
Prepend an indent to every line of text. The first line may use a different indent if first_indent is provided.
Useful when the text is already wrapped (for example, came from another source) and only needs re-indenting. For wrap-and-indent in one step, use wrap. For a hanging-indent first-line outdent, use hanging_indent.
105 106 107 108 109 110 |
# File 'lib/philiprehberger/word_wrap.rb', line 105 def indent_lines(text, indent, first_indent: nil) first_indent ||= indent text.split("\n").each_with_index.map do |line, i| "#{i.zero? ? first_indent : indent}#{line}" end.join("\n") end |
.paragraphs(text, width, spacing: 1) ⇒ String
Split on double newlines, wrap each paragraph independently, and rejoin with spacing blank lines
148 149 150 151 152 153 |
# File 'lib/philiprehberger/word_wrap.rb', line 148 def paragraphs(text, width, spacing: 1) parts = text.split(/\n{2,}/) wrapped_parts = parts.map { |para| wrap(para.strip, width: width) } separator = "\n#{"\n" * spacing}" wrapped_parts.join(separator) end |
.strip_ansi(text) ⇒ String
Remove ANSI escape codes from text, returning the plain visible string.
41 42 43 |
# File 'lib/philiprehberger/word_wrap.rb', line 41 def strip_ansi(text) text.gsub(ANSI_PATTERN, '') end |
.truncate(text, width: 80, omission: '...') ⇒ Object
23 24 25 26 27 28 29 30 31 |
# File 'lib/philiprehberger/word_wrap.rb', line 23 def truncate(text, width: 80, omission: '...') return text if visible_width(text) <= width omission_width = visible_width(omission) available = width - omission_width return omission if available <= 0 truncate_at_word_boundary(text, available) + omission end |
.unwrap(text) ⇒ String
Remove single newlines within paragraphs (rejoin soft-wrapped text) while preserving paragraph boundaries (double newlines)
160 161 162 163 |
# File 'lib/philiprehberger/word_wrap.rb', line 160 def unwrap(text) paragraphs = text.split(/\n{2,}/) paragraphs.map { |para| para.gsub("\n", ' ').squeeze(' ').strip }.join("\n\n") end |
.visible_width(text) ⇒ Object
33 34 35 |
# File 'lib/philiprehberger/word_wrap.rb', line 33 def visible_width(text) text.gsub(ANSI_PATTERN, '').length end |
.wrap(text, width: 80, indent: nil, first_indent: nil, justify: false) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/philiprehberger/word_wrap.rb', line 10 def wrap(text, width: 80, indent: nil, first_indent: nil, justify: false) indent ||= '' first_indent ||= indent paragraphs = text.split("\n") wrapped_paragraphs = paragraphs.map do |paragraph| wrap_paragraph(paragraph, width: width, indent: indent, first_indent: first_indent) end result = wrapped_paragraphs.join("\n") justify ? justify_text(result, width) : result end |