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.3.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.
-
.paragraphs(text, width, spacing: 1) ⇒ String
Split on double newlines, wrap each paragraph independently, and rejoin with spacing blank lines.
- .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
42 43 44 45 46 47 48 |
# File 'lib/philiprehberger/word_wrap.rb', line 42 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
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/philiprehberger/word_wrap.rb', line 56 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
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/philiprehberger/word_wrap.rb', line 92 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
80 81 82 83 |
# File 'lib/philiprehberger/word_wrap.rb', line 80 def hanging_indent(text, width, indent:) indent_str = ' ' * indent wrap(text, width: width, first_indent: '', indent: indent_str) end |
.paragraphs(text, width, spacing: 1) ⇒ String
Split on double newlines, wrap each paragraph independently, and rejoin with spacing blank lines
121 122 123 124 125 126 |
# File 'lib/philiprehberger/word_wrap.rb', line 121 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 |
.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)
133 134 135 136 |
# File 'lib/philiprehberger/word_wrap.rb', line 133 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 |