Module: Strings::Align

Defined in:
lib/strings/align.rb

Overview

Responsible for text alignment

Constant Summary collapse

NEWLINE =
"\n".freeze
SPACE =
" ".freeze
LINE_BREAK =
%r{\r\n|\r|\n}.freeze

Class Method Summary collapse

Class Method Details

.align(text, width, direction: :left, **options) ⇒ Object

Aligns text within the width.

If the text is greater than the width then unmodified string is returned.

Examples:

text = "the madness of men"

Strings::Align.align(22, :left)
# => "the madness of men      "

Strings::Align.align(22, :center)
# => "   the madness of men   "

Strings::Align(22, :right)
# => "      the madness of men"

Strings::Align.align(22, :center, fill: '*)
# => "***the madness of men***"

Parameters:

  • text (String)

    the text to align lines of

  • width (Integer)

    the maximum width to align to



39
40
41
42
43
# File 'lib/strings/align.rb', line 39

def align(text, width, direction: :left, **options)
  return text if width.nil?
  method = to_alignment(direction)
  send(method, text, width, options)
end

.align_center(text, width, fill: SPACE, separator: nil) ⇒ String

Centers text within the width

Returns:

  • (String)


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/strings/align.rb', line 85

def align_center(text, width, fill: SPACE, separator: nil)
  return text if width.nil?
  sep = separator || text[LINE_BREAK] || NEWLINE

  each_line(text, sep) do |line|
    width_diff = width - display_width(line)
    if width_diff > 0
      right_count = (width_diff.to_f / 2).ceil
      left_count  =  width_diff - right_count
      [fill * left_count, line, fill * right_count].join
    else
      line
    end
  end
end

.align_left(text, width, fill: SPACE, separator: nil) ⇒ String

Aligns text to the left at given length

Returns:

  • (String)


65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/strings/align.rb', line 65

def align_left(text, width, fill: SPACE, separator: nil)
  return if width.nil?
  sep = separator || text[LINE_BREAK] || NEWLINE

  each_line(text, sep) do |line|
    width_diff = width - display_width(line)
    if width_diff > 0
      line + fill * width_diff
    else
      line
    end
  end
end

.align_right(text, width, fill: SPACE, separator: nil) ⇒ String

Aligns text to the right at given length

Returns:

  • (String)


107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/strings/align.rb', line 107

def align_right(text, width, fill: SPACE, separator: nil)
  return text if width.nil?
  sep = separator || text[LINE_BREAK] || NEWLINE

  each_line(text, sep) do |line|
    width_diff = width - display_width(line)
    if width_diff > 0
      fill * width_diff + line
    else
      line
    end
  end
end

.display_width(string) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Visible width of a string



141
142
143
# File 'lib/strings/align.rb', line 141

def display_width(string)
  Unicode::DisplayWidth.of(Strings::ANSI.sanitize(string))
end

.each_line(text, separator) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Enumerate text line by line

Parameters:

  • text (String)

Returns:

  • (String)


129
130
131
132
133
134
135
# File 'lib/strings/align.rb', line 129

def each_line(text, separator)
  lines = text.split(separator)
  return yield(text) if text.empty?
  lines.reduce([]) do |aligned, line|
    aligned << yield(line)
  end.join(separator)
end

.to_alignment(direction) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Convert direction to method name



49
50
51
52
53
54
55
56
57
# File 'lib/strings/align.rb', line 49

def to_alignment(direction)
  case direction.to_sym
  when :left   then :align_left
  when :right  then :align_right
  when :center then :align_center
  else
    raise ArgumentError, "Unknown alignment `#{direction}`."
  end
end