terminal_rb 0.6.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 +7 -0
- data/.yardopts +11 -0
- data/README.md +55 -0
- data/bin/bbcode +46 -0
- data/examples/24bit-colors.rb +20 -0
- data/examples/3bit-colors.rb +18 -0
- data/examples/8bit-colors.rb +32 -0
- data/examples/attributes.rb +14 -0
- data/examples/bbcode.rb +28 -0
- data/examples/info.rb +15 -0
- data/examples/key-codes.rb +22 -0
- data/lib/terminal/ansi/attributes.rb +209 -0
- data/lib/terminal/ansi/named_colors.rb +668 -0
- data/lib/terminal/ansi.rb +593 -0
- data/lib/terminal/detect.rb +151 -0
- data/lib/terminal/input.rb +187 -0
- data/lib/terminal/preload.rb +8 -0
- data/lib/terminal/rspec/helper.rb +33 -0
- data/lib/terminal/text/char_width.rb +2585 -0
- data/lib/terminal/text.rb +542 -0
- data/lib/terminal/version.rb +6 -0
- data/lib/terminal.rb +269 -0
- data/lib/terminal_rb.rb +3 -0
- metadata +68 -0
data/lib/terminal.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'terminal/ansi'
|
4
|
+
require_relative 'terminal/input'
|
5
|
+
|
6
|
+
#
|
7
|
+
# Terminal access with support for ANSI control codes and
|
8
|
+
# [BBCode-like](https://en.wikipedia.org/wiki/BBCode) embedded text attribute
|
9
|
+
# syntax.
|
10
|
+
#
|
11
|
+
# It automagically detects whether your terminal supports ANSI features.
|
12
|
+
#
|
13
|
+
module Terminal
|
14
|
+
class << self
|
15
|
+
# Return true when the current terminal supports ANSI control codes.
|
16
|
+
# When the terminal does not support it, {colors} will return `2` as color
|
17
|
+
# count and all output methods ({<<}, {print}, {puts}) will not forward
|
18
|
+
# ANSI control codes to the terminal.
|
19
|
+
#
|
20
|
+
# @attribute [r] ansi?
|
21
|
+
# @return [Boolean] whether ANSI control codes are supported
|
22
|
+
def ansi? = (@mode == :ansi)
|
23
|
+
|
24
|
+
# Terminal application identifier.
|
25
|
+
#
|
26
|
+
# The detection supports a wide range of terminal emulators but may return
|
27
|
+
# `nil` if an unsupported terminal was found. These are the supported
|
28
|
+
# application IDs:
|
29
|
+
#
|
30
|
+
# - `:alacritty`,
|
31
|
+
# - `:amiga`,
|
32
|
+
# - `:code_edit`,
|
33
|
+
# - `:dg_unix`,
|
34
|
+
# - `:fluent`,
|
35
|
+
# - `:ghostty`,
|
36
|
+
# - `:hpterm`,
|
37
|
+
# - `:hyper`,
|
38
|
+
# - `:iterm`,
|
39
|
+
# - `:macos`,
|
40
|
+
# - `:mintty`,
|
41
|
+
# - `:ms_terminal`,
|
42
|
+
# - `:ncr260`,
|
43
|
+
# - `:nsterm`,
|
44
|
+
# - `:terminator`,
|
45
|
+
# - `:terminology`,
|
46
|
+
# - `:terminus`,
|
47
|
+
# - `:termite`,
|
48
|
+
# - `:tmux`,
|
49
|
+
# - `:vscode`,
|
50
|
+
# - `:vt100`,
|
51
|
+
# - `:warp`,
|
52
|
+
# - `:wezterm`,
|
53
|
+
# - `:wyse`,
|
54
|
+
# - `:xnuppc`
|
55
|
+
#
|
56
|
+
# @attribute [r] application
|
57
|
+
# @return [Symbol, nil] the application identifier
|
58
|
+
def application = (@application ||= Detect.application)
|
59
|
+
|
60
|
+
# Number of supported colors.
|
61
|
+
# The detection checks various conditions to find the correct value. The
|
62
|
+
# most common values are
|
63
|
+
#
|
64
|
+
# - `16_777_216` for 24-bit encoding ({true_color?} return true)
|
65
|
+
# - `256` for 8-Bit encoding
|
66
|
+
# - `52` for some Unix terminals with an extended color palette
|
67
|
+
# - `8` for 3-/4-bit encoding
|
68
|
+
# - `2` if ANSI is not supported in general ({ansi?} return false)
|
69
|
+
#
|
70
|
+
# @attribute [r] colors
|
71
|
+
# @return [Integer] number of supported colors
|
72
|
+
def colors = (@colors ||= ansi? ? Detect.colors : 2)
|
73
|
+
|
74
|
+
# Screen column count.
|
75
|
+
# See {size} for support and detection details.
|
76
|
+
#
|
77
|
+
# @attribute [r] columns
|
78
|
+
# @return [Integer] number of available columns
|
79
|
+
def columns = size[1]
|
80
|
+
|
81
|
+
# @attribute [w] columns
|
82
|
+
def columns=(value)
|
83
|
+
self.size = [rows, value]
|
84
|
+
end
|
85
|
+
|
86
|
+
# Current cursor position.
|
87
|
+
# This is only available when ANSI is supported ({ansi?} return true).
|
88
|
+
#
|
89
|
+
# @attribute [r] pos
|
90
|
+
# @return [[Integer, Integer]] cursor position as rows and columns
|
91
|
+
# @return [nil] for incompatible terminals
|
92
|
+
def pos
|
93
|
+
@con&.cursor
|
94
|
+
rescue IOError
|
95
|
+
@con = nil
|
96
|
+
end
|
97
|
+
|
98
|
+
# @attribute [w] pos
|
99
|
+
def pos=(pos)
|
100
|
+
@con&.cursor = pos
|
101
|
+
rescue IOError
|
102
|
+
@con = nil
|
103
|
+
end
|
104
|
+
|
105
|
+
# Screen row count.
|
106
|
+
# See {size} for support and detection details.
|
107
|
+
#
|
108
|
+
# @attribute [r] rows
|
109
|
+
# @return [Integer] number of available rows
|
110
|
+
def rows = size[0]
|
111
|
+
|
112
|
+
# @attribute [w] rows
|
113
|
+
def rows=(value)
|
114
|
+
self.size = [value, columns]
|
115
|
+
end
|
116
|
+
|
117
|
+
# Screen size as a tuple of {rows} and {columns}.
|
118
|
+
#
|
119
|
+
# If the terminal does not support the report for it's dimension or ANSI
|
120
|
+
# is not supported in general then environment variables will be used.
|
121
|
+
# If this failed `[25, 80]` will be returned as default.
|
122
|
+
#
|
123
|
+
# Setting the terminal size is not widely supported.
|
124
|
+
#
|
125
|
+
# @see rows
|
126
|
+
# @see columns
|
127
|
+
#
|
128
|
+
# @attribute [r] size
|
129
|
+
# @return [[Integer, Integer]] available screen size as rows and columns
|
130
|
+
def size
|
131
|
+
@size ||= @inf&.winsize || _default_size
|
132
|
+
rescue IOError
|
133
|
+
@inf = nil
|
134
|
+
@size = _default_size
|
135
|
+
end
|
136
|
+
|
137
|
+
# @attribute [w] size
|
138
|
+
def size=(size)
|
139
|
+
@inf&.winsize = size
|
140
|
+
rescue IOError
|
141
|
+
@inf = nil
|
142
|
+
end
|
143
|
+
|
144
|
+
# @see colors
|
145
|
+
# @attribute [r] true_color?
|
146
|
+
# @return [Boolean] whether true colors are supported
|
147
|
+
def true_color? = (colors == 16_777_216)
|
148
|
+
|
149
|
+
# Hide the cursor.
|
150
|
+
# Will not send the control code if the cursor is already hidden.
|
151
|
+
#
|
152
|
+
# To show the cursor again call {show_cursor}.
|
153
|
+
#
|
154
|
+
# @return [Terminal] itself
|
155
|
+
def hide_cursor
|
156
|
+
_write(Ansi::CURSOR_HIDE) if ansi? && (@cc += 1) == 1
|
157
|
+
self
|
158
|
+
end
|
159
|
+
|
160
|
+
# Show the cursor.
|
161
|
+
# Will not send the control code if the cursor is not hidden.
|
162
|
+
#
|
163
|
+
# When you called {hide_cursor} n-times you need to call {show_cursor}
|
164
|
+
# n-times to show the cursor again.
|
165
|
+
#
|
166
|
+
# @return [Terminal] itself
|
167
|
+
def show_cursor
|
168
|
+
_write(Ansi::CURSOR_SHOW) if @cc > 0 && (@cc -= 1).zero?
|
169
|
+
self
|
170
|
+
end
|
171
|
+
|
172
|
+
# Writes the given object to the terminal.
|
173
|
+
# Interprets embedded BBCode.
|
174
|
+
#
|
175
|
+
# @param [#to_s] object object to write
|
176
|
+
# @return [Terminal] itself
|
177
|
+
def <<(object)
|
178
|
+
@out.write(@bbcode[object]) unless object.nil? || @out.nil?
|
179
|
+
self
|
180
|
+
rescue IOError
|
181
|
+
@out = nil
|
182
|
+
self
|
183
|
+
end
|
184
|
+
|
185
|
+
# Writes the given objects to the terminal.
|
186
|
+
# Optionally interprets embedded BBCode.
|
187
|
+
#
|
188
|
+
# @param [Array<#to_s>] objects any number of objects to write
|
189
|
+
# @param [true|false] bbcode whether to interpret embedded BBCode
|
190
|
+
# @return [nil]
|
191
|
+
def print(*objects, bbcode: true)
|
192
|
+
return unless @out
|
193
|
+
bbcode = bbcode ? @bbcode : @nobbcode
|
194
|
+
objects.flatten.each { @out.write(bbcode[_1]) unless _1.nil? }
|
195
|
+
nil
|
196
|
+
rescue IOError
|
197
|
+
@out = nil
|
198
|
+
end
|
199
|
+
|
200
|
+
# Writes the given objects to the terminal.
|
201
|
+
# Writes a newline after each objects that does not already end with a
|
202
|
+
# newline sequence in it's String represenation.
|
203
|
+
# If called without any arguments, writes a newline only.
|
204
|
+
#
|
205
|
+
# Optionally interprets embedded BBCode.
|
206
|
+
#
|
207
|
+
# @param (see print)
|
208
|
+
# @return (see print)
|
209
|
+
def puts(*objects, bbcode: true)
|
210
|
+
return unless @out
|
211
|
+
objects.flatten!
|
212
|
+
if objects.empty?
|
213
|
+
@out.write("\n")
|
214
|
+
return
|
215
|
+
end
|
216
|
+
bbcode = bbcode ? @bbcode : @nobbcode
|
217
|
+
objects.each do |s|
|
218
|
+
next @out.write("\n") if s.nil?
|
219
|
+
@out.write(s = bbcode[s])
|
220
|
+
@out.write("\n") if s[-1] != "\n"
|
221
|
+
end
|
222
|
+
nil
|
223
|
+
rescue IOError
|
224
|
+
@out = nil
|
225
|
+
end
|
226
|
+
|
227
|
+
private
|
228
|
+
|
229
|
+
def _write(str)
|
230
|
+
@out&.write(str)
|
231
|
+
rescue IOError
|
232
|
+
@out = nil
|
233
|
+
end
|
234
|
+
|
235
|
+
def _default_size
|
236
|
+
rows = ENV['LINES'].to_i
|
237
|
+
columns = ENV['COLUMNS'].to_i
|
238
|
+
[rows > 0 ? rows : 25, columns > 0 ? columns : 80]
|
239
|
+
end
|
240
|
+
|
241
|
+
def _determine_mode
|
242
|
+
# order is important:
|
243
|
+
return :dumb unless STDOUT.tty?
|
244
|
+
ENV.key?('NO_COLOR') || ENV['TERM'] == 'dumb' ? :dumb : :ansi
|
245
|
+
rescue IOError
|
246
|
+
nil
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
@mode = _determine_mode
|
251
|
+
@out = STDOUT if @mode
|
252
|
+
@cc = 0
|
253
|
+
|
254
|
+
if ansi?
|
255
|
+
@bbcode = ->(s) { Ansi.bbcode(s) }
|
256
|
+
@nobbcode = lambda(&:to_s)
|
257
|
+
@inf = STDOUT
|
258
|
+
@con = IO.console
|
259
|
+
Signal.trap('WINCH') { @size = nil } if Signal.list.key?('WINCH')
|
260
|
+
else
|
261
|
+
@bbcode = ->(s) { Ansi.plain(s) }
|
262
|
+
@nobbcode = ->(s) { Ansi.undecorate(s) }
|
263
|
+
end
|
264
|
+
|
265
|
+
dir = "#{__dir__}/terminal"
|
266
|
+
autoload :Text, "#{dir}/text.rb"
|
267
|
+
autoload :Detect, "#{dir}/detect.rb"
|
268
|
+
private_constant :Detect
|
269
|
+
end
|
data/lib/terminal_rb.rb
ADDED
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: terminal_rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Blumtritt
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies: []
|
12
|
+
description: |
|
13
|
+
Terminal access with support for ANSI control codes and
|
14
|
+
BBCode-like embedded text attribute syntax.
|
15
|
+
executables:
|
16
|
+
- bbcode
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files:
|
19
|
+
- README.md
|
20
|
+
files:
|
21
|
+
- ".yardopts"
|
22
|
+
- README.md
|
23
|
+
- bin/bbcode
|
24
|
+
- examples/24bit-colors.rb
|
25
|
+
- examples/3bit-colors.rb
|
26
|
+
- examples/8bit-colors.rb
|
27
|
+
- examples/attributes.rb
|
28
|
+
- examples/bbcode.rb
|
29
|
+
- examples/info.rb
|
30
|
+
- examples/key-codes.rb
|
31
|
+
- lib/terminal.rb
|
32
|
+
- lib/terminal/ansi.rb
|
33
|
+
- lib/terminal/ansi/attributes.rb
|
34
|
+
- lib/terminal/ansi/named_colors.rb
|
35
|
+
- lib/terminal/detect.rb
|
36
|
+
- lib/terminal/input.rb
|
37
|
+
- lib/terminal/preload.rb
|
38
|
+
- lib/terminal/rspec/helper.rb
|
39
|
+
- lib/terminal/text.rb
|
40
|
+
- lib/terminal/text/char_width.rb
|
41
|
+
- lib/terminal/version.rb
|
42
|
+
- lib/terminal_rb.rb
|
43
|
+
homepage: https://codeberg.org/mblumtritt/Terminal.rb
|
44
|
+
licenses:
|
45
|
+
- MIT
|
46
|
+
metadata:
|
47
|
+
source_code_uri: https://codeberg.org/mblumtritt/Terminal.rb
|
48
|
+
bug_tracker_uri: https://codeberg.org/mblumtritt/Terminal.rb/issues
|
49
|
+
documentation_uri: https://rubydoc.info/gems/terminal_rb
|
50
|
+
rubygems_mfa_required: 'true'
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '3.0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
requirements: []
|
65
|
+
rubygems_version: 3.6.9
|
66
|
+
specification_version: 4
|
67
|
+
summary: Easy terminal access with ANSI and BBCode support.
|
68
|
+
test_files: []
|