Module: Terminal::Text

Defined in:
lib/terminal/text.rb,
lib/terminal/text/formatter.rb,
lib/terminal/text/char_width.rb

Overview

Unicode-aware text processing utilities for display width calculation, word-wrapping, and formatted text output.

All methods correctly handle multi-byte Unicode characters, East Asian wide characters, emoji, combining marks, and ANSI escape codes.

Examples:

Measure display width

Terminal::Text.width('Hello')     # => 5
Terminal::Text.width("\u{1F600}") # => 2  (emoji)

Word-wrap text

Terminal::Text.lines('Hello World, this is a test', width: 12)
# => ["Hello World,", "this is a", "test"]

See Also:

Defined Under Namespace

Classes: Formatter

Constant Summary collapse

UNICODE_VERSION =

supported Unicode Standard version

'17.0.0'

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.ambiguous_char_widthInteger

Display width used for East Asian ambiguous-width characters.

Examples:

Terminal::Text.ambiguous_char_width     # => 1
Terminal::Text.ambiguous_char_width = 2 # for CJK terminals

Returns:

  • (Integer)

    default: +1+



32
33
34
# File 'lib/terminal/text.rb', line 32

def ambiguous_char_width
  @ambiguous_char_width
end

Class Method Details

.each_line(*str, limit: nil, bbcode: true, ansi: true, ignore_newline: false) ⇒ Object Also known as: each

Deprecated.

Use lines and iterate over the result.



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/terminal/text.rb', line 117

def each_line(
  *str,
  limit: nil,
  bbcode: true,
  ansi: true,
  ignore_newline: false,
  &
)
  warn(
    '[DEPRECATED] `each_line` is deprecated – use `.lines.each` instead',
    category: :deprecated,
    uplevel: 1
  )
  lines(
    *str,
    bbcode:,
    ansi:,
    spaces: true,
    eol: !ignore_newline,
    width: limit
  ).each(&)
end

.each_line_with_size(*str, limit: nil, bbcode: true, ansi: true, ignore_newline: false) ⇒ Object Also known as: each_with_size

Deprecated.

Use lines_with_size and iterate over the result.



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/terminal/text.rb', line 150

def each_line_with_size(
  *str,
  limit: nil,
  bbcode: true,
  ansi: true,
  ignore_newline: false,
  &
)
  warn(
    '[DEPRECATED] `each_line_with_size` is deprecated ' \
      '– use `.lines_width_size.each` instead',
    category: :deprecated,
    uplevel: 1
  )

  lines_with_size(
    *str,
    bbcode:,
    ansi:,
    spaces: true,
    eol: !ignore_newline,
    width: limit
  ).each(&)
end

.formatObject

Format text with alignment, padding, and decorations.

Parameters:

  • str (Array<#to_s>)

    text to process

  • ansi (true, false)

    recognize ANSI escape codes

  • bbcode (true, false)

    process BBCode markup

  • spaces (true, false)

    preserve whitespace; when +false+ leading/trailing spaces and multiple spaces are collapsed

  • eol (true, false)

    preserve line endings; when +false+ newlines are treated as spaces

  • align (Symbol, nil)

    text alignment: +:left+, +:right+, +:center+, or +nil+ (no fill)

  • width (Integer, nil)

    output line width in columns

  • height (Integer, nil)

    number of output lines; negative values take lines from the end

  • padding (Integer, Array, nil)

    CSS-style padding

    • 1 value: all sides;
    • 2 values: [vertical, horizontal];
    • 3 values: [top, horizontal, bottom];
    • 4 values: [top, right, bottom, left]
  • prefix (#to_s, nil)

    string prepended to each line

  • suffix (#to_s, nil)

    string appended to each line

Raises:

  • (ArgumentError)

    if +width+ is zero or negative

See Also:



106
# File 'lib/terminal/text.rb', line 106

def format(...) = Formatter.format(...)

.lines(*str, bbcode: true, ansi: true, spaces: true, eol: true, width: nil) ⇒ Array<String>

Split text into lines as strings.

Examples:

Terminal::Text.lines('Hello World', width: 5)
# => ["Hello", "World"]

With BBCode

Terminal::Text.lines('[bold]Hello[/] World', width: 5)
# => ["\e[1mHello\e[m", "World"]

Parameters:

  • str (Array<#to_s>)

    text to process

  • ansi (true, false) (defaults to: true)

    recognize ANSI escape codes

  • bbcode (true, false) (defaults to: true)

    process BBCode markup

  • spaces (true, false) (defaults to: true)

    preserve whitespace; when +false+ leading/trailing spaces and multiple spaces are collapsed

  • eol (true, false) (defaults to: true)

    preserve line endings; when +false+ newlines are treated as spaces

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

    maximum line width in columns

Returns:

  • (Array<String>)

See Also:



88
89
90
91
92
93
94
95
96
97
# File 'lib/terminal/text.rb', line 88

def lines(
  *str,
  bbcode: true,
  ansi: true,
  spaces: true,
  eol: true,
  width: nil
)
  Formatter.new(*str, bbcode:, ansi:, spaces:, eol:).lines(width:)
end

.lines_with_size(*str, bbcode: true, ansi: true, spaces: true, eol: true, width: nil) ⇒ Array<String, Integer>

Split text into lines with their display widths.

Examples:

Terminal::Text.lines_with_size('Hello World', width: 5)
# => [["Hello", 5], ["World", 5]]

Parameters:

  • str (Array<#to_s>)

    text to process

  • ansi (true, false) (defaults to: true)

    recognize ANSI escape codes

  • bbcode (true, false) (defaults to: true)

    process BBCode markup

  • spaces (true, false) (defaults to: true)

    preserve whitespace; when +false+ leading/trailing spaces and multiple spaces are collapsed

  • eol (true, false) (defaults to: true)

    preserve line endings; when +false+ newlines are treated as spaces

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

    maximum line width in columns; +nil+ returns unwrapped lines

Returns:

  • (Array<String, Integer>)

    pairs of +[line_text, display_width]+



61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/terminal/text.rb', line 61

def lines_with_size(
  *str,
  bbcode: true,
  ansi: true,
  spaces: true,
  eol: true,
  width: nil
)
  Formatter.new(*str, bbcode:, ansi:, spaces:, eol:).lines_with_size(
    width:
  )
end

.max_line_width(*str, ansi: true, bbcode: true, spaces: true, eol: true, **opts) ⇒ Integer

Calculate the maximum display width of any line.

Examples:

Terminal::Text.max_line_width("short\na longer line")
# => 13

Parameters:

  • str (Array<#to_s>)

    text to process

  • ansi (true, false) (defaults to: true)

    recognize ANSI escape codes

  • bbcode (true, false) (defaults to: true)

    process BBCode markup

  • spaces (true, false) (defaults to: true)

    preserve whitespace; when +false+ leading/trailing spaces and multiple spaces are collapsed

  • eol (true, false) (defaults to: true)

    preserve line endings; when +false+ newlines are treated as spaces

Returns:

  • (Integer)

    widest line in columns, +0+ when empty



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/terminal/text.rb', line 184

def max_line_width(
  *str,
  ansi: true,
  bbcode: true,
  spaces: true,
  eol: true,
  **opts
)
  # backward compatibility:
  if opts.key?(:ignore_newline)
    eol = opts[:ignore_newline] ? false : true
    warn(
      "Parameter ':ignore_newline' will become obsolete - " \
        "use 'eol: #{eol.inspect}' instead",
      category: :deprecated
    )
  end

  Formatter.new(*str, bbcode:, ansi:, spaces:, eol:).max_line_width
end

.width(str, bbcode: true, spaces: true) ⇒ Integer

Calculate the display width of a string in terminal columns.

Examples:

Terminal::Text.width('Hello')                          # => 5
Terminal::Text.width('[bold]Hi[/bold]')                # => 2
Terminal::Text.width('[bold]Hi[/bold]', bbcode: false) # => 14

Parameters:

  • str (#to_s)

    the string to measure

  • bbcode (true, false) (defaults to: true)

    process BBCode markup

  • spaces (true, false) (defaults to: true)

    preserve whitespace; when +false+ leading/trailing spaces and multiple spaces are collapsed

Returns:

  • (Integer)

    display width in columns



45
46
47
48
49
50
# File 'lib/terminal/text.rb', line 45

def width(str, bbcode: true, spaces: true)
  Formatter
    .new(str, bbcode:, spaces:, ansi: false, eol: false)
    .lines_with_size
    .dig(0, -1) || 0
end