terminal_rb 1.0.5 → 1.0.6

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: dd88e0e1f5665c57303b6540930bb88bc7fc7ba37341161593c47641d83aee5a
4
- data.tar.gz: adde7fd25392299f1bc967d6537fd25fb94016fcfed76812a99c07ef45604765
3
+ metadata.gz: 8f2f93f672f13936c9415cf3a474533df0f5785da3272f3482a02842a0607917
4
+ data.tar.gz: 52a1498c80085ea7667b7641416f406ae8694e02505a0c3201efd5f150f8d986
5
5
  SHA512:
6
- metadata.gz: 3f487a373e5c05c61ef3c8433db0be643ac2cbd590859d67c2cdecbf62f6c91002d8c2ce19f6895f20e78531e2608ddb2a43491f87fea58c519f133df62070bf
7
- data.tar.gz: 6db6da10522f8d94e5e1ff964529b0e2a022618c7edae701ffc89ce9bbdfb4ba5942d288b276112dff718e521d43d4f37736acf1be67049821a3abeabf18e39b
6
+ metadata.gz: 41cfbe3e34fa3db0af51674dc0f70f32dd08fb20d2b3a1040eff2834c65440f917f2ecea021500037658fbcf613373148c8399fdb29b7ea987916e71c570a65d
7
+ data.tar.gz: b6485ac5e2a9ba17ec72ffadc94cad6f5348ab846f885d12e9a68a338c15baeaa0d564ce1e1a4d2f946505887782e02dfd7221fc03e60bd3e7bb40afb88b47a1
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # Terminal.rb v1.0.5
1
+ # Terminal.rb v1.0.6
2
2
 
3
3
  Terminal.rb supports you with input and output on your terminal. Simple [BBCode](https://en.wikipedia.org/wiki/BBCode)-like markup for attributes and coloring, word-wise line breaks, correct special key recognition and mouse event reporting enable you to implement your CLI app quickly and easily.
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/1.0.5/Terminal)
7
+ - Help: [rubydoc.info](https://rubydoc.info/gems/terminal_rb/1.0.6/Terminal)
8
8
 
9
9
  ## Features
10
10
 
@@ -52,7 +52,7 @@ module Terminal
52
52
  # Total number of lines.
53
53
  #
54
54
  # @attribute [r] line_count
55
- # @return [Integer, nil] +nil+ when not already calculated
55
+ # @return [Integer, nil] `nil` when not already calculated
56
56
  def line_count = @buf&.size
57
57
 
58
58
  # Index of the topmost visible line.
@@ -68,7 +68,7 @@ module Terminal
68
68
 
69
69
  # Resize to the current terminal dimensions and redraw.
70
70
  #
71
- # @return [self, nil] +nil+ when resize is not required
71
+ # @return [self, nil] `nil` when resize is not required
72
72
  def resize_to_screen = _resize(*Terminal.size)
73
73
 
74
74
  # Resize to specific dimensions (clamped to terminal bounds)
@@ -76,7 +76,7 @@ module Terminal
76
76
  #
77
77
  # @param rows [Integer] new row count
78
78
  # @param columns [Integer] new column count
79
- # @return [self, nil] +nil+ when resize is not required
79
+ # @return [self, nil] `nil` when resize is not required
80
80
  def resize(rows, columns)
81
81
  _resize(
82
82
  rows.clamp(1, Terminal.rows),
@@ -99,7 +99,7 @@ module Terminal
99
99
 
100
100
  # Scroll to the beginning of the content.
101
101
  #
102
- # @return [self, nil] +nil+ when already on begin
102
+ # @return [self, nil] `nil` when already on begin
103
103
  def begin
104
104
  return draw unless @buf
105
105
  return if @line_top == 0
@@ -109,7 +109,7 @@ module Terminal
109
109
 
110
110
  # Scroll to the end of the content.
111
111
  #
112
- # @return [self, nil] +nil+ when already on end
112
+ # @return [self, nil] `nil` when already on end
113
113
  def end
114
114
  return draw unless @buf
115
115
  idx = @buf.size - @rows_visible
data/lib/terminal/ansi.rb CHANGED
@@ -45,7 +45,7 @@ module Terminal
45
45
  # Generate an ANSI escape sequence from attribute names or color
46
46
  # indices.
47
47
  #
48
- # Accepts symbols (`:bold`, +:red+), strings (`"bold"`, +"#ff0000"+),
48
+ # Accepts symbols (`:bold`, `:red`), strings (`"bold"`, `"#ff0000"`),
49
49
  # or integers for 256-color palette (0-255 foreground, 256-511
50
50
  # background, 512-767 underline color).
51
51
  #
@@ -122,11 +122,11 @@ module Terminal
122
122
  #
123
123
  # @example
124
124
  # Terminal::Ansi.try_convert('bold red') # => "\e[1;31m"
125
- # Terminal::Ansi.try_convert('invalid') # => nil
125
+ # Terminal::Ansi.try_convert('invalid') # => nil
126
126
  #
127
127
  # @param attributes [#to_s] space-separated attribute names
128
128
  # @param separator [String] delimiter for splitting
129
- # @return [String, nil] ANSI escape sequence, or +nil+ if any
129
+ # @return [String, nil] ANSI escape sequence, or `nil` if any
130
130
  # attribute is invalid
131
131
  def try_convert(attributes, separator: ' ')
132
132
  return unless attributes
@@ -168,9 +168,9 @@ module Terminal
168
168
 
169
169
  # Convert BBCode markup to ANSI escape codes.
170
170
  #
171
- # Tags like +[bold]+ are converted to their ANSI equivalents;
172
- # +[/bold]+ or +[/]+ resets. Unknown tags are left unchanged.
173
- # Escape a tag with a backslash: +[\\bold]+ renders as +[bold]+.
171
+ # Tags like `[bold]` are converted to their ANSI equivalents;
172
+ # `[/bold]` or `[/]` resets. Unknown tags are left unchanged.
173
+ # Escape a tag with a backslash: `[\\bold]` renders as `[bold]`.
174
174
  #
175
175
  # @see .unbbcode
176
176
  # @see .plain
@@ -361,7 +361,7 @@ module Terminal
361
361
  # Terminal::Ansi.cursor_pos(1, 1) # home position
362
362
  # Terminal::Ansi.cursor_pos(10, 5) # row 10, column 5
363
363
  #
364
- # @param row [Integer, nil] row number; +nil+ moves to home
364
+ # @param row [Integer, nil] row number; `nil` moves to home
365
365
  # @param column [Integer, nil] column number
366
366
  # @return (see .[])
367
367
  def cursor_pos(row, column = nil)
@@ -396,7 +396,7 @@ module Terminal
396
396
  # Erase part of the screen.
397
397
  #
398
398
  # @param part [Symbol] area to erase:
399
- # +:all+, +:below+, +:above+, or +:scrollback+
399
+ # `:all`, `:below`, `:above`, or `:scrollback`
400
400
  # @return (see .[])
401
401
  def screen_erase(part = :all) = "\e[#{@screen_erase[part]}J"
402
402
 
@@ -449,7 +449,7 @@ module Terminal
449
449
  # Erase part of the current line.
450
450
  #
451
451
  # @param part [Symbol] area to erase:
452
- # +:all+, +:to_end+, or +:to_start+
452
+ # `:all`, `:to_end`, or `:to_start`
453
453
  # @return (see .[])
454
454
  def line_erase(part = :all) = "\e[#{@line_erase[part]}K"
455
455
 
@@ -472,7 +472,7 @@ module Terminal
472
472
  # @see .link_end
473
473
  #
474
474
  # @param url [#to_s] the link URL
475
- # @param params [Hash] optional link parameters (e.g., +id:+)
475
+ # @param params [Hash] optional link parameters (e.g., `id:`)
476
476
  # @return (see .[])
477
477
  def link_start(url, **params)
478
478
  "\e]8;#{params.map { it.join('=') }.join(':')};#{url}\a"
@@ -520,12 +520,12 @@ module Terminal
520
520
  # Terminal.raw_write(Terminal::Ansi.progress(:error)) # error state
521
521
  # Terminal.raw_write(Terminal::Ansi.progress(nil)) # hide
522
522
  #
523
- # @param state [Symbol, Numeric, Boolean] progress state:
524
- # - +:show+ or +true+ to show, `:err`/`:error`, `:warn`/`:warning`,
525
- # +:indeterminate+, a +Numeric+ (0-100) to set percentage, or
523
+ # @param state [Symbol, Numeric, true, false] progress state:
524
+ # - `:show` or `true` to show, `:err`/`:error`, `:warn`/`:warning`,
525
+ # `:indeterminate`, a `Numeric` (0-100) to set percentage, or
526
526
  # any other value to hide
527
- # @param percent [Integer] progress percentage (0-100, used with
528
- # +:show+ state)
527
+ # @param percent [#to_i] progress percentage (0-100, used with
528
+ # `:show` state)
529
529
  # @return (see .[])
530
530
  def progress(state, percent = 0)
531
531
  case state
@@ -563,9 +563,9 @@ module Terminal
563
563
  # @param fracd [Integer, nil] fractional denominator
564
564
  # (must be > fracn, max 15)
565
565
  # @param vertical [Symbol, Integer, nil] vertical alignment:
566
- # +:top+, +:bottom+, +:middle+
566
+ # `:top`, `:bottom`, `:middle`
567
567
  # @param horizontal [Symbol, Integer, nil] horizontal alignment:
568
- # +:left+, +:right+, +:center+
568
+ # `:left`, `:right`, `:center`
569
569
  # @return (see .[])
570
570
  def scale(
571
571
  text,
@@ -6,14 +6,13 @@ module Terminal
6
6
  attr_reader :input_mode
7
7
 
8
8
  def on_key_event(mouse: false, mouse_move: false, focus: false)
9
- raise('already reading key events') if (@in_recursion += 1) != 1
10
9
  return unless block_given?
11
- opts = __input_option(mouse, mouse_move, focus)
10
+ opts = nil
12
11
  STDIN.noecho do
13
- opts &&= @in.syswrite("#{opts}h") ? "#{opts}l" : nil
12
+ opts = __input_options(mouse, mouse_move, focus)
14
13
  while (raw = @in.getch)
15
14
  next yield(KeyEvent[raw]) if raw != "\e"
16
- while String === (nc = @in.read_nonblock(1, exception: false))
15
+ while (nc = @in.read_nonblock(1, exception: false)).is_a?(String)
17
16
  raw << nc
18
17
  end
19
18
  next yield(KeyEvent[raw]) if raw.rindex("\e") < 2
@@ -25,13 +24,15 @@ module Terminal
25
24
  __input_error
26
25
  false
27
26
  ensure
28
- @in_recursion -= 1
29
- @in.syswrite(opts) if opts && @in
27
+ if opts
28
+ @in_opts.pop
29
+ @in&.syswrite(opts)
30
+ end
30
31
  end
31
32
 
32
33
  private
33
34
 
34
- def __input_option(mouse, mouse_move, focus)
35
+ def __input_options(mouse, mouse_move, focus)
35
36
  opts = (mouse ? ['1000'] : [])
36
37
  # highlight: '1001'
37
38
  # drag: '1002'
@@ -41,7 +42,19 @@ module Terminal
41
42
  # sgr: '1006'
42
43
  # urxvt: '1015'
43
44
  # pixel: '1016'
44
- "\e[?#{opts.join(';')};1006" unless opts.empty?
45
+ if (last = @in_opts[-1])
46
+ if opts.empty?
47
+ @in.syswrite("#{last}l")
48
+ return "#{last}h"
49
+ end
50
+ @in_opts << (opts = "\e[?#{opts.join(';')};1006")
51
+ @in.syswrite("#{last}l#{opts}h")
52
+ return "#{opts}l#{last}h"
53
+ end
54
+ return if opts.empty?
55
+ @in_opts << (opts = "\e[?#{opts.join(';')};1006")
56
+ @in.syswrite("#{opts}h")
57
+ "#{opts}l"
45
58
  end
46
59
  end
47
60
 
@@ -5,8 +5,7 @@ module Terminal
5
5
  module DumpInput
6
6
  def input_mode = :dumb
7
7
 
8
- def on_key_event(*_)
9
- raise('already reading key events') if (@in_recursion += 1) != 1
8
+ def on_key_event(*)
10
9
  return unless block_given?
11
10
  while (raw = STDIN.getc)
12
11
  opts = dumb_keys[raw.ord] if raw.size == 1
@@ -17,8 +16,6 @@ module Terminal
17
16
  rescue IOError, SystemCallError
18
17
  __input_error
19
18
  false
20
- ensure
21
- @in_recursion -= 1
22
19
  end
23
20
 
24
21
  private
@@ -23,8 +23,8 @@ module Terminal
23
23
  class KeyEvent
24
24
  # The key identifier.
25
25
  #
26
- # @return [Symbol, String, nil] a named key like +:Enter+, +:Tab+,
27
- # +:MBLeft+ (mouse), or a character string like +"a"+; +nil+ for
26
+ # @return [Symbol, String, nil] a named key like `:Enter`, `:Tab`,
27
+ # `:MBLeft` (mouse), or a character string like `"a"`; `nil` for
28
28
  # unknown sequences
29
29
  attr_reader :key
30
30
 
@@ -61,8 +61,8 @@ module Terminal
61
61
 
62
62
  # Mouse position when this is a mouse event.
63
63
  #
64
- # @return [Array<Integer, Integer>, nil] +[row, column]+ for mouse
65
- # events, +nil+ for keyboard events
64
+ # @return [Array<Integer, Integer>, nil] `[row, column]` for mouse
65
+ # events, `nil` for keyboard events
66
66
  attr_reader :position
67
67
 
68
68
  # The raw input sequence as received from the terminal.
@@ -85,8 +85,8 @@ module Terminal
85
85
  # @private
86
86
  # Destructuring-friendly array representation.
87
87
  #
88
- # @return [Array<String>] +[raw]+ if {#simple?}
89
- # @return [Array<String, String>] +[raw, name]+ otherwise
88
+ # @return [Array<String>] `[raw]` if {#simple?}
89
+ # @return [Array<String, String>] `[raw, name]` otherwise
90
90
  def to_ary = simple? ? [@raw] : [@raw, @name]
91
91
 
92
92
  # @return [String] the event {#name}
@@ -140,7 +140,7 @@ module Terminal
140
140
  @names ||=
141
141
  (@csiu.values + @csi.values + @ss3.values)
142
142
  .uniq
143
- .keep_if { Symbol === it }
143
+ .keep_if { it.is_a?(Symbol) }
144
144
  .sort!
145
145
  ).dup
146
146
  end
@@ -15,7 +15,7 @@ module Terminal
15
15
  # Terminal.input_mode # => :csi_u
16
16
  #
17
17
  # @attribute [r] input_mode
18
- # @return [Symbol] +:csi_u+, +:legacy+, +:dumb+, or +:error+
18
+ # @return [Symbol] `:csi_u`, `:legacy`, `:dumb`, or `:error`
19
19
 
20
20
  #
21
21
  # @!endgroup
@@ -42,8 +42,7 @@ module Terminal
42
42
  # @param focus [true, false] enable terminal focus/unfocus events
43
43
  # @yield [event] called for each input event
44
44
  # @yieldparam event [KeyEvent] the parsed key event
45
- # @return [nil, false] +false+ on I/O error
46
- # @raise [RuntimeError] if already inside a key event loop
45
+ # @return [nil, false] `false` on I/O error
47
46
 
48
47
  # @!method self.read_key_event
49
48
  #
@@ -53,7 +52,7 @@ module Terminal
53
52
  # event = Terminal.read_key_event
54
53
  # puts "You pressed: #{event.name}"
55
54
  #
56
- # @return [KeyEvent, false] the next key event, or +false+ on error
55
+ # @return [KeyEvent, false] the next key event, or `false` on error
57
56
 
58
57
  #
59
58
  # @!endgroup
@@ -62,10 +61,10 @@ module Terminal
62
61
  # @private
63
62
  module Input
64
63
  def input_mode
65
- @in_recursion = 0
66
64
  case @input_mode = __find_input_mode
67
65
  when :legacy, :csi_u
68
66
  @in = IO.console
67
+ @in_opts = []
69
68
  require_relative('input/ansi')
70
69
  extend AnsiInput
71
70
  when :dumb
@@ -105,7 +104,7 @@ module Terminal
105
104
  con = IO.console
106
105
  STDIN.noecho do
107
106
  return :legacy if con.syswrite("\e[>1u\e[?u\e[c") != 12
108
- inp = +''
107
+ inp = ''.b
109
108
  inp << con.getch until inp.rindex('c')
110
109
  return :legacy unless inp.include?("\e[?1u")
111
110
  end
@@ -84,6 +84,7 @@ module Terminal
84
84
  suffix: nil
85
85
  )
86
86
  objects.flatten!
87
+ return @out.puts if objects.empty?
87
88
  @out.puts(
88
89
  Text::Formatter.format(
89
90
  *objects,
@@ -67,13 +67,14 @@ module Terminal
67
67
  suffix: nil
68
68
  )
69
69
  objects.flatten!
70
+ return @out.puts if objects.empty?
70
71
  @out.puts(
71
72
  Text::Formatter.format(
72
73
  *objects,
73
74
  ansi: false,
74
75
  bbcode:,
75
76
  spaces:,
76
- eol: eol,
77
+ eol:,
77
78
  align:,
78
79
  width:,
79
80
  height:,
@@ -66,7 +66,7 @@ module Terminal
66
66
  #
67
67
  # The terminal size.
68
68
  #
69
- # @return [Array<Integer, Integer>] +[rows, columns]+
69
+ # @return [Array<Integer, Integer>] `[rows, columns]`
70
70
 
71
71
  # Terminal width in columns.
72
72
  #
@@ -89,7 +89,7 @@ module Terminal
89
89
  # Current cursor position.
90
90
  # This is only available when ANSI is supported ({ansi?} return true).
91
91
  #
92
- # @return [Array<Integer, Integer>, nil] +[row, column]+ or +nil+ if
92
+ # @return [Array<Integer, Integer>, nil] `[row, column]` or `nil` if
93
93
  # unavailable
94
94
 
95
95
  # Whether the terminal has been resized since the last size query.
@@ -113,7 +113,7 @@ module Terminal
113
113
  # @example
114
114
  # Terminal << '[bold]Hello[/bold] World'
115
115
  #
116
- # @param object [#to_s, nil] the object to output; +nil+ is ignored
116
+ # @param object [#to_s, nil] the object to output; `nil` is ignored
117
117
  # @return [self]
118
118
 
119
119
  # @!method print(*objects, bbcode: true)
@@ -162,7 +162,7 @@ module Terminal
162
162
  # processing.
163
163
  #
164
164
  # @param object [#to_s] object to write
165
- # @return [Integer, nil] bytes written, or +nil+ on error
165
+ # @return [Integer, nil] bytes written, or `nil` on error
166
166
 
167
167
  # @!method hide_cursor
168
168
  #
@@ -4,9 +4,9 @@ require 'stringio'
4
4
 
5
5
  # RSpec shared context for testing code that uses Terminal.rb.
6
6
  #
7
- # Stubs all Terminal I/O methods and provides +stdout+, +stdin+, and
8
- # +stdoutstr+ test helpers. Output is captured into the +stdout+ array;
9
- # input is read from the +stdin+ array.
7
+ # Stubs all Terminal I/O methods and provides `stdout`, `stdin`, and
8
+ # `stdoutstr` test helpers. Output is captured into the `stdout` array;
9
+ # input is read from the `stdin` array.
10
10
  #
11
11
  # @example Basic usage
12
12
  # RSpec.describe MyClass do
@@ -22,15 +22,15 @@ require 'stringio'
22
22
  # include_context 'with Terminal.rb', ansi: false, colors: 8,
23
23
  # size: [40, 120]
24
24
  #
25
- # @param ansi [true, false] mock ANSI support (default: +true+)
25
+ # @param ansi [true, false] mock ANSI support (default: `true`)
26
26
  # @param application [Symbol] mock terminal application
27
- # (default: +:kitty+)
28
- # @param colors [Integer, Symbol] mock color depth; use +:true_color+
29
- # for 16777216 (default: +256+)
27
+ # (default: `:kitty`)
28
+ # @param colors [Integer, Symbol] mock color depth; use `:true_color`
29
+ # for 16777216 (default: `256`)
30
30
  # @param size [Array<Integer, Integer>] mock terminal size as
31
- # +[rows, columns]+ (default: +[25, 80]+)
31
+ # `[rows, columns]` (default: `[25, 80]`)
32
32
  # @param pos [Array<Integer, Integer>] mock cursor position as
33
- # +[row, column]+ (default: +[1, 1]+)
33
+ # `[row, column]` (default: `[1, 1]`)
34
34
  RSpec.shared_context 'with Terminal.rb' do |ansi: true, application: :kitty, colors: 256, size: [25, 80], pos: [1, 1]|
35
35
  let(:stdout) { StringIO.new }
36
36
  let(:stdout_lines) { stdout.string.lines(chomp: true) }
@@ -77,7 +77,7 @@ module Terminal
77
77
  return unless obj
78
78
  return copy_writer(obj) if obj.respond_to?(:readpartial)
79
79
  return copy_writer(obj.to_io) if obj.respond_to?(:to_io)
80
- return array_writer(obj) if Array === obj
80
+ return array_writer(obj) if obj.is_a?(Array)
81
81
  if obj.respond_to?(:each)
82
82
  return enum_writer(obj.enum_for(:each)) if obj.respond_to?(:enum_for)
83
83
  return enum_writer(Enumerator.new { |y| obj.each { y << it } })
@@ -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
 
@@ -510,7 +516,7 @@ module Terminal
510
516
  # @private
511
517
  class Space
512
518
  attr_accessor :size
513
- def to_str = (' ' * @size)
519
+ def to_str = (@size == 1 ? ' ' : ' ' * @size)
514
520
  def initialize = (@size = 1)
515
521
  def inc = (@size += 1)
516
522
  def inspect = @size == 1 ? '<Space>' : "<Space #{@size}>"
@@ -568,7 +574,7 @@ module Terminal
568
574
  class << self
569
575
  attr_reader :to_str, :size, :inspect
570
576
  end
571
- @to_str = "\e[m"
577
+ @to_str = Ansi::RESET
572
578
  @size = 0
573
579
  @inspect = '<CsiEnd>'
574
580
  end
@@ -584,11 +590,12 @@ module Terminal
584
590
 
585
591
  ENCODING = Encoding::UTF_8
586
592
 
587
- SPACE_CACHE =
588
- Hash
589
- .new { |h, s| h[s] = s < 1 ? '' : ' ' * s }
590
- .compare_by_identity
591
- .freeze
593
+ space_cache =
594
+ Hash.new { |h, s| h[s] = s < 1 ? '' : ' ' * s }.compare_by_identity
595
+ space_cache[0]
596
+ space_cache[1]
597
+ space_cache[2]
598
+ SPACE_CACHE = space_cache.freeze
592
599
 
593
600
  SCAN_REGEX =
594
601
  /\G(?:
data/lib/terminal/text.rb CHANGED
@@ -28,7 +28,7 @@ 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+
31
+ # @return [Integer] default: `1`
32
32
  attr_accessor :ambiguous_char_width
33
33
 
34
34
  # Calculate the display width of a string in terminal columns.
@@ -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.6'
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.6
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.6
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.15
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.