terminal_rb 0.7.0 → 0.9.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f0ee278f7b96ba33953b258b8ca66365bbd3e97ea670488711e8ad42aa3e59b3
4
- data.tar.gz: de6c7769a32cf5aef25cf8acd055b1e86a5ac5b80eb36ff71afa83eba057f083
3
+ metadata.gz: 8fdd6ab56d007f6fa6e82bf8d557d0a27815ad789998da5583310dd62af2b551
4
+ data.tar.gz: ef83edfd6c82bc9a2a056d148cd4da2af7b1a28acaa0cab9863901d608d502b7
5
5
  SHA512:
6
- metadata.gz: f7c9198faea2f62bb289f19c3a42c8d271b898b826b1990164bea6eead69b1f78324ec02cc408b3d35a40b915de7e9e59b5d43489971c4ec6222a36a55b4a202
7
- data.tar.gz: f61cb0793edf2b27b9455e14df9ee5604c142f72e078cde13655fff055d626d0b3d9566dea2f029954c8b298a1c278af9f6612de4fded640dd1a3c17b7ae2f4d
6
+ metadata.gz: d53c04af3d74273cf3111b9b7078846e0c33f0caf8501e9f0182427ed784d96b94444c1f6238427dd248cf300fb362d95a3a0f5dea2ead5c571ff2fd7d52fdf9
7
+ data.tar.gz: 82d79cfab6b7d499bb5d6f9fb7d6ce9af14f69ed792f8f7eedf4485a4f26546576ecadd723cc67a48ffbb4bc00ab1cc83d04a15a1bceb37d8437ec825d0f38cc
data/README.md CHANGED
@@ -4,7 +4,7 @@ Terminal access with support for ANSI control codes and [BBCode-like](https://en
4
4
 
5
5
  - Gem: [rubygems.org](https://rubygems.org/gems/terminal_rb)
6
6
  - Source: [codeberg.org](https://codeberg.org/mblumtritt/Terminal.rb)
7
- - Help: [rubydoc.info](https://rubydoc.info/gems/terminal_rb/Terminal)
7
+ - Help: [rubydoc.info](https://rubydoc.info/gems/terminal_rb/0.9.0/Terminal)
8
8
 
9
9
  ## Features
10
10
 
@@ -43,6 +43,22 @@ Terminal::Text.width('ライブラリは中国語、日本語、韓国語のテ
43
43
  # => 64
44
44
  ```
45
45
 
46
+ ### Split text word-wise and limit line width to 30 chars
47
+
48
+ ```ruby
49
+ Terminal::Text.each_line(<<~TEXT, limit: 30).to_a
50
+ [b]Hello Ruby World![/]
51
+ This gem provides terminal access with support for [i]ANSI[/] control codes
52
+ and [i]BBCode-like[/] embedded text attribute syntax.
53
+ TEXT
54
+ # => ["\e[1mHello Ruby World!\e[m",
55
+ # => "This gem provides terminal",
56
+ # => "access with support for \e[3mANSI\e[m",
57
+ # => "control codes",
58
+ # => "and \e[3mBBCode-like\e[m embedded text",
59
+ # => "attribute syntax."]
60
+ ```
61
+
46
62
  Have a look at the [examples](./examples/) directory to learn from code.
47
63
 
48
64
  ## Installation
data/lib/terminal/ansi.rb CHANGED
@@ -154,7 +154,10 @@ module Terminal
154
154
  #
155
155
  # @param str [#to_s] string to be modified
156
156
  # @return [String] string without ANSI attributes
157
- def undecorate(str) = str.to_s.gsub(TEST, '')
157
+ def undecorate(str)
158
+ str = str.to_s
159
+ str.index("\e") ? str.gsub(TEST, '') : str.dup
160
+ end
158
161
 
159
162
  # Try to combine given ANSI attributes and colors.
160
163
  # The attributes and colors have to be separated by given `separator``.
@@ -220,13 +223,13 @@ module Terminal
220
223
  # @param str [#to_s] string to be modified
221
224
  # @return [String] string with ANSI attributes
222
225
  def bbcode(str)
223
- str
224
- .to_s
225
- .gsub(BBCODE) do |match_str|
226
- next match_str if (match = Regexp.last_match[1]).empty?
227
- next "[#{match[1..]}]" if match[0] == '\\'
228
- try_convert(match) || match_str
229
- end
226
+ str = str.to_s
227
+ return str.dup unless str.index('[')
228
+ str.gsub(BBCODE) do |match_str|
229
+ next match_str if (match = Regexp.last_match[1]).empty?
230
+ next "[#{match[1..]}]" if match[0] == '\\'
231
+ try_convert(match) || match_str
232
+ end
230
233
  end
231
234
 
232
235
  # Remove embedded BBCode-like attributes.
@@ -240,15 +243,15 @@ module Terminal
240
243
  # @param str [#to_s] string to be modified
241
244
  # @return [String] string without BBCode
242
245
  def unbbcode(str)
243
- str
244
- .to_s
245
- .gsub(BBCODE) do |match_str|
246
- next match_str if (match = Regexp.last_match[1]).empty?
247
- next "[#{match[1..]}]" if match[0] == '\\'
248
- next match_str if (match = match.split).empty?
249
- next if match.all? { ATTRIBUTES[_1] || COLORS[_1] || _color(_1) }
250
- match_str
251
- end
246
+ str = str.to_s
247
+ return str.dup unless str.index('[')
248
+ str.gsub(BBCODE) do |match_str|
249
+ next match_str if (match = Regexp.last_match[1]).empty?
250
+ next "[#{match[1..]}]" if match[0] == '\\'
251
+ next match_str if (match = match.split).empty?
252
+ next if match.all? { ATTRIBUTES[_1] || COLORS[_1] || _color(_1) }
253
+ match_str
254
+ end
252
255
  end
253
256
 
254
257
  #
@@ -264,7 +267,21 @@ module Terminal
264
267
  #
265
268
  # @param str [#to_s] string to be modified
266
269
  # @return [String] string without BBCode and ANSI control codes.
267
- def plain(str) = unbbcode(str).gsub(TEST, '')
270
+ def plain(str)
271
+ str = str.to_s
272
+ unless str.index('[')
273
+ return str.index("\e") ? str.gsub(TEST, '') : str.dup
274
+ end
275
+ str =
276
+ str.gsub(BBCODE) do |match_str|
277
+ next match_str if (match = Regexp.last_match[1]).empty?
278
+ next "[#{match[1..]}]" if match[0] == '\\'
279
+ next match_str if (match = match.split).empty?
280
+ next if match.all? { ATTRIBUTES[_1] || COLORS[_1] || _color(_1) }
281
+ match_str
282
+ end
283
+ str.index("\e") ? str.gsub!(TEST, '') : str
284
+ end
268
285
 
269
286
  # Create nice colored text.
270
287
  #
@@ -47,47 +47,37 @@ module Terminal
47
47
  KEY_MAP =
48
48
  Module
49
49
  .new do
50
- def self.add_modifiers(**keys)
50
+ def self.add_modifiers(keys)
51
51
  @mods.each_pair do |mod, pref|
52
- @map.merge!(
53
- keys.to_h do |name, code|
54
- ["\e[1;#{mod}#{code}", "#{pref}+#{name}"]
55
- end
56
- )
52
+ keys.each_pair do |name, code|
53
+ @map["\e[1;#{mod}#{code}"] = "#{pref}+#{name}"
54
+ end
57
55
  end
58
56
  end
59
57
 
60
- def self.add_keys(**keys)
61
- @map.merge!(keys.to_h { |name, code| ["\e[#{code}", name] })
62
- add_modifiers(**keys)
58
+ def self.add_keys(keys)
59
+ keys.each_pair { |name, code| @map["\e[#{code}"] = name }
60
+ add_modifiers(keys)
63
61
  end
64
62
 
65
- def self.add_fkeys(**keys)
66
- @map.merge!(keys.to_h { |name, code| ["\e[#{code}~", name] })
63
+ def self.add_fkeys(keys)
64
+ keys.each_pair { |name, code| @map["\e[#{code}~"] = name }
67
65
  @mods.each_pair do |mod, prefix|
68
- @map.merge!(
69
- keys.to_h do |name, code|
70
- ["\e[#{code};#{mod}~", "#{prefix}+#{name}"]
71
- end
72
- )
73
- end
74
- end
75
-
76
- def self.add_alt_keys(**keys)
77
- keys.each_pair do |name, code|
78
- @map[code] = name
79
- @map["\e#{code}"] = "Alt+#{name}" # kitty
66
+ keys.each_pair do |name, code|
67
+ @map["\e[#{code};#{mod}~"] = "#{prefix}+#{name}"
68
+ end
80
69
  end
81
70
  end
82
71
 
83
72
  def self.to_hash
84
- # control codes
85
73
  num = 0
86
74
  @map = ('A'..'Z').to_h { [(num += 1).chr, "Ctrl+#{_1}"] }
87
75
 
88
- add_keys('F1' => 'P', 'F2' => 'Q', 'F3' => 'R', 'F4' => 'S')
89
-
90
76
  add_keys(
77
+ 'F1' => 'P',
78
+ 'F2' => 'Q',
79
+ 'F3' => 'R',
80
+ 'F4' => 'S',
91
81
  'Up' => 'A',
92
82
  'Down' => 'B',
93
83
  'Right' => 'C',
@@ -97,7 +87,7 @@ module Terminal
97
87
  )
98
88
 
99
89
  add_fkeys(
100
- 'DEL' => '3',
90
+ 'Del' => '3',
101
91
  'PgUp' => '5',
102
92
  'PgDown' => '6',
103
93
  # -
@@ -126,18 +116,29 @@ module Terminal
126
116
 
127
117
  add_fkeys('F3' => '13') # Kitty
128
118
 
129
- add_alt_keys(
130
- 'ESC' => "\e",
131
- 'ENTER' => "\r",
132
- 'TAB' => "\t",
133
- 'BACK' => "\u007F",
134
- 'Ctrl+BACK' => "\b",
135
- 'Shift+TAB' => "\e[Z"
136
- )
119
+ # Kitty:
120
+ @mods.each_pair do |mod, pref|
121
+ ('a'..'z').each do |char|
122
+ @map["\e[#{char.ord};#{mod}u"] = "#{pref}+#{char.upcase}"
123
+ end
124
+ end
125
+
126
+ {
127
+ 'Esc' => "\e",
128
+ 'Enter' => "\r",
129
+ 'Tab' => "\t",
130
+ 'Back' => "\u007F",
131
+ 'Shift+Tab' => "\e[Z"
132
+ }.each_pair do |name, code|
133
+ @map[code] = name
134
+ @map["\e#{code}"] = "Alt+#{name}" # Kitty
135
+ end
137
136
 
138
137
  # overrides and additional keys
139
138
  @map.merge!(
140
- "\4" => 'DEL',
139
+ "\b" => 'Ctrl+Back',
140
+ "\e\b" => 'Ctrl+Alt+Back', # Kitty
141
+ "\4" => 'Del',
141
142
  "\e[5" => 'PgUp',
142
143
  "\e[6" => 'PgDown',
143
144
  # SS3 control (VT 100 etc)
data/lib/terminal/text.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require_relative 'ansi'
4
4
 
5
5
  module Terminal
6
+ # Text helper functions.
7
+ #
6
8
  module Text
7
9
  class << self
8
10
  # Value for {width} of letters whose display width is not precisely
@@ -31,46 +33,85 @@ module Terminal
31
33
  str = str.encode(ENC) if str.encoding != ENC
32
34
  width = 0
33
35
  str.scan(WIDTH_SCANNER) do |sp, gc|
34
- next width += __char_width(gc) if gc
36
+ next width += char_width(gc) if gc
35
37
  width += 1 if sp
36
38
  end
37
39
  width
38
40
  end
39
41
 
40
42
  # Iterate each line of given text.
41
- # It can optionally
42
43
  #
43
- # - interprete embedded BBCode
44
- # - remove ANSI control codes
45
- # - ignore embedded new line
46
- # - limit text output width
47
- # - report each line's size
48
- #
49
- # @param (see Wrap#initialize)
50
- # @param (see Wrap#each_line)
51
- # @yield (see Wrap#each_line)
52
- # @return (see Wrap#each_line)
53
- # @raise (see Wrap#each_line)
44
+ # @param [#to_s, ...] text
45
+ # text objects to process
46
+ # @param [#to_i, nil] limit
47
+ # optionally limit line size
48
+ # @param [true, false] bbcode
49
+ # whether to interprete embedded BBCode (see {Ansi.bbcode})
50
+ # @param [true, false] ansi
51
+ # whether to keep embedded ANSI control codes
52
+ # @param [true, false] ignore_newline
53
+ # wheter to ignore embedded line breaks (`"\r\n"` or `"\n"`)
54
+ # @yield [String] text line
55
+ # @return [Enumerator] when no block given
56
+ # @return [nil]
57
+ # @raise ArgumentError when a `limit` less than `1` is given
54
58
  def each_line(
55
59
  *text,
60
+ limit: nil,
56
61
  bbcode: true,
57
62
  ansi: true,
58
63
  ignore_newline: false,
64
+ &block
65
+ )
66
+ if limit
67
+ limit = limit.to_i
68
+ raise(ArgumentError, "invalid limit - #{limit}") if limit < 1
69
+ if block_given?
70
+ lines_in(text, bbcode, ansi, ignore_newline, limit, &block)
71
+ else
72
+ to_enum(:lines_in, text, bbcode, ansi, ignore_newline, limit)
73
+ end
74
+ elsif block_given?
75
+ lines(text, bbcode, ansi, ignore_newline, &block)
76
+ else
77
+ to_enum(:lines, text, bbcode, ansi, ignore_newline)
78
+ end
79
+ end
80
+ alias each each_line
81
+
82
+ # Iterate each line and it's display width of given text.
83
+ #
84
+ # @param (see each_line)
85
+ # @yield [String, Integer] text line and it's display width
86
+ # @return (see each_line)
87
+ # @raise (see each_line)
88
+ def each_line_with_size(
89
+ *text,
59
90
  limit: nil,
60
- with_size: false,
91
+ bbcode: true,
92
+ ansi: true,
93
+ ignore_newline: false,
61
94
  &block
62
95
  )
63
- Wrap.new(
64
- *text,
65
- bbcode: bbcode,
66
- ansi: ansi,
67
- ignore_newline: ignore_newline
68
- ).each_line(limit: limit, with_size: with_size, &block)
96
+ if limit
97
+ limit = limit.to_i
98
+ raise(ArgumentError, "invalid limit - #{limit}") if limit < 1
99
+ if block_given?
100
+ pairs_in(text, bbcode, ansi, ignore_newline, limit, &block)
101
+ else
102
+ to_enum(:pairs_in, text, bbcode, ansi, ignore_newline, limit)
103
+ end
104
+ elsif block_given?
105
+ pairs(text, bbcode, ansi, ignore_newline, &block)
106
+ else
107
+ to_enum(:pairs, text, bbcode, ansi, ignore_newline)
108
+ end
69
109
  end
110
+ alias each_with_size each_line_with_size
111
+
112
+ private
70
113
 
71
- # @!visibility private
72
- # works for UTF-8 chars only!
73
- def __char_width(char)
114
+ def char_width(char)
74
115
  ord = char.ord
75
116
  return CONTROL_CHAR_WIDTH[ord] || 2 if ord < 0x20
76
117
  return 1 if ord < 0xa1
@@ -80,127 +121,39 @@ module Terminal
80
121
  # Halfwidth Dakuten Handakuten
81
122
  sco == 0xff9e || sco == 0xff9f ? 2 : 1
82
123
  end
83
- end
84
124
 
85
- # Helper class to calculate word-wise text wrapping in various conditions.
86
- # Internally used by {Text.each_line}.
87
- class Wrap
88
- # Create a new instance which may support different conditions.
89
- #
90
- # @param [#to_s, ...] text
91
- # text objects to process
92
- # @param [true, false] bbcode
93
- # whether to interprete embedded BBCode (see {Ansi.bbcode})
94
- # @param [true, false] ansi
95
- # whether to keep embedded ANSI control codes
96
- # @param [true, false] ignore_newline
97
- # wheter to ignore embedded line breaks (`"\r\n"` or `"\n"`)
98
- def initialize(*text, bbcode: true, ansi: true, ignore_newline: false)
99
- @parts = []
125
+ def each_part(text, bbcode, ansi, ignore_newline)
100
126
  newline = ignore_newline ? :space : :nl
101
127
  text.each do |txt|
102
128
  txt = bbcode ? Ansi.bbcode(txt) : txt.to_s
103
- next @parts << :hard_nl if txt.empty?
129
+ next yield(:hard_nl) if txt.empty?
104
130
  txt = txt.encode(ENC) if txt.encoding != ENC
105
131
  word = nil
106
- txt.scan(REGEXP) do |nl, csi, osc, space, gc|
107
- next word ? word << gc : @parts << (word = Word.new(gc)) if gc
132
+ txt.scan(SCAN_EXPR) do |nl, csi, osc, space, gc|
133
+ if gc
134
+ next word.add(gc, char_width(gc)) if word
135
+ next word = Word.new(gc, char_width(gc))
136
+ end
137
+ yield(word) if word
108
138
  word = nil
109
- next @parts << :space if space
110
- next @parts << newline if nl
139
+ next yield(:space) if space
140
+ next yield(newline) if nl
111
141
  next unless ansi
112
- next @parts << [:seq, osc] if osc
113
- next @parts << :seq_end if csi == "\e[m" || csi == "\e[0m"
114
- @parts << [:seq, csi]
142
+ next yield(:seq, osc) if osc
143
+ next yield(:seq_end) if csi == "\e[m" || csi == "\e[0m"
144
+ yield(:seq, csi)
115
145
  end
116
- @parts << :hard_nl
146
+ yield(word) if word
147
+ yield(:hard_nl)
117
148
  end
118
- end
119
-
120
- # Iterate each line of given text.
121
- #
122
- # @param [#to_i, nil] limit
123
- # optionally limit line size
124
- # @param [true, false] with_size
125
- # whether to yield each line with it's display width
126
- # @yield [String] line when `with_size` is false
127
- # @yield [<String, Integer>] line and it's display width
128
- # when `with_size` is true
129
- # @return [Enumerator] when no block is given
130
- # @return [nil] when block is given
131
- # @raise ArgumentError when a `limit` less than `1` is given
132
- def each_line(limit: nil, with_size: false, &block)
133
- unless limit
134
- return with_size ? pairs(&block) : lines(&block) if block_given?
135
- return to_enum(with_size ? :pairs : :lines)
136
- end
137
- limit = limit.to_i
138
- raise(ArgumentError, "invalid limit - #{limit}") if limit < 1
139
- if block_given?
140
- return with_size ? pairs_in(limit, &block) : lines_in(limit, &block)
141
- end
142
- to_enum(with_size ? :pairs_in : :lines_in, limit)
143
- end
144
- alias each each_line
145
-
146
- # @!visibility private
147
- def each_word(with_size: false, &block)
148
- return with_size ? word_pairs(&block) : words(&block) if block_given?
149
- to_enum(with_size ? :word_pairs : :words)
150
- end
151
-
152
- # @!visibility private
153
- def to_str
154
- str = EMPTY.dup
155
- seq = EMPTY.dup
156
- @parts.each do |part, opt|
157
- next str << part if part.is_a?(Word)
158
- next str << ' ' if part == :space
159
-
160
- if part == :nl
161
- str << "\n"
162
- next str << seq.dup
163
- end
164
-
165
- if part == :seq
166
- str << opt
167
- next seq << opt
168
- end
169
-
170
- # :seq_end
171
- next if seq.empty?
172
- str << "\e[m"
173
- seq.clear
174
- end
175
- str
176
- end
177
- alias to_s to_str
178
-
179
- # @!visibility private
180
- def to_a(limit: nil, with_size: false)
181
- each_line(limit: limit, with_size: with_size).to_a
182
- end
183
-
184
- # @!visibility private
185
- def to_ary = each_line.to_a
186
-
187
- private
188
-
189
- def words
190
- @parts.each { yield(_1.to_s) if _1.is_a?(Word) }
191
149
  nil
192
150
  end
193
151
 
194
- def word_pairs
195
- @parts.each { yield(_1.to_s, _1.size) if _1.is_a?(Word) }
196
- nil
197
- end
198
-
199
- def lines
152
+ def lines(text, bbcode, ansi, ignore_newline)
200
153
  current = EMPTY.dup
201
154
  seq = EMPTY.dup
202
155
  lws = nil
203
- @parts.each do |part, opt|
156
+ each_part(text, bbcode, ansi, ignore_newline) do |part, opt|
204
157
  if part == :space
205
158
  next if lws
206
159
  current << ' '
@@ -239,12 +192,12 @@ module Terminal
239
192
  nil
240
193
  end
241
194
 
242
- def lines_in(limit)
195
+ def lines_in(text, bbcode, ansi, ignore_newline, limit)
243
196
  current = EMPTY.dup
244
197
  seq = EMPTY.dup
245
198
  width = 0
246
199
  lws = nil
247
- @parts.each do |part, opt|
200
+ each_part(text, bbcode, ansi, ignore_newline) do |part, opt|
248
201
  if part == :space
249
202
  next if lws
250
203
  if width.succ < limit
@@ -322,12 +275,12 @@ module Terminal
322
275
  nil
323
276
  end
324
277
 
325
- def pairs
278
+ def pairs(text, bbcode, ansi, ignore_newline)
326
279
  current = EMPTY.dup
327
280
  seq = EMPTY.dup
328
281
  width = 0
329
282
  lws = nil
330
- @parts.each do |part, opt|
283
+ each_part(text, bbcode, ansi, ignore_newline) do |part, opt|
331
284
  if part == :space
332
285
  next if lws
333
286
  current << ' '
@@ -371,12 +324,12 @@ module Terminal
371
324
  nil
372
325
  end
373
326
 
374
- def pairs_in(limit)
327
+ def pairs_in(text, bbcode, ansi, ignore_newline, limit)
375
328
  current = EMPTY.dup
376
329
  seq = EMPTY.dup
377
330
  width = 0
378
331
  lws = nil
379
- @parts.each do |part, opt|
332
+ each_part(text, bbcode, ansi, ignore_newline) do |part, opt|
380
333
  if part == :space
381
334
  next if lws
382
335
  if width.succ < limit
@@ -457,46 +410,40 @@ module Terminal
457
410
  end
458
411
  nil
459
412
  end
413
+ end
460
414
 
461
- class Word
462
- attr_reader :to_str, :size, :chars
415
+ @ambiguous_char_width = 1
463
416
 
464
- def initialize(char)
465
- @to_str = char.dup
466
- @size = Text.__char_width(char)
467
- @chars = [[char, @size]]
468
- end
417
+ class Word
418
+ attr_reader :to_str, :size, :chars
469
419
 
470
- def <<(char)
471
- @to_str << char
472
- @chars << [char, cw = Text.__char_width(char)]
473
- @size += cw
474
- self
475
- end
420
+ def initialize(char, size)
421
+ @to_str = char.dup
422
+ @size = size
423
+ @chars = [[char, size]]
424
+ end
425
+
426
+ def add(char, size)
427
+ @to_str << char
428
+ @size += size
429
+ @chars << [char, size]
430
+ nil
476
431
  end
477
- private_constant :Word
478
-
479
- REGEXP =
480
- /\G(?:
481
- (\r?\n)
482
- | (\e\[[\d;:\?]*[ABCDEFGHJKSTfminsuhl])
483
- | (\e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\))
484
- | (\s+)
485
- | (\X)
486
- )/x
487
- private_constant :REGEXP
488
-
489
- ENC = Encoding::UTF_8
490
- private_constant :ENC
491
-
492
- EMPTY = String.new(encoding: ENC).freeze
493
- private_constant :EMPTY
494
432
  end
433
+ private_constant :Word
495
434
 
496
435
  ENC = Encoding::UTF_8
497
- private_constant :ENC
436
+ EMPTY = String.new(encoding: ENC).freeze
437
+ private_constant :ENC, :EMPTY
498
438
 
499
- @ambiguous_char_width = 1
439
+ SCAN_EXPR =
440
+ /\G(?:
441
+ (\r?\n)
442
+ | (\e\[[\d;:\?]*[ABCDEFGHJKSTfminsuhl])
443
+ | (\e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\))
444
+ | (\s+)
445
+ | (\X)
446
+ )/x
500
447
 
501
448
  WIDTH_SCANNER =
502
449
  /\G(?:
@@ -505,7 +452,7 @@ module Terminal
505
452
  | (\s+)
506
453
  | (\X)
507
454
  )/x
508
- private_constant :WIDTH_SCANNER
455
+ private_constant :SCAN_EXPR, :WIDTH_SCANNER
509
456
 
510
457
  CONTROL_CHAR_WIDTH = {
511
458
  0x00 => 0,
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Terminal
4
4
  # The version number of the gem.
5
- VERSION = '0.7.0'
5
+ VERSION = '0.9.1'
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terminal_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
@@ -44,10 +44,10 @@ homepage: https://codeberg.org/mblumtritt/Terminal.rb
44
44
  licenses:
45
45
  - MIT
46
46
  metadata:
47
+ rubygems_mfa_required: 'true'
47
48
  source_code_uri: https://codeberg.org/mblumtritt/Terminal.rb
48
49
  bug_tracker_uri: https://codeberg.org/mblumtritt/Terminal.rb/issues
49
- documentation_uri: https://rubydoc.info/gems/terminal_rb/Terminal
50
- rubygems_mfa_required: 'true'
50
+ documentation_uri: https://rubydoc.info/gems/terminal_rb/0.9.1/Terminal
51
51
  rdoc_options: []
52
52
  require_paths:
53
53
  - lib