terminal_rb 1.0.6 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,15 +9,15 @@ module Terminal
9
9
  # @see Terminal::Text
10
10
  #
11
11
  # @example Basic word-wrapping
12
- # fmt = Terminal::Text::Formatter.new('Hello World, this is a test')
13
- # fmt.lines(width: 12)
12
+ # formatter = Terminal::Text::Formatter.new('Hello World, this is a test')
13
+ # formatter.lines(width: 12)
14
14
  # # => ["Hello World,", "this is a", "test"]
15
15
  #
16
16
  # @example Formatted output with alignment
17
17
  # Terminal::Text::Formatter.format(
18
18
  # 'Hello', align: :center, width: 20
19
19
  # )
20
- # # => [" Hello "]
20
+ # # => ["       Hello        "]
21
21
  class Formatter
22
22
  # Parse text into lines, optionally with display widths.
23
23
  #
@@ -55,7 +55,7 @@ module Terminal
55
55
  #
56
56
  # @param (see #initialize)
57
57
  # @param (see #format)
58
- # @result (see #format)
58
+ # @return (see #format)
59
59
  # @raise (see #format)
60
60
  def self.format(
61
61
  *str,
@@ -80,6 +80,31 @@ module Terminal
80
80
  )
81
81
  end
82
82
 
83
+ # Format text with alignment.
84
+ #
85
+ # @see #fmt
86
+ #
87
+ # @example
88
+ # Terminal::Text::Formatter.fmt('Hi', align: :center, width: 10)
89
+ # # => ["    Hi    "]
90
+ #
91
+ # @param (see #initialize)
92
+ # @param (see #fmt)
93
+ # @return (see #fmt)
94
+ # @raise (see #fmt)
95
+ def self.fmt(
96
+ *str,
97
+ ansi: true,
98
+ bbcode: true,
99
+ spaces: true,
100
+ eol: true,
101
+ align: nil,
102
+ width: nil,
103
+ height: nil
104
+ )
105
+ new(*str, ansi:, bbcode:, spaces:, eol:).fmt(align:, width:, height:)
106
+ end
107
+
83
108
  # Create a new formatter with given text and options.
84
109
  #
85
110
  # @param str [Array<#to_s>] text to process
@@ -108,8 +133,8 @@ module Terminal
108
133
  # Word-wrap and return lines with their display widths.
109
134
  #
110
135
  # @example
111
- # fmt = Terminal::Text::Formatter.new('Hello World')
112
- # fmt.lines_with_size(width: 5)
136
+ # formatter = Terminal::Text::Formatter.new('Hello World')
137
+ # formatter.lines_with_size(width: 5)
113
138
  # # => [["Hello", 5], ["World", 5]]
114
139
  #
115
140
  # @param width [#to_i, nil] maximum line width in columns;
@@ -127,8 +152,8 @@ module Terminal
127
152
  # Word-wrap and return lines as strings.
128
153
  #
129
154
  # @example
130
- # fmt = Terminal::Text::Formatter.new('Hello World')
131
- # fmt.lines(width: 5)
155
+ # formatter = Terminal::Text::Formatter.new('Hello World')
156
+ # formatter.lines(width: 5)
132
157
  # # => ["Hello", "World"]
133
158
  #
134
159
  # @param width [#to_i, nil] maximum line width in columns
@@ -138,16 +163,22 @@ module Terminal
138
163
 
139
164
  # Format lines with alignment, padding, and decorations.
140
165
  #
141
- # @example Centered text with padding
142
- # fmt = Terminal::Text::Formatter.new('Hi')
143
- # fmt.format(align: :center, width: 10, padding: [0, 1])
144
- # # => [" Hi "]
166
+ # @see #fmt
167
+ #
168
+ # @example Prefix each line
169
+ # formatter = Terminal::Text::Formatter.new("Hello\nWorld")
170
+ # formatter.format(prefix: '> ')
171
+ # # => ["> Hello", "> World"]
172
+ # @example Framed box with padding
173
+ # formatter = Terminal::Text::Formatter.new('Hi')
174
+ # formatter.format(width: 6, padding: [1, 2], prefix: '|', suffix: '|')
175
+ # # => ["|      |", "|  Hi  |", "|      |"]
145
176
  #
146
177
  # @param align [Symbol, nil] text alignment:
147
178
  # `:left`, `:right`, `:center`, or `nil` (no fill)
148
179
  # @param width [#to_i, nil] output line width in columns
149
180
  # @param height [#to_i, nil] number of output lines;
150
- # negative values take lines from the end
181
+ # negative values take lines from the end; `0` returns `[""]`
151
182
  # @param padding [#to_i, Array, nil] CSS-style padding
152
183
  # - 1 value: all sides;
153
184
  # - 2 values: [vertical, horizontal];
@@ -165,6 +196,10 @@ module Terminal
165
196
  prefix: nil,
166
197
  suffix: nil
167
198
  )
199
+ if padding.nil? && prefix.nil? && suffix.nil?
200
+ return fmt(align:, width:, height:)
201
+ end
202
+
168
203
  top, right, bottom, left = _padding(padding)
169
204
 
170
205
  if height
@@ -200,11 +235,9 @@ module Terminal
200
235
  left = left < 1 ? prefix.to_s : "#{prefix}#{space[left]}"
201
236
  right = right < 1 ? suffix.to_s : "#{space[right]}#{suffix}"
202
237
 
203
- # TODO: styling
204
-
205
238
  case align
206
- when :left
207
- lws.each { |l, s| ret << "#{left}#{l}#{space[w - s]}#{right}" }
239
+ when nil, false
240
+ lws.each { |l, _| ret << "#{left}#{l}#{right}" }
208
241
  when :right
209
242
  lws.each { |l, s| ret << "#{left}#{space[w - s]}#{l}#{right}" }
210
243
  when :center
@@ -214,13 +247,58 @@ module Terminal
214
247
  ret << "#{left}#{space[s - rs]}#{l}#{space[rs]}#{right}"
215
248
  end
216
249
  else
217
- lws.each { |l, _| ret << "#{left}#{l}#{right}" }
250
+ lws.each { |l, s| ret << "#{left}#{l}#{space[w - s]}#{right}" }
218
251
  end
219
252
 
220
253
  return ret.fill(empty, ret.size, bottom) if bottom > 0
221
254
  ret.empty? ? ret << '' : ret
222
255
  end
223
256
 
257
+ # Format lines with alignment.
258
+ #
259
+ # Like {#format} without padding, prefix, and suffix.
260
+ #
261
+ # @see #format
262
+ #
263
+ # @example
264
+ # Terminal::Text::Formatter.new('Hi').fmt(align: :right, width: 6)
265
+ # # => ["    Hi"]
266
+ #
267
+ # @param align (see #format)
268
+ # @param width (see #format)
269
+ # @param height (see #format)
270
+ # @return (see #format)
271
+ # @raise (see #format)
272
+ def fmt(width: nil, height: nil, align: nil)
273
+ if height
274
+ return [] if (height = height.to_i) == 0
275
+ height = -height if (tail = (height < 0))
276
+ end
277
+
278
+ lines =
279
+ if width
280
+ w = (width = width.to_i)
281
+ raise(ArgumentError, "invalid width - #{width.inspect}") if w < 1
282
+ _limited(w)
283
+ else
284
+ @unlimited || _unlimited
285
+ end
286
+
287
+ return [+''] if lines.empty?
288
+
289
+ lines = tail ? lines.last(height) : lines.take(height) if height
290
+ w ||= lines.max_by(&:last)[-1] # unless width
291
+
292
+ return lines.map(&:first) unless align
293
+ space = SPACE_CACHE.dup
294
+ return lines.map { |l, s| "#{space[w - s]}#{l}" } if align == :right
295
+ return lines.map { |l, s| "#{l}#{space[w - s]}" } if align != :center
296
+ lines.map do |l, s|
297
+ rs = ((s = w - s) / 2.0).round
298
+ rs < 1 ? l : "#{space[s - rs]}#{l}#{space[rs]}"
299
+ end
300
+ end
301
+
224
302
  # Whether the formatter has any content.
225
303
  #
226
304
  # @return [true, false]
@@ -229,8 +307,8 @@ module Terminal
229
307
  # Maximum display width of any line.
230
308
  #
231
309
  # @example
232
- # fmt = Terminal::Text::Formatter.new("short\na longer line")
233
- # fmt.max_line_width # => 13
310
+ # formatter = Terminal::Text::Formatter.new("short\na longer line")
311
+ # formatter.max_line_width # => 13
234
312
  #
235
313
  # @return [Integer] widest line in columns, `0` when empty
236
314
  def max_line_width
@@ -352,9 +430,7 @@ module Terminal
352
430
  next if current.is_a?(Space) # ignore trailing space
353
431
 
354
432
  # handle Word...
355
- splitted = current.split(width)
356
- last = splitted.pop
357
-
433
+ *splitted, last = current.split(width)
358
434
  if csi.empty?
359
435
  splitted.each { ret << [it.to_str, it.size] }
360
436
  else
@@ -368,7 +444,10 @@ module Terminal
368
444
  size = last.size
369
445
  end
370
446
 
371
- ret.pop if ret[-1] == ['', 0]
447
+ if ret.size > 1
448
+ str, width = ret[-1]
449
+ ret.pop if width == 0 && str.empty?
450
+ end
372
451
  ret
373
452
  end
374
453
 
@@ -392,18 +471,41 @@ module Terminal
392
471
 
393
472
  line.encode!(ENCODING) if line.encoding != ENCODING
394
473
 
395
- line.scan(SCAN_REGEX) do |newline, space, _, _, char|
396
- if char
397
- (last = @lex[-1]).is_a?(Word) and next last.add(char)
398
- next @lex << Word.new(char)
474
+ line.scan(SCAN_REGEX) do |token|
475
+ b = token.getbyte(0)
476
+
477
+ if b > 0x20 # word chunk: an ASCII run or a single grapheme
478
+ # a single-byte token is printable ASCII: one character, one
479
+ # column - no need to ask for its width
480
+ size = token.bytesize
481
+ if size == 1
482
+ (last = @lex[-1]).is_a?(Word) and next last.add(token, 1)
483
+ next @lex << Word.new(token, 1)
484
+ end
485
+ # an ASCII run is the only multi-byte token which cannot be a
486
+ # grapheme cluster - there its width is simply its byte count
487
+ size = nil unless b < 0x80 && token.ascii_only?
488
+ if (last = @lex[-1]).is_a?(Word)
489
+ next size ? last.add(token, size, true) : last.add(token)
490
+ end
491
+ next @lex << Word.new(token, size, true) if size
492
+ next @lex << Word.new(token)
399
493
  end
400
494
 
401
- if space
402
- (last = @lex[-1]).is_a?(Space) and next last.inc
403
- next @lex << Space.new
495
+ if SPACE_BYTE[b] && !(b == 0x0d && token.bytesize == 2)
496
+ size = token.bytesize
497
+ (last = @lex[-1]).is_a?(Space) and next last.size += size
498
+ next @lex << Space.new(size)
404
499
  end
405
500
 
406
- next @lex << EOL if newline
501
+ next @lex << EOL if b == 0x0a || b == 0x0d
502
+
503
+ # escape sequences are dropped without `ansi`, any other control
504
+ # character is text
505
+ next if b == 0x1b && ((c = token.getbyte(1)) == 0x5b || c == 0x5d)
506
+
507
+ (last = @lex[-1]).is_a?(Word) and next last.add(token)
508
+ @lex << Word.new(token)
407
509
  end
408
510
 
409
511
  @lex[-1] == EOL ? @lex[-1] = EOP : @lex << EOP
@@ -421,23 +523,46 @@ module Terminal
421
523
  line.encode!(ENCODING) if line.encoding != ENCODING
422
524
  csis = 0
423
525
 
424
- line.scan(SCAN_REGEX) do |newline, space, csi, osc, char|
425
- if char
426
- (last = @lex[-1]).is_a?(Word) and next last.add(char)
427
- next @lex << Word.new(char)
526
+ line.scan(SCAN_REGEX) do |token|
527
+ b = token.getbyte(0)
528
+
529
+ if b > 0x20 # word chunk: an ASCII run or a single grapheme
530
+ # a single-byte token is printable ASCII: one character, one
531
+ # column - no need to ask for its width
532
+ size = token.bytesize
533
+ if size == 1
534
+ (last = @lex[-1]).is_a?(Word) and next last.add(token, 1)
535
+ next @lex << Word.new(token, 1)
536
+ end
537
+ # an ASCII run is the only multi-byte token which cannot be a
538
+ # grapheme cluster - there its width is simply its byte count
539
+ size = nil unless b < 0x80 && token.ascii_only?
540
+ if (last = @lex[-1]).is_a?(Word)
541
+ next size ? last.add(token, size, true) : last.add(token)
542
+ end
543
+ next @lex << Word.new(token, size, true) if size
544
+ next @lex << Word.new(token)
428
545
  end
429
546
 
430
- if space
431
- (last = @lex[-1]).is_a?(Space) and next last.inc
432
- next @lex << Space.new
547
+ if SPACE_BYTE[b] && !(b == 0x0d && token.bytesize == 2)
548
+ size = token.bytesize
549
+ (last = @lex[-1]).is_a?(Space) and next last.size += size
550
+ next @lex << Space.new(size)
433
551
  end
434
552
 
435
- next @lex << EOL if newline
553
+ next @lex << EOL if b == 0x0a || b == 0x0d
436
554
 
437
- next @lex << Osc.new(osc) if osc
555
+ if (c = token.getbyte(1)) == 0x5d # Osc
556
+ next @lex << Osc.new(token)
557
+ end
558
+ if c != 0x5b # Csi
559
+ # a bare escape is just text
560
+ (last = @lex[-1]).is_a?(Word) and next last.add(token)
561
+ next @lex << Word.new(token)
562
+ end
438
563
 
439
- # Handle csi...
440
- if csi == "\e[m" || csi == "\e[0m"
564
+ # Handle Csi...
565
+ if token == "\e[m" || token == "\e[0m"
441
566
  next if csis == 0
442
567
 
443
568
  if @lex[-1].is_a?(Csi)
@@ -449,21 +574,17 @@ module Terminal
449
574
  next @lex << CsiEnd
450
575
  end
451
576
 
452
- (last = @lex[-1]).is_a?(Csi) and next last.add(csi)
577
+ (last = @lex[-1]).is_a?(Csi) and next last.add(token)
453
578
 
454
579
  csis += 1
455
- @lex << Csi.new(csi)
580
+ @lex << Csi.new(token)
456
581
  end
457
582
 
458
583
  @lex.pop if (last = @lex[-1]) == EOL
459
584
 
460
585
  next @lex << EOP if csis == 0
461
586
 
462
- if last.is_a?(Csi) && csis == 1
463
- @lex.pop
464
- else
465
- @lex << CsiEnd
466
- end
587
+ last.is_a?(Csi) && csis == 1 ? @lex.pop : @lex << CsiEnd
467
588
  @lex << EOP
468
589
  end
469
590
 
@@ -517,33 +638,56 @@ module Terminal
517
638
  class Space
518
639
  attr_accessor :size
519
640
  def to_str = (@size == 1 ? ' ' : ' ' * @size)
520
- def initialize = (@size = 1)
641
+ def initialize(size = 1) = (@size = size)
521
642
  def inc = (@size += 1)
522
643
  def inspect = @size == 1 ? '<Space>' : "<Space #{@size}>"
523
644
  end
524
645
 
525
646
  # @private
647
+ # A chunk is either a single grapheme cluster or a run of printable
648
+ # ASCII, for which the display width equals the character count.
526
649
  class Word
527
- def to_str = (@to_str ||= @chars.join)
528
- def size = (@size ||= @sizes.sum)
529
- def inspect = "<Word #{@sizes.sum}:#{@chars.join.inspect}>"
530
-
531
- def initialize(char, size = Text.char_width(char))
532
- @chars = [char]
650
+ def to_str = (@to_str ||= @chunks.size == 1 ? @chunks[0] : @chunks.join)
651
+ def size = (@size ||= @sizes.size == 1 ? @sizes[0] : @sizes.sum)
652
+ def inspect = "<Word #{@sizes.sum}:#{@chunks.join.inspect}>"
653
+
654
+ # `run` marks a chunk holding more than one character; only the lexer
655
+ # creates those and it knows without having to inspect the chunk again
656
+ def initialize(chunk, size = Text.char_width(chunk), run = false)
657
+ @chunks = [chunk]
533
658
  @sizes = [size]
659
+ @runs = run
534
660
  end
535
661
 
536
- def add(char, size = Text.char_width(char))
537
- @chars << char
662
+ def add(chunk, size = Text.char_width(chunk), run = false)
663
+ @chunks << chunk
538
664
  @sizes << size
665
+ @runs ||= run
539
666
  nil
540
667
  end
541
668
 
542
669
  def split(width)
543
- return [self] if @chars.size == 1
670
+ if @runs
671
+ # ASCII runs have to become single characters again to be split -
672
+ # a multi-character grapheme cluster must stay untouched
673
+ chars = []
674
+ sizes = []
675
+ @chunks.each_with_index do |chunk, idx|
676
+ if chunk.bytesize > 1 && chunk.getbyte(0) < 0x80 &&
677
+ chunk.ascii_only?
678
+ next chunk.each_char { chars << it and sizes << 1 }
679
+ end
680
+ chars << chunk
681
+ sizes << @sizes[idx]
682
+ end
683
+ else
684
+ chars = @chunks
685
+ sizes = @sizes
686
+ end
687
+ return [self] if chars.size == 1
544
688
  ret = last = size = nil
545
- @chars.each_with_index do |char, idx|
546
- csize = @sizes[idx]
689
+ chars.each_with_index do |char, idx|
690
+ csize = sizes[idx]
547
691
  next ret = [last = Word.new(char, size = csize)] unless ret
548
692
  next last.add(char, csize) if (size += csize) <= width
549
693
  ret << (last = Word.new(char, size = csize))
@@ -597,16 +741,36 @@ module Terminal
597
741
  space_cache[2]
598
742
  SPACE_CACHE = space_cache.freeze
599
743
 
744
+ # A run of printable ASCII is only taken when the following character is
745
+ # ASCII too: everything which can extend a grapheme cluster (combining
746
+ # marks, ZWJ, variation selectors, ...) is non-ASCII, so a run can never
747
+ # swallow the base of a cluster `\X` would have kept together.
600
748
  SCAN_REGEX =
601
- /\G(?:
602
- (\r?\n)
603
- | (\s)
604
- | (\e\[[\x30-\x3f]*[\x20-\x2f]*[a-zA-Z])
605
- | (\e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\))
606
- | (\X)
607
- )/x
749
+ /
750
+ [\x21-\x7e]+(?=[\x00-\x7f]|\z)
751
+ | \x20+
752
+ | \r?\n
753
+ | \e\[[\x30-\x3f]*[\x20-\x2f]*[a-zA-Z]
754
+ | \e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\)
755
+ | \s
756
+ | \X
757
+ /x
758
+
759
+ SPACE_BYTE =
760
+ Hash
761
+ .new(false)
762
+ .compare_by_identity
763
+ .merge!(
764
+ 0x20 => true,
765
+ 0x09 => true,
766
+ 0x0b => true,
767
+ 0x0c => true,
768
+ 0x0d => true
769
+ )
770
+ .freeze
608
771
 
609
772
  private_constant(
773
+ :SPACE_BYTE,
610
774
  :Space,
611
775
  :Word,
612
776
  :Osc,
data/lib/terminal/text.rb CHANGED
@@ -29,14 +29,20 @@ module Terminal
29
29
  # Terminal::Text.ambiguous_char_width = 2 # for CJK terminals
30
30
  #
31
31
  # @return [Integer] default: `1`
32
- attr_accessor :ambiguous_char_width
32
+ attr_reader :ambiguous_char_width
33
+
34
+ # @attribute [w] ambiguous_char_width
35
+ def ambiguous_char_width=(value)
36
+ autoload?(:CharWidth) or CharWidth.clear
37
+ @ambiguous_char_width = value
38
+ end
33
39
 
34
40
  # Calculate the display width of a string in terminal columns.
35
41
  #
36
42
  # @example
37
43
  # Terminal::Text.width('Hello') # => 5
38
44
  # Terminal::Text.width('[bold]Hi[/bold]') # => 2
39
- # Terminal::Text.width('[bold]Hi[/bold]', bbcode: false) # => 14
45
+ # Terminal::Text.width('[bold]Hi[/bold]', bbcode: false) # => 15
40
46
  #
41
47
  # @param str [#to_s] the string to measure
42
48
  # @param bbcode (see Formatter#initialize)
@@ -100,11 +106,30 @@ module Terminal
100
106
  #
101
107
  # @see Formatter.format
102
108
  #
109
+ # @example
110
+ # Terminal::Text.format(
111
+ # 'Hello World', width: 9, align: :left, prefix: '| ', suffix: ' |'
112
+ # )
113
+ # # => ["| Hello     |", "| World     |"]
114
+ #
103
115
  # @param (see Formatter.format)
104
116
  # @return (see Formatter.format)
105
117
  # @raise (see Formatter.format)
106
118
  def format(...) = Formatter.format(...)
107
119
 
120
+ # Format text with alignment.
121
+ #
122
+ # @see Formatter.fmt
123
+ #
124
+ # @example
125
+ # Terminal::Text.fmt('Hi', align: :center, width: 10)
126
+ # # => ["    Hi    "]
127
+ #
128
+ # @param (see Formatter.fmt)
129
+ # @return (see Formatter.fmt)
130
+ # @raise (see Formatter.fmt)
131
+ def fmt(...) = Formatter.fmt(...)
132
+
108
133
  # @deprecated Use {.lines} and iterate over the result.
109
134
  #
110
135
  # @comment @param str [Array<#to_s>] text to process
@@ -157,7 +182,7 @@ module Terminal
157
182
  )
158
183
  warn(
159
184
  '[DEPRECATED] `each_line_with_size` is deprecated ' \
160
- '– use `.lines_width_size.each` instead',
185
+ '– use `.lines_with_size.each` instead',
161
186
  category: :deprecated,
162
187
  uplevel: 1
163
188
  )
@@ -206,66 +231,64 @@ module Terminal
206
231
  def char_width(char)
207
232
  ord = char.ord
208
233
  return @ctrlchar_width[ord] if ord < 0x20
209
- if char.size == 1
210
- return ord < 0xa1 ? 1 : CharWidth[ord] || @ambiguous_char_width
211
- end
234
+ return ord < 0xa1 ? 1 : CharWidth[ord] if char.bytesize == 1
235
+ return 2 if ord == 0x1f3f3 && @very_special_flags.include?(char)
212
236
  sum = 0
213
- zwj = false
214
- char.each_char do |c|
215
- next zwj = false if zwj
216
- ord = c.ord
217
- next zwj = true if ord == 0x200d # zero with joiner
218
- sum += CharWidth[ord] || @ambiguous_char_width
237
+ skip = false
238
+ char.each_codepoint do |cp|
239
+ next skip = false if skip
240
+ next skip = true if cp == 0x200d # zero width joiner
241
+ sum += cp < 0xa1 ? 1 : CharWidth[cp]
219
242
  end
220
243
  sum
221
244
  end
222
245
  end
223
246
 
224
- @ambiguous_char_width = 1
247
+ @very_special_flags = [
248
+ "🏳\u{FE0F}\u{200D}🌈", # rainbow flag
249
+ "🏳\u{FE0F}\u{200D}⚧\u{FE0F}" # transgender flag
250
+ ].freeze
225
251
 
226
- @ctrlchar_width =
227
- Hash
228
- .new(2)
229
- .compare_by_identity
230
- .merge!(
231
- 0x00 => 0,
232
- 0x01 => 1,
233
- 0x02 => 1,
234
- 0x03 => 1,
235
- 0x04 => 1,
236
- 0x05 => 0,
237
- 0x06 => 1,
238
- 0x07 => 0,
239
- 0x08 => 0,
240
- 0x09 => 8,
241
- 0x0a => 0,
242
- 0x0b => 0,
243
- 0x0c => 0,
244
- 0x0d => 0,
245
- 0x0e => 0,
246
- 0x0f => 0,
247
- 0x10 => 1,
248
- 0x11 => 1,
249
- 0x12 => 1,
250
- 0x13 => 1,
251
- 0x14 => 1,
252
- 0x15 => 1,
253
- 0x16 => 1,
254
- 0x17 => 1,
255
- 0x18 => 1,
256
- 0x19 => 1,
257
- 0x1a => 1,
258
- 0x1b => 1,
259
- 0x1c => 1,
260
- 0x1d => 1,
261
- 0x1e => 1,
262
- 0x1f => 1
263
- )
264
- .freeze
252
+ @ctrlchar_width = [
253
+ 0,
254
+ 1,
255
+ 1,
256
+ 1,
257
+ 1,
258
+ 0,
259
+ 1,
260
+ 0,
261
+ 0,
262
+ 1,
263
+ 0,
264
+ 0,
265
+ 0,
266
+ 0,
267
+ 0,
268
+ 0,
269
+ 1,
270
+ 1,
271
+ 1,
272
+ 1,
273
+ 1,
274
+ 1,
275
+ 1,
276
+ 1,
277
+ 1,
278
+ 1,
279
+ 1,
280
+ 1,
281
+ 1,
282
+ 1,
283
+ 1,
284
+ 1
285
+ ].freeze
286
+
287
+ @ambiguous_char_width = 1
265
288
 
266
- cw_file = "#{__dir__}/text/char_width.rb"
267
- autoload :CharWidth, cw_file
268
- autoload :UNICODE_VERSION, cw_file
289
+ char_width_file = "#{__dir__}/text/char_width.rb"
290
+ autoload :CharWidth, char_width_file
291
+ autoload :UNICODE_VERSION, char_width_file
269
292
  private_constant :CharWidth
270
293
  end
271
294
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Terminal
4
4
  # The version number of the gem.
5
- VERSION = '1.0.6'
5
+ VERSION = '1.0.9'
6
6
  end