Class: Toys::WrappableString

Inherits:
Object
  • Object
show all
Defined in:
lib/toys/wrappable_string.rb

Overview

A string intended for word-wrapped display.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(string = "") ⇒ WrappableString

Create a wrapped string.

Parameters:

  • string (String, Array<String>) (defaults to: "")

    The string or array of string fragments



13
14
15
# File 'lib/toys/wrappable_string.rb', line 13

def initialize(string = "")
  @fragments = string.is_a?(::Array) ? string.map(&:to_s) : string.to_s.split
end

Instance Attribute Details

#fragmentsArray<String> (readonly)

Returns the string fragments, i.e. the individual "words" for wrapping.

Returns:

  • (Array<String>)


22
23
24
# File 'lib/toys/wrappable_string.rb', line 22

def fragments
  @fragments
end

Class Method Details

.make(obj) ⇒ Toys::WrappableString

Make the given object a WrappableString. If the object is already a WrappableString, return it. Otherwise, treat it as a string or an array of strings and wrap it in a WrappableString.

Parameters:

Returns:



134
135
136
# File 'lib/toys/wrappable_string.rb', line 134

def self.make(obj)
  obj.is_a?(WrappableString) ? obj : WrappableString.new(obj)
end

.make_array(objs) ⇒ Array<Toys::WrappableString>

Make the given object an array of WrappableString.

Parameters:

Returns:



144
145
146
# File 'lib/toys/wrappable_string.rb', line 144

def self.make_array(objs)
  Array(objs).map { |obj| make(obj) }
end

.wrap_lines(strs, width, width2 = nil) ⇒ Array<String>

Wraps an array of lines to the given width.

Parameters:

  • strs (Array<WrappableString>)

    Array of strings to wrap.

  • width (Integer, nil)

    Width in characters, or nil for infinite.

  • width2 (Integer, nil) (defaults to: nil)

    Width in characters for the second and subsequent lines, or nil to use the same as width.

Returns:

  • (Array<String>)

    Wrapped lines



114
115
116
117
118
119
120
121
122
123
# File 'lib/toys/wrappable_string.rb', line 114

def self.wrap_lines(strs, width, width2 = nil)
  result = Array(strs).map do |s|
    s = make(s)
    lines = s.empty? ? [""] : s.wrap(width, width2)
    width = width2 if width2
    lines
  end.flatten
  result = [] if result.all?(&:empty?)
  result
end

Instance Method Details

#+(other) ⇒ WrappableString

Returns a new WrappaableString whose content is the concatenation of this WrappableString with another WrappableString.

Parameters:

Returns:



31
32
33
34
# File 'lib/toys/wrappable_string.rb', line 31

def +(other)
  other = WrappableString.new(other) unless other.is_a?(WrappableString)
  WrappableString.new(fragments + other.fragments)
end

#==(other) ⇒ Boolean Also known as: eql?

Tests two wrappable strings for equality

Parameters:

  • other (Object)

Returns:

  • (Boolean)


58
59
60
61
# File 'lib/toys/wrappable_string.rb', line 58

def ==(other)
  return false unless other.is_a?(WrappableString)
  other.fragments == fragments
end

#empty?Boolean

Returns true if the string is empty (i.e. has no fragments)

Returns:

  • (Boolean)


40
41
42
# File 'lib/toys/wrappable_string.rb', line 40

def empty?
  @fragments.empty?
end

#hashInteger

Returns a hash code for this object

Returns:

  • (Integer)


68
69
70
# File 'lib/toys/wrappable_string.rb', line 68

def hash
  fragments.hash
end

#stringString Also known as: to_s

Returns the string without any wrapping

Returns:

  • (String)


48
49
50
# File 'lib/toys/wrappable_string.rb', line 48

def string
  @fragments.join(" ")
end

#wrap(width, width2 = nil) ⇒ Array<String>

Wraps the string to the given width.

Parameters:

  • width (Integer, nil)

    Width in characters, or nil for infinite.

  • width2 (Integer, nil) (defaults to: nil)

    Width in characters for the second and subsequent lines, or nil to use the same as width.

Returns:

  • (Array<String>)

    Wrapped lines



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/toys/wrappable_string.rb', line 81

def wrap(width, width2 = nil)
  lines = []
  line = ""
  line_len = 0
  fragments.each do |frag|
    frag_len = frag.gsub(/\e\[\d+(;\d+)*m/, "").size
    if line_len.zero?
      line = frag
      line_len = frag_len
    elsif width && line_len + 1 + frag_len > width
      lines << line
      line = frag
      line_len = frag_len
      width = width2 if width2
    else
      line_len += frag_len + 1
      line = "#{line} #{frag}"
    end
  end
  lines << line if line_len.positive?
  lines
end