Class: TuiTui::DisplayText

Inherits:
Object
  • Object
show all
Defined in:
lib/tui_tui/display_text.rb

Overview

String wrapper for width-aware truncation, centering, and wrapping.

Instance Method Summary collapse

Constructor Details

#initialize(string) ⇒ DisplayText

Returns a new instance of DisplayText.



9
10
11
# File 'lib/tui_tui/display_text.rb', line 9

def initialize(string)
  @string = string.is_a?(DisplayText) ? string.to_s : TextSanitizer.sanitize(string.to_s)
end

Instance Method Details

#center(columns) ⇒ Object



38
39
40
41
42
43
44
# File 'lib/tui_tui/display_text.rb', line 38

def center(columns)
  gap = columns - width
  return self if gap <= 0

  left = gap / 2
  self.class.new((" " * left) + @string + (" " * (gap - left)))
end

#to_sObject



13
# File 'lib/tui_tui/display_text.rb', line 13

def to_s = @string

#truncate(max, marker: "...") ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/tui_tui/display_text.rb', line 19

def truncate(max, marker: "...")
  return self.class.new("") if max <= 0
  return self if width <= max

  marker = self.class.new(marker)
  budget = [max - marker.width, 0].max
  kept = +""
  used = 0
  @string.each_grapheme_cluster do |grapheme|
    grapheme_width = Width.cluster(grapheme)
    break if used + grapheme_width > budget

    kept << grapheme
    used += grapheme_width
  end

  self.class.new(kept + marker.to_s)
end

#widthObject



15
16
17
# File 'lib/tui_tui/display_text.rb', line 15

def width
  @string.each_grapheme_cluster.sum { |grapheme| Width.cluster(grapheme) }
end

#wrap(max, indent: "") ⇒ Object



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
# File 'lib/tui_tui/display_text.rb', line 46

def wrap(max, indent: "")
  return [self] if max <= 0 || width <= max

  indent = self.class.new(indent)
  chunks = []
  current = +""
  current_width = 0
  budget = max
  @string.each_grapheme_cluster do |grapheme|
    grapheme_width = Width.cluster(grapheme)
    if current_width + grapheme_width > budget && !current.empty?
      chunks << current
      current = +""
      current_width = 0
      budget = [max - indent.width, 1].max
    end

    current << grapheme
    current_width += grapheme_width
  end

  chunks << current unless current.empty?
  return [self] if chunks.empty?

  [self.class.new(chunks.first)] + chunks[1..].map { |chunk| self.class.new(indent.to_s + chunk) }
end