terminal_rb 0.6.0 → 0.9.0
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 +4 -4
- data/README.md +14 -3
- data/examples/info.rb +5 -5
- data/lib/terminal/ansi.rb +35 -18
- data/lib/terminal/detect.rb +21 -20
- data/lib/terminal/text.rb +115 -161
- data/lib/terminal/version.rb +1 -1
- data/lib/terminal.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 351b0ba282f1686000796ca789653308c722d201286ea7e1e6b99d2802db2b21
|
4
|
+
data.tar.gz: c25af6f120fc06e991b7f2a5f616141ac44d99a72a7d4569228d7822daa730a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31c49a47f6bf38aa08cb8e75e85fe5180d7d676b737392b38e52baebf1ff7669d9fb76d1037bfdb1e13a5683b36a434e41b4001ef2dfc56692ed1229cc7f044d
|
7
|
+
data.tar.gz: 2ba822e7bc9448d577f6f6649abb8b6c8f6fb9c44a76c86d9c9595c78cfd96e9dbda1451d6617e5c180e19a1c40dd0b7b09392fc1894dd3dbe858b7ab526c6da
|
data/README.md
CHANGED
@@ -19,17 +19,28 @@ Terminal access with support for ANSI control codes and [BBCode-like](https://en
|
|
19
19
|
|
20
20
|
## Examples
|
21
21
|
|
22
|
-
### Check
|
22
|
+
### Check whether ANSI is supported
|
23
23
|
|
24
24
|
```ruby
|
25
25
|
Terminal.ansi?
|
26
26
|
# => true when current terminal emulator supports ANSI control codes
|
27
27
|
```
|
28
28
|
|
29
|
-
### Print
|
29
|
+
### Print embedded formatting
|
30
30
|
|
31
31
|
```ruby
|
32
32
|
Terminal.puts "[red on_bright_yellow bold]Hello World![/]"
|
33
|
+
# when terminal supports ANSI
|
34
|
+
# => prints "\e[31;103;1mHello World!\e[m"
|
35
|
+
# when terminal does not support ANSI
|
36
|
+
# => prints "Hello World"
|
37
|
+
```
|
38
|
+
|
39
|
+
### Calculate display width of a string
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
Terminal::Text.width('ライブラリは中国語、日本語、韓国語のテキストをサポートしています')
|
43
|
+
# => 64
|
33
44
|
```
|
34
45
|
|
35
46
|
Have a look at the [examples](./examples/) directory to learn from code.
|
@@ -42,7 +53,7 @@ You can install the gem in your system with
|
|
42
53
|
gem install terminal_rb
|
43
54
|
```
|
44
55
|
|
45
|
-
or you can use [Bundler](http://gembundler.com/) to add Terminal to your own project:
|
56
|
+
or you can use [Bundler](http://gembundler.com/) to add Terminal.rb to your own project:
|
46
57
|
|
47
58
|
```shell
|
48
59
|
bundle add terminal_rb
|
data/examples/info.rb
CHANGED
@@ -6,10 +6,10 @@ Terminal.puts <<~TEXT
|
|
6
6
|
|
7
7
|
✅ [b bright_green]Terminal.rb[/b] — Terminal Info:[/]
|
8
8
|
|
9
|
-
Ansi mode: #{Terminal.ansi? ? '✓' : '𐄂'}
|
10
|
-
Application: #{Terminal.application}
|
11
|
-
Supported Colors: #{Terminal.colors}#{' (truecolor)' if Terminal.true_color?}
|
12
|
-
Terminal Size: #{Terminal.size.join(' x ')}
|
13
|
-
Cursor Position: #{Terminal.pos
|
9
|
+
Ansi mode: #{Terminal.ansi? ? '[b bright_green]✓' : '[b bright_red]𐄂'}[/]
|
10
|
+
Application: [b bright_blue]#{Terminal.application}[/]
|
11
|
+
Supported Colors: [b]#{Terminal.colors}#{Terminal::Ansi.rainbow(' (truecolor)') if Terminal.true_color?}[/]
|
12
|
+
Terminal Size: [b]#{Terminal.size.join(' x ')}[/]
|
13
|
+
Cursor Position: [b]#{Terminal.pos&.join(', ')}[/]
|
14
14
|
|
15
15
|
TEXT
|
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)
|
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
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
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
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
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)
|
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
|
#
|
data/lib/terminal/detect.rb
CHANGED
@@ -5,31 +5,26 @@ module Terminal
|
|
5
5
|
class << self
|
6
6
|
def application
|
7
7
|
return :kitty if ENV.key?('KITTY_PID')
|
8
|
+
return :alacritty if ENV.key?('ALACRITTY_WINDOW_ID')
|
8
9
|
app_from_term_program || app_from_term
|
9
10
|
end
|
10
11
|
|
11
12
|
def colors
|
12
|
-
|
13
|
-
|
14
|
-
16_777_216
|
13
|
+
if KNOW_APP_WITH_TRUE_COLOR.include?(app_from_term_program) ||
|
14
|
+
(ENV['COLORTERM'] == 'truecolor')
|
15
|
+
return 16_777_216
|
16
|
+
end
|
17
|
+
term = ENV['TERM'] or return 8
|
18
|
+
return 16_777_216 if /[+-]direct/.match?(term)
|
19
|
+
match = /[-+](\d+)color/.match(term) and return match[1].to_i
|
20
|
+
match = /[-+](\d+)bit/.match(term) and return 2**match[1].to_i
|
21
|
+
ret = color_by_name[term] and return ret
|
22
|
+
case term
|
23
|
+
when /^(?:iTerm\s?\d*\.app|nsterm-build\d+|terminology(-[0-9.]+)?)$/
|
24
|
+
256
|
25
|
+
when /^(?:dg\+ccc|dgunix\+ccc|d430.*?[-+](?:dg|unix).*?[-+]ccc)$/
|
26
|
+
52
|
15
27
|
else
|
16
|
-
term = ENV['TERM'] or return 8
|
17
|
-
return 16_777_216 if /[+-]direct/.match?(term)
|
18
|
-
match = /[-+](\d+)color/.match(term) and return match[1].to_i
|
19
|
-
match = /[-+](\d+)bit/.match(term) and return 2**match[1].to_i
|
20
|
-
ret = color_by_name[term] and return ret
|
21
|
-
if /^(
|
22
|
-
iTerm\s?\d*\.app
|
23
|
-
|nsterm-build\d+
|
24
|
-
|terminology(-[0-9.]+)?
|
25
|
-
)$/x.match?(
|
26
|
-
term
|
27
|
-
)
|
28
|
-
return 256
|
29
|
-
end
|
30
|
-
if /^(dg+ccc|dgunix+ccc|d430.*?[-+](dg|unix).*?[-+]ccc)$/.match?(term)
|
31
|
-
return 52
|
32
|
-
end
|
33
28
|
8
|
34
29
|
end
|
35
30
|
end
|
@@ -46,6 +41,8 @@ module Terminal
|
|
46
41
|
'Hyper' => :hyper,
|
47
42
|
'HyperTerm' => :hyper,
|
48
43
|
'iTerm.app' => :iterm,
|
44
|
+
'rio' => :rio,
|
45
|
+
'Tabby' => :tabby,
|
49
46
|
'Terminus' => :terminus,
|
50
47
|
'tmux' => :tmux,
|
51
48
|
'vscode' => :vscode,
|
@@ -79,6 +76,7 @@ module Terminal
|
|
79
76
|
'wy370' => :wyse,
|
80
77
|
'xnuppc' => :xnuppc
|
81
78
|
}.each_pair { |str, type| return type if value.start_with?(str) }
|
79
|
+
nil
|
82
80
|
end
|
83
81
|
|
84
82
|
def color_by_name
|
@@ -144,6 +142,9 @@ module Terminal
|
|
144
142
|
'dummy' => 2
|
145
143
|
}
|
146
144
|
end
|
145
|
+
|
146
|
+
KNOW_APP_WITH_TRUE_COLOR = %i[kitty ghostty vscode iterm].freeze
|
147
|
+
private_constant :KNOW_APP_WITH_TRUE_COLOR
|
147
148
|
end
|
148
149
|
end
|
149
150
|
|
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,39 +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 +=
|
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
43
|
#
|
42
|
-
# @param
|
43
|
-
#
|
44
|
-
# @
|
45
|
-
#
|
46
|
-
# @
|
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
|
47
58
|
def each_line(
|
48
59
|
*text,
|
60
|
+
limit: nil,
|
49
61
|
bbcode: true,
|
50
62
|
ansi: true,
|
51
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,
|
52
90
|
limit: nil,
|
53
|
-
|
91
|
+
bbcode: true,
|
92
|
+
ansi: true,
|
93
|
+
ignore_newline: false,
|
54
94
|
&block
|
55
95
|
)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
62
109
|
end
|
110
|
+
alias each_with_size each_line_with_size
|
111
|
+
|
112
|
+
private
|
63
113
|
|
64
|
-
|
65
|
-
# works for UTF-8 chars only!
|
66
|
-
def __char_width(char)
|
114
|
+
def char_width(char)
|
67
115
|
ord = char.ord
|
68
116
|
return CONTROL_CHAR_WIDTH[ord] || 2 if ord < 0x20
|
69
117
|
return 1 if ord < 0xa1
|
@@ -73,127 +121,39 @@ module Terminal
|
|
73
121
|
# Halfwidth Dakuten Handakuten
|
74
122
|
sco == 0xff9e || sco == 0xff9f ? 2 : 1
|
75
123
|
end
|
76
|
-
end
|
77
124
|
|
78
|
-
|
79
|
-
# Internally used by {Text.each_line}.
|
80
|
-
class Wrap
|
81
|
-
# Create a new instance which may support different conditions.
|
82
|
-
#
|
83
|
-
# @param [#to_s, ...] text
|
84
|
-
# text objects to process
|
85
|
-
# @param [true, false] bbcode
|
86
|
-
# whether to interprete embedded BBCode (see {Ansi.bbcode})
|
87
|
-
# @param [true, false] ansi
|
88
|
-
# whether to keep embedded ANSI control codes
|
89
|
-
# @param [true, false] ignore_newline
|
90
|
-
# wheter to ignore embedded line breaks (`"\r\n"` or `"\n"`)
|
91
|
-
def initialize(*text, bbcode: true, ansi: true, ignore_newline: false)
|
92
|
-
@parts = []
|
125
|
+
def each_part(text, bbcode, ansi, ignore_newline)
|
93
126
|
newline = ignore_newline ? :space : :nl
|
94
127
|
text.each do |txt|
|
95
128
|
txt = bbcode ? Ansi.bbcode(txt) : txt.to_s
|
96
|
-
next
|
129
|
+
next yield(:hard_nl) if txt.empty?
|
97
130
|
txt = txt.encode(ENC) if txt.encoding != ENC
|
98
131
|
word = nil
|
99
|
-
txt.scan(
|
100
|
-
|
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
|
101
138
|
word = nil
|
102
|
-
next
|
103
|
-
next
|
139
|
+
next yield(:space) if space
|
140
|
+
next yield(newline) if nl
|
104
141
|
next unless ansi
|
105
|
-
next
|
106
|
-
next
|
107
|
-
|
142
|
+
next yield(:seq, osc) if osc
|
143
|
+
next yield(:seq_end) if csi == "\e[m" || csi == "\e[0m"
|
144
|
+
yield(:seq, csi)
|
108
145
|
end
|
109
|
-
|
146
|
+
yield(word) if word
|
147
|
+
yield(:hard_nl)
|
110
148
|
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Report each line of the text.
|
114
|
-
#
|
115
|
-
# @param [#to_i, nil] limit
|
116
|
-
# optionally limit line size
|
117
|
-
# @param [true, false] with_size
|
118
|
-
# whether to yield each line with it's display width
|
119
|
-
# @yield [String] line when `with_size` is false
|
120
|
-
# @yield [<String, Integer>] line and it's display width
|
121
|
-
# when `with_size` is true
|
122
|
-
# @return [Enumerator] when no block is given
|
123
|
-
# @return [nil] when block is given
|
124
|
-
# @raise ArgumentError when a `limit` less than `1` is given
|
125
|
-
def each_line(limit: nil, with_size: false, &block)
|
126
|
-
unless limit
|
127
|
-
return with_size ? pairs(&block) : lines(&block) if block_given?
|
128
|
-
return to_enum(with_size ? :pairs : :lines)
|
129
|
-
end
|
130
|
-
limit = limit.to_i
|
131
|
-
raise(ArgumentError, "invalid limit - #{limit}") if limit < 1
|
132
|
-
if block_given?
|
133
|
-
return with_size ? pairs_in(limit, &block) : lines_in(limit, &block)
|
134
|
-
end
|
135
|
-
to_enum(with_size ? :pairs_in : :lines_in, limit)
|
136
|
-
end
|
137
|
-
alias each each_line
|
138
|
-
|
139
|
-
# @!visibility private
|
140
|
-
def each_word(with_size: false, &block)
|
141
|
-
return with_size ? word_pairs(&block) : words(&block) if block_given?
|
142
|
-
to_enum(with_size ? :word_pairs : :words)
|
143
|
-
end
|
144
|
-
|
145
|
-
# @!visibility private
|
146
|
-
def to_str
|
147
|
-
str = EMPTY.dup
|
148
|
-
seq = EMPTY.dup
|
149
|
-
@parts.each do |part, opt|
|
150
|
-
next str << part if part.is_a?(Word)
|
151
|
-
next str << ' ' if part == :space
|
152
|
-
|
153
|
-
if part == :nl
|
154
|
-
str << "\n"
|
155
|
-
next str << seq.dup
|
156
|
-
end
|
157
|
-
|
158
|
-
if part == :seq
|
159
|
-
str << opt
|
160
|
-
next seq << opt
|
161
|
-
end
|
162
|
-
|
163
|
-
# :seq_end
|
164
|
-
next if seq.empty?
|
165
|
-
str << "\e[m"
|
166
|
-
seq.clear
|
167
|
-
end
|
168
|
-
str
|
169
|
-
end
|
170
|
-
alias to_s to_str
|
171
|
-
|
172
|
-
# @!visibility private
|
173
|
-
def to_a(limit: nil, with_size: false)
|
174
|
-
each_line(limit: limit, with_size: with_size).to_a
|
175
|
-
end
|
176
|
-
|
177
|
-
# @!visibility private
|
178
|
-
def to_ary = each_line.to_a
|
179
|
-
|
180
|
-
private
|
181
|
-
|
182
|
-
def words
|
183
|
-
@parts.each { yield(_1.to_s) if _1.is_a?(Word) }
|
184
149
|
nil
|
185
150
|
end
|
186
151
|
|
187
|
-
def
|
188
|
-
@parts.each { yield(_1.to_s, _1.size) if _1.is_a?(Word) }
|
189
|
-
nil
|
190
|
-
end
|
191
|
-
|
192
|
-
def lines
|
152
|
+
def lines(text, bbcode, ansi, ignore_newline)
|
193
153
|
current = EMPTY.dup
|
194
154
|
seq = EMPTY.dup
|
195
155
|
lws = nil
|
196
|
-
|
156
|
+
each_part(text, bbcode, ansi, ignore_newline) do |part, opt|
|
197
157
|
if part == :space
|
198
158
|
next if lws
|
199
159
|
current << ' '
|
@@ -232,12 +192,12 @@ module Terminal
|
|
232
192
|
nil
|
233
193
|
end
|
234
194
|
|
235
|
-
def lines_in(limit)
|
195
|
+
def lines_in(text, bbcode, ansi, ignore_newline, limit)
|
236
196
|
current = EMPTY.dup
|
237
197
|
seq = EMPTY.dup
|
238
198
|
width = 0
|
239
199
|
lws = nil
|
240
|
-
|
200
|
+
each_part(text, bbcode, ansi, ignore_newline) do |part, opt|
|
241
201
|
if part == :space
|
242
202
|
next if lws
|
243
203
|
if width.succ < limit
|
@@ -315,12 +275,12 @@ module Terminal
|
|
315
275
|
nil
|
316
276
|
end
|
317
277
|
|
318
|
-
def pairs
|
278
|
+
def pairs(text, bbcode, ansi, ignore_newline)
|
319
279
|
current = EMPTY.dup
|
320
280
|
seq = EMPTY.dup
|
321
281
|
width = 0
|
322
282
|
lws = nil
|
323
|
-
|
283
|
+
each_part(text, bbcode, ansi, ignore_newline) do |part, opt|
|
324
284
|
if part == :space
|
325
285
|
next if lws
|
326
286
|
current << ' '
|
@@ -364,12 +324,12 @@ module Terminal
|
|
364
324
|
nil
|
365
325
|
end
|
366
326
|
|
367
|
-
def pairs_in(limit)
|
327
|
+
def pairs_in(text, bbcode, ansi, ignore_newline, limit)
|
368
328
|
current = EMPTY.dup
|
369
329
|
seq = EMPTY.dup
|
370
330
|
width = 0
|
371
331
|
lws = nil
|
372
|
-
|
332
|
+
each_part(text, bbcode, ansi, ignore_newline) do |part, opt|
|
373
333
|
if part == :space
|
374
334
|
next if lws
|
375
335
|
if width.succ < limit
|
@@ -450,46 +410,40 @@ module Terminal
|
|
450
410
|
end
|
451
411
|
nil
|
452
412
|
end
|
413
|
+
end
|
453
414
|
|
454
|
-
|
455
|
-
attr_reader :to_str, :size, :chars
|
415
|
+
@ambiguous_char_width = 1
|
456
416
|
|
457
|
-
|
458
|
-
|
459
|
-
@size = Text.__char_width(char)
|
460
|
-
@chars = [[char, @size]]
|
461
|
-
end
|
417
|
+
class Word
|
418
|
+
attr_reader :to_str, :size, :chars
|
462
419
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
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
|
469
431
|
end
|
470
|
-
private_constant :Word
|
471
|
-
|
472
|
-
REGEXP =
|
473
|
-
/\G(?:
|
474
|
-
(\r?\n)
|
475
|
-
| (\e\[[\d;:\?]*[ABCDEFGHJKSTfminsuhl])
|
476
|
-
| (\e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\))
|
477
|
-
| (\s+)
|
478
|
-
| (\X)
|
479
|
-
)/x
|
480
|
-
private_constant :REGEXP
|
481
|
-
|
482
|
-
ENC = Encoding::UTF_8
|
483
|
-
private_constant :ENC
|
484
|
-
|
485
|
-
EMPTY = String.new(encoding: ENC).freeze
|
486
|
-
private_constant :EMPTY
|
487
432
|
end
|
433
|
+
private_constant :Word
|
488
434
|
|
489
435
|
ENC = Encoding::UTF_8
|
490
|
-
|
436
|
+
EMPTY = String.new(encoding: ENC).freeze
|
437
|
+
private_constant :ENC, :EMPTY
|
491
438
|
|
492
|
-
|
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
|
493
447
|
|
494
448
|
WIDTH_SCANNER =
|
495
449
|
/\G(?:
|
@@ -498,7 +452,7 @@ module Terminal
|
|
498
452
|
| (\s+)
|
499
453
|
| (\X)
|
500
454
|
)/x
|
501
|
-
private_constant :WIDTH_SCANNER
|
455
|
+
private_constant :SCAN_EXPR, :WIDTH_SCANNER
|
502
456
|
|
503
457
|
CONTROL_CHAR_WIDTH = {
|
504
458
|
0x00 => 0,
|
data/lib/terminal/version.rb
CHANGED
data/lib/terminal.rb
CHANGED
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.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Blumtritt
|
@@ -46,7 +46,7 @@ licenses:
|
|
46
46
|
metadata:
|
47
47
|
source_code_uri: https://codeberg.org/mblumtritt/Terminal.rb
|
48
48
|
bug_tracker_uri: https://codeberg.org/mblumtritt/Terminal.rb/issues
|
49
|
-
documentation_uri: https://rubydoc.info/gems/terminal_rb
|
49
|
+
documentation_uri: https://rubydoc.info/gems/terminal_rb/Terminal
|
50
50
|
rubygems_mfa_required: 'true'
|
51
51
|
rdoc_options: []
|
52
52
|
require_paths:
|