terminal_rb 1.0.5 → 1.0.8

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.
@@ -32,8 +32,8 @@ module Terminal
32
32
  # # => [["Hello", 5]]
33
33
  #
34
34
  # @param (see #initialize)
35
- # @param with_size [true, false] when +true+,
36
- # return +[line, width]+ pairs instead of plain strings
35
+ # @param with_size [true, false] when `true`,
36
+ # return `[line, width]` pairs instead of plain strings
37
37
  # @param (see #lines_with_size)
38
38
  # @return (see #lines_with_size)
39
39
  def self.[](
@@ -86,17 +86,23 @@ module Terminal
86
86
  # @param ansi [true, false] recognize ANSI escape codes
87
87
  # @param bbcode [true, false] process BBCode markup
88
88
  # @param spaces [true, false] preserve whitespace;
89
- # when +false+ leading/trailing spaces and multiple spaces are
89
+ # when `false` leading/trailing spaces and multiple spaces are
90
90
  # collapsed
91
91
  # @param eol [true, false] preserve line endings;
92
- # when +false+ newlines are treated as spaces
92
+ # when `false` newlines are treated as spaces
93
93
  def initialize(*str, ansi: true, bbcode: true, spaces: true, eol: true)
94
94
  @lex = []
95
95
  return if str.empty?
96
96
  ansi ? _generate_ansi(str, bbcode) : _generate(str, bbcode)
97
97
  return if @lex.empty?
98
+ @keep_paragraph = true
98
99
  @lex = _ignore_whitespace unless spaces
99
- @lex = _ignore_newline unless eol
100
+ case eol
101
+ when false, nil
102
+ @lex = _ignore_newline
103
+ when :no_paragraph
104
+ @keep_paragraph = false
105
+ end
100
106
  end
101
107
 
102
108
  # Word-wrap and return lines with their display widths.
@@ -106,10 +112,10 @@ module Terminal
106
112
  # fmt.lines_with_size(width: 5)
107
113
  # # => [["Hello", 5], ["World", 5]]
108
114
  #
109
- # @param width [Integer, nil] maximum line width in columns;
110
- # +nil+ returns unwrapped lines
115
+ # @param width [#to_i, nil] maximum line width in columns;
116
+ # `nil` returns unwrapped lines
111
117
  # @return [Array<String, Integer>] pairs of
112
- # +[line_text, display_width]+
118
+ # `[line_text, display_width]`
113
119
  # @raise (see #format)
114
120
  def lines_with_size(width: nil)
115
121
  return [] if @lex.empty?
@@ -125,9 +131,9 @@ module Terminal
125
131
  # fmt.lines(width: 5)
126
132
  # # => ["Hello", "World"]
127
133
  #
128
- # @param width [Integer, nil] maximum line width in columns
134
+ # @param width [#to_i, nil] maximum line width in columns
129
135
  # @return [Array<String>]
130
- # @raise [ArgumentError] if +width+ is zero or negative
136
+ # @raise [ArgumentError] if `width` is zero or negative
131
137
  def lines(width: nil) = lines_with_size(width:).map(&:first)
132
138
 
133
139
  # Format lines with alignment, padding, and decorations.
@@ -138,11 +144,11 @@ module Terminal
138
144
  # # => [" Hi "]
139
145
  #
140
146
  # @param align [Symbol, nil] text alignment:
141
- # +:left+, +:right+, +:center+, or +nil+ (no fill)
142
- # @param width [Integer, nil] output line width in columns
143
- # @param height [Integer, nil] number of output lines;
147
+ # `:left`, `:right`, `:center`, or `nil` (no fill)
148
+ # @param width [#to_i, nil] output line width in columns
149
+ # @param height [#to_i, nil] number of output lines;
144
150
  # negative values take lines from the end
145
- # @param padding [Integer, Array, nil] CSS-style padding
151
+ # @param padding [#to_i, Array, nil] CSS-style padding
146
152
  # - 1 value: all sides;
147
153
  # - 2 values: [vertical, horizontal];
148
154
  # - 3 values: [top, horizontal, bottom];
@@ -150,7 +156,7 @@ module Terminal
150
156
  # @param prefix [#to_s, nil] string prepended to each line
151
157
  # @param suffix [#to_s, nil] string appended to each line
152
158
  # @return [Array<String>] formatted output lines
153
- # @raise [ArgumentError] if +width+ is zero or negative
159
+ # @raise [ArgumentError] if `width` is zero or negative
154
160
  def format(
155
161
  align: nil,
156
162
  width: nil,
@@ -226,7 +232,7 @@ module Terminal
226
232
  # fmt = Terminal::Text::Formatter.new("short\na longer line")
227
233
  # fmt.max_line_width # => 13
228
234
  #
229
- # @return [Integer] widest line in columns, +0+ when empty
235
+ # @return [Integer] widest line in columns, `0` when empty
230
236
  def max_line_width
231
237
  @max_line_width ||=
232
238
  (@lex.empty? ? 0 : (@unlimited || _unlimited).max_by(&:last)[-1])
@@ -239,7 +245,7 @@ module Terminal
239
245
  # Terminal::Text::Formatter.new('Hello World').to_s(width: 5)
240
246
  # # => "Hello\nWorld"
241
247
  #
242
- # @param width [Integer, nil] maximum line width in columns
248
+ # @param width [#to_i, nil] maximum line width in columns
243
249
  # @return [String]
244
250
  def to_s(width: nil) = lines(width:).join("\n")
245
251
 
@@ -298,7 +304,7 @@ module Terminal
298
304
  size -= last.size
299
305
  next add_line.call
300
306
  end
301
- add_line.call if size > 0
307
+ add_line.call if (current != EOP) || (@keep_paragraph || size > 0)
302
308
  next
303
309
  end
304
310
 
@@ -386,18 +392,41 @@ module Terminal
386
392
 
387
393
  line.encode!(ENCODING) if line.encoding != ENCODING
388
394
 
389
- line.scan(SCAN_REGEX) do |newline, space, _, _, char|
390
- if char
391
- (last = @lex[-1]).is_a?(Word) and next last.add(char)
392
- next @lex << Word.new(char)
395
+ line.scan(SCAN_REGEX) do |token|
396
+ b = token.getbyte(0)
397
+
398
+ if b > 0x20 # word chunk: an ASCII run or a single grapheme
399
+ # a single-byte token is printable ASCII: one character, one
400
+ # column - no need to ask for its width
401
+ size = token.bytesize
402
+ if size == 1
403
+ (last = @lex[-1]).is_a?(Word) and next last.add(token, 1)
404
+ next @lex << Word.new(token, 1)
405
+ end
406
+ # an ASCII run is the only multi-byte token which cannot be a
407
+ # grapheme cluster - there its width is simply its byte count
408
+ size = nil unless b < 0x80 && token.ascii_only?
409
+ if (last = @lex[-1]).is_a?(Word)
410
+ next size ? last.add(token, size, true) : last.add(token)
411
+ end
412
+ next @lex << Word.new(token, size, true) if size
413
+ next @lex << Word.new(token)
393
414
  end
394
415
 
395
- if space
396
- (last = @lex[-1]).is_a?(Space) and next last.inc
397
- next @lex << Space.new
416
+ if SPACE_BYTE[b] && !(b == 0x0d && token.bytesize == 2)
417
+ size = token.bytesize
418
+ (last = @lex[-1]).is_a?(Space) and next last.size += size
419
+ next @lex << Space.new(size)
398
420
  end
399
421
 
400
- next @lex << EOL if newline
422
+ next @lex << EOL if b == 0x0a || b == 0x0d
423
+
424
+ # escape sequences are dropped without `ansi`, any other control
425
+ # character is text
426
+ next if b == 0x1b && ((c = token.getbyte(1)) == 0x5b || c == 0x5d)
427
+
428
+ (last = @lex[-1]).is_a?(Word) and next last.add(token)
429
+ @lex << Word.new(token)
401
430
  end
402
431
 
403
432
  @lex[-1] == EOL ? @lex[-1] = EOP : @lex << EOP
@@ -415,23 +444,46 @@ module Terminal
415
444
  line.encode!(ENCODING) if line.encoding != ENCODING
416
445
  csis = 0
417
446
 
418
- line.scan(SCAN_REGEX) do |newline, space, csi, osc, char|
419
- if char
420
- (last = @lex[-1]).is_a?(Word) and next last.add(char)
421
- next @lex << Word.new(char)
447
+ line.scan(SCAN_REGEX) do |token|
448
+ b = token.getbyte(0)
449
+
450
+ if b > 0x20 # word chunk: an ASCII run or a single grapheme
451
+ # a single-byte token is printable ASCII: one character, one
452
+ # column - no need to ask for its width
453
+ size = token.bytesize
454
+ if size == 1
455
+ (last = @lex[-1]).is_a?(Word) and next last.add(token, 1)
456
+ next @lex << Word.new(token, 1)
457
+ end
458
+ # an ASCII run is the only multi-byte token which cannot be a
459
+ # grapheme cluster - there its width is simply its byte count
460
+ size = nil unless b < 0x80 && token.ascii_only?
461
+ if (last = @lex[-1]).is_a?(Word)
462
+ next size ? last.add(token, size, true) : last.add(token)
463
+ end
464
+ next @lex << Word.new(token, size, true) if size
465
+ next @lex << Word.new(token)
422
466
  end
423
467
 
424
- if space
425
- (last = @lex[-1]).is_a?(Space) and next last.inc
426
- next @lex << Space.new
468
+ if SPACE_BYTE[b] && !(b == 0x0d && token.bytesize == 2)
469
+ size = token.bytesize
470
+ (last = @lex[-1]).is_a?(Space) and next last.size += size
471
+ next @lex << Space.new(size)
427
472
  end
428
473
 
429
- next @lex << EOL if newline
474
+ next @lex << EOL if b == 0x0a || b == 0x0d
430
475
 
431
- next @lex << Osc.new(osc) if osc
476
+ if (c = token.getbyte(1)) == 0x5d # Osc
477
+ next @lex << Osc.new(token)
478
+ end
479
+ if c != 0x5b # Csi
480
+ # a bare escape is just text
481
+ (last = @lex[-1]).is_a?(Word) and next last.add(token)
482
+ next @lex << Word.new(token)
483
+ end
432
484
 
433
- # Handle csi...
434
- if csi == "\e[m" || csi == "\e[0m"
485
+ # Handle Csi...
486
+ if token == "\e[m" || token == "\e[0m"
435
487
  next if csis == 0
436
488
 
437
489
  if @lex[-1].is_a?(Csi)
@@ -443,21 +495,17 @@ module Terminal
443
495
  next @lex << CsiEnd
444
496
  end
445
497
 
446
- (last = @lex[-1]).is_a?(Csi) and next last.add(csi)
498
+ (last = @lex[-1]).is_a?(Csi) and next last.add(token)
447
499
 
448
500
  csis += 1
449
- @lex << Csi.new(csi)
501
+ @lex << Csi.new(token)
450
502
  end
451
503
 
452
504
  @lex.pop if (last = @lex[-1]) == EOL
453
505
 
454
506
  next @lex << EOP if csis == 0
455
507
 
456
- if last.is_a?(Csi) && csis == 1
457
- @lex.pop
458
- else
459
- @lex << CsiEnd
460
- end
508
+ last.is_a?(Csi) && csis == 1 ? @lex.pop : @lex << CsiEnd
461
509
  @lex << EOP
462
510
  end
463
511
 
@@ -510,34 +558,58 @@ module Terminal
510
558
  # @private
511
559
  class Space
512
560
  attr_accessor :size
513
- def to_str = (' ' * @size)
514
- def initialize = (@size = 1)
561
+ def to_str = (@size == 1 ? ' ' : ' ' * @size)
562
+ def initialize(size = 1) = (@size = size)
515
563
  def inc = (@size += 1)
516
564
  def inspect = @size == 1 ? '<Space>' : "<Space #{@size}>"
517
565
  end
518
566
 
519
567
  # @private
568
+ # A chunk is either a single grapheme cluster or a run of printable
569
+ # ASCII, for which the display width equals the character count.
520
570
  class Word
521
- def to_str = (@to_str ||= @chars.join)
522
- def size = (@size ||= @sizes.sum)
523
- def inspect = "<Word #{@sizes.sum}:#{@chars.join.inspect}>"
524
-
525
- def initialize(char, size = Text.char_width(char))
526
- @chars = [char]
571
+ def to_str = (@to_str ||= @chunks.size == 1 ? @chunks[0] : @chunks.join)
572
+ def size = (@size ||= @sizes.size == 1 ? @sizes[0] : @sizes.sum)
573
+ def inspect = "<Word #{@sizes.sum}:#{@chunks.join.inspect}>"
574
+
575
+ # `run` marks a chunk holding more than one character; only the lexer
576
+ # creates those and it knows without having to inspect the chunk again
577
+ def initialize(chunk, size = Text.char_width(chunk), run = false)
578
+ @chunks = [chunk]
527
579
  @sizes = [size]
580
+ @runs = run
528
581
  end
529
582
 
530
- def add(char, size = Text.char_width(char))
531
- @chars << char
583
+ def add(chunk, size = Text.char_width(chunk), run = false)
584
+ @chunks << chunk
532
585
  @sizes << size
586
+ @runs ||= run
533
587
  nil
534
588
  end
535
589
 
536
590
  def split(width)
537
- return [self] if @chars.size == 1
591
+ if @runs
592
+ # ASCII runs have to become single characters again to be split -
593
+ # a multi-character grapheme cluster must stay untouched
594
+ chars = []
595
+ sizes = []
596
+ @chunks.each_with_index do |chunk, idx|
597
+ if chunk.bytesize > 1 && chunk.getbyte(0) < 0x80 &&
598
+ chunk.ascii_only?
599
+ chunk.each_char { chars << it and sizes << 1 }
600
+ else
601
+ chars << chunk
602
+ sizes << @sizes[idx]
603
+ end
604
+ end
605
+ else
606
+ chars = @chunks
607
+ sizes = @sizes
608
+ end
609
+ return [self] if chars.size == 1
538
610
  ret = last = size = nil
539
- @chars.each_with_index do |char, idx|
540
- csize = @sizes[idx]
611
+ chars.each_with_index do |char, idx|
612
+ csize = sizes[idx]
541
613
  next ret = [last = Word.new(char, size = csize)] unless ret
542
614
  next last.add(char, csize) if (size += csize) <= width
543
615
  ret << (last = Word.new(char, size = csize))
@@ -568,7 +640,7 @@ module Terminal
568
640
  class << self
569
641
  attr_reader :to_str, :size, :inspect
570
642
  end
571
- @to_str = "\e[m"
643
+ @to_str = Ansi::RESET
572
644
  @size = 0
573
645
  @inspect = '<CsiEnd>'
574
646
  end
@@ -584,22 +656,43 @@ module Terminal
584
656
 
585
657
  ENCODING = Encoding::UTF_8
586
658
 
587
- SPACE_CACHE =
659
+ space_cache =
660
+ Hash.new { |h, s| h[s] = s < 1 ? '' : ' ' * s }.compare_by_identity
661
+ space_cache[0]
662
+ space_cache[1]
663
+ space_cache[2]
664
+ SPACE_CACHE = space_cache.freeze
665
+
666
+ # A run of printable ASCII is only taken when the following character is
667
+ # ASCII too: everything which can extend a grapheme cluster (combining
668
+ # marks, ZWJ, variation selectors, ...) is non-ASCII, so a run can never
669
+ # swallow the base of a cluster `\X` would have kept together.
670
+ SCAN_REGEX =
671
+ /
672
+ [\x21-\x7e]+(?=[\x00-\x7f]|\z)
673
+ | \x20+
674
+ | \r?\n
675
+ | \e\[[\x30-\x3f]*[\x20-\x2f]*[a-zA-Z]
676
+ | \e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\)
677
+ | \s
678
+ | \X
679
+ /x
680
+
681
+ SPACE_BYTE =
588
682
  Hash
589
- .new { |h, s| h[s] = s < 1 ? '' : ' ' * s }
683
+ .new(false)
590
684
  .compare_by_identity
685
+ .merge!(
686
+ 0x20 => true,
687
+ 0x09 => true,
688
+ 0x0b => true,
689
+ 0x0c => true,
690
+ 0x0d => true
691
+ )
591
692
  .freeze
592
693
 
593
- SCAN_REGEX =
594
- /\G(?:
595
- (\r?\n)
596
- | (\s)
597
- | (\e\[[\x30-\x3f]*[\x20-\x2f]*[a-zA-Z])
598
- | (\e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\))
599
- | (\X)
600
- )/x
601
-
602
694
  private_constant(
695
+ :SPACE_BYTE,
603
696
  :Space,
604
697
  :Word,
605
698
  :Osc,
data/lib/terminal/text.rb CHANGED
@@ -28,8 +28,14 @@ module Terminal
28
28
  # Terminal::Text.ambiguous_char_width # => 1
29
29
  # Terminal::Text.ambiguous_char_width = 2 # for CJK terminals
30
30
  #
31
- # @return [Integer] default: +1+
32
- attr_accessor :ambiguous_char_width
31
+ # @return [Integer] default: `1`
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
  #
@@ -206,66 +212,66 @@ module Terminal
206
212
  def char_width(char)
207
213
  ord = char.ord
208
214
  return @ctrlchar_width[ord] if ord < 0x20
209
- if char.size == 1
210
- return ord < 0xa1 ? 1 : CharWidth[ord] || @ambiguous_char_width
211
- end
215
+ # CharWidth knows this rule too - a comparison just beats a memo hit
216
+ return ord < 0xa1 ? 1 : CharWidth[ord] if char.bytesize == 1
217
+ return 2 if ord == 0x1f3f3 && @very_special_flags.include?(char)
212
218
  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
219
+ skip = false
220
+ char.each_codepoint do |cp|
221
+ next skip = false if skip
222
+ next skip = true if cp == 0x200d # zero width joiner
223
+ sum += CharWidth[cp]
219
224
  end
220
225
  sum
221
226
  end
222
227
  end
223
228
 
224
- @ambiguous_char_width = 1
229
+ @very_special_flags = [
230
+ "🏳\u{FE0F}\u{200D}🌈", # rainbow flag
231
+ "🏳\u{FE0F}\u{200D}⚧\u{FE0F}" # transgender flag
232
+ ].freeze
225
233
 
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
234
+ # indexed by ordinal, only ever asked for control characters
235
+ @ctrlchar_width = [
236
+ 0,
237
+ 1,
238
+ 1,
239
+ 1,
240
+ 1,
241
+ 0,
242
+ 1,
243
+ 0,
244
+ 0,
245
+ 1,
246
+ 0,
247
+ 0,
248
+ 0,
249
+ 0,
250
+ 0,
251
+ 0,
252
+ 1,
253
+ 1,
254
+ 1,
255
+ 1,
256
+ 1,
257
+ 1,
258
+ 1,
259
+ 1,
260
+ 1,
261
+ 1,
262
+ 1,
263
+ 1,
264
+ 1,
265
+ 1,
266
+ 1,
267
+ 1
268
+ ].freeze
269
+
270
+ @ambiguous_char_width = 1
265
271
 
266
- cw_file = "#{__dir__}/text/char_width.rb"
267
- autoload :CharWidth, cw_file
268
- autoload :UNICODE_VERSION, cw_file
272
+ char_width_file = "#{__dir__}/text/char_width.rb"
273
+ autoload :CharWidth, char_width_file
274
+ autoload :UNICODE_VERSION, char_width_file
269
275
  private_constant :CharWidth
270
276
  end
271
277
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Terminal
4
4
  # The version number of the gem.
5
- VERSION = '1.0.5'
5
+ VERSION = '1.0.8'
6
6
  end
data/lib/terminal.rb CHANGED
@@ -30,32 +30,32 @@ module Terminal
30
30
  # Detect the terminal emulator application.
31
31
  #
32
32
  # Known applications:
33
- # +:alacritty+,
34
- # +:amiga+,
35
- # +:code_edit+,
36
- # +:dg_unix+,
37
- # +:docker+,
38
- # +:fluent+,
39
- # +:hpterm+,
40
- # +:hyper+,
41
- # +:iterm+,
42
- # +:kitty+,
43
- # +:macos+,
44
- # +:mintty+,
45
- # +:ms_terminal+,
46
- # +:ncr260+,
47
- # +:nsterm+,
48
- # +:terminator+,
49
- # +:terminology+,
50
- # +:termite+,
51
- # +:vscode+,
52
- # +:vt100+,
53
- # +:warp+,
54
- # +:wyse+,
55
- # +:xnuppc+
33
+ # `:alacritty`,
34
+ # `:amiga`,
35
+ # `:code_edit`,
36
+ # `:dg_unix`,
37
+ # `:docker`,
38
+ # `:fluent`,
39
+ # `:hpterm`,
40
+ # `:hyper`,
41
+ # `:iterm`,
42
+ # `:kitty`,
43
+ # `:macos`,
44
+ # `:mintty`,
45
+ # `:ms_terminal`,
46
+ # `:ncr260`,
47
+ # `:nsterm`,
48
+ # `:terminator`,
49
+ # `:terminology`,
50
+ # `:termite`,
51
+ # `:vscode`,
52
+ # `:vt100`,
53
+ # `:warp`,
54
+ # `:wyse`,
55
+ # `:xnuppc`
56
56
  #
57
- # Any unrecognized +TERM_PROGRAM+ value is converted to a sanitized
58
- # symbol. Returns +nil+ when no terminal can be identified.
57
+ # Any unrecognized `TERM_PROGRAM` value is converted to a sanitized
58
+ # symbol. Returns `nil` when no terminal can be identified.
59
59
  #
60
60
  # @example
61
61
  # Terminal.application # => :kitty
@@ -77,7 +77,7 @@ module Terminal
77
77
  # @param cmd [Array<String>] command and arguments
78
78
  # @param options [Hash] options passed to the shell runner
79
79
  # @return [Array<Process::Status, Array<String>, Array<String>>]
80
- # +[status, stdout_lines, stderr_lines]+
80
+ # `[status, stdout_lines, stderr_lines]`
81
81
  # @example
82
82
  # status, output, error = Terminal.sh('echo', 'hello')
83
83
  # output # => ["hello\n"]
@@ -88,7 +88,7 @@ module Terminal
88
88
  # @param options [Hash] options passed to the shell runner
89
89
  # @yield [line, type] called for each output line
90
90
  # @yieldparam line [String] the output line
91
- # @yieldparam type [Symbol] +:output+ or +:error+
91
+ # @yieldparam type [Symbol] `:output` or `:error`
92
92
  # @return [Process::Status] the exit status
93
93
  # @example
94
94
  # Terminal.sh('make') do |line, type|
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: 1.0.5
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
@@ -60,13 +60,13 @@ metadata:
60
60
  yard.run: yard
61
61
  source_code_uri: https://codeberg.org/mblumtritt/Terminal.rb
62
62
  bug_tracker_uri: https://codeberg.org/mblumtritt/Terminal.rb/issues
63
- documentation_uri: https://rubydoc.info/gems/terminal_rb/1.0.5
63
+ documentation_uri: https://rubydoc.info/gems/terminal_rb/1.0.8
64
64
  rdoc_options: []
65
65
  require_paths:
66
66
  - lib
67
67
  required_ruby_version: !ruby/object:Gem::Requirement
68
68
  requirements:
69
- - - ">"
69
+ - - ">="
70
70
  - !ruby/object:Gem::Version
71
71
  version: '3.4'
72
72
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -75,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  requirements: []
78
- rubygems_version: 4.0.13
78
+ rubygems_version: 4.0.18
79
79
  specification_version: 4
80
80
  summary: Fast terminal access with ANSI, CSIu, mouse events, BBCode, word-wise line
81
81
  break support and much more.