paperback 0.0.3 → 0.0.5
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 +5 -5
- data/.github/workflows/tests.yml +46 -0
- data/.rubocop-disables.yml +26 -12
- data/CHANGELOG.md +21 -0
- data/README.md +27 -6
- data/bin/paperback +4 -0
- data/lib/paperback/cli.rb +38 -2
- data/lib/paperback/document.rb +134 -17
- data/lib/paperback/preparer.rb +107 -29
- data/lib/paperback/version.rb +2 -1
- data/lib/paperback.rb +12 -0
- data/paperback.gemspec +10 -7
- data/sorbet/config +3 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
- data/sorbet/rbi/gems/chunky_png@1.4.0.rbi +4498 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +3426 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1083 -0
- data/sorbet/rbi/gems/method_source@1.0.0.rbi +272 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
- data/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
- data/sorbet/rbi/gems/parser@3.2.0.0.rbi +6963 -0
- data/sorbet/rbi/gems/pdf-core@0.4.0.rbi +1682 -0
- data/sorbet/rbi/gems/prawn@1.3.0.rbi +5567 -0
- data/sorbet/rbi/gems/pry@0.14.1.rbi +9990 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +408 -0
- data/sorbet/rbi/gems/rake@13.0.6.rbi +3023 -0
- data/sorbet/rbi/gems/rbi@0.0.16.rbi +3008 -0
- data/sorbet/rbi/gems/regexp_parser@2.6.1.rbi +3481 -0
- data/sorbet/rbi/gems/rexml@3.2.5.rbi +4717 -0
- data/sorbet/rbi/gems/rqrcode@0.10.1.rbi +617 -0
- data/sorbet/rbi/gems/rspec-core@3.12.0.rbi +10791 -0
- data/sorbet/rbi/gems/rspec-expectations@3.12.1.rbi +8106 -0
- data/sorbet/rbi/gems/rspec-mocks@3.12.1.rbi +5305 -0
- data/sorbet/rbi/gems/rspec-support@3.12.0.rbi +1617 -0
- data/sorbet/rbi/gems/rspec@3.12.0.rbi +88 -0
- data/sorbet/rbi/gems/rubocop-ast@1.24.1.rbi +6617 -0
- data/sorbet/rbi/gems/rubocop@0.93.1.rbi +40848 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +1234 -0
- data/sorbet/rbi/gems/sixword@0.4.0.rbi +536 -0
- data/sorbet/rbi/gems/spoom@1.1.15.rbi +2383 -0
- data/sorbet/rbi/gems/subprocess@1.5.6.rbi +391 -0
- data/sorbet/rbi/gems/tapioca@0.10.5.rbi +3207 -0
- data/sorbet/rbi/gems/thor@1.2.1.rbi +3956 -0
- data/sorbet/rbi/gems/ttfunk@1.4.0.rbi +1951 -0
- data/sorbet/rbi/gems/unicode-display_width@1.8.0.rbi +40 -0
- data/sorbet/rbi/gems/unparser@0.6.7.rbi +4524 -0
- data/sorbet/rbi/gems/webrick@1.7.0.rbi +2555 -0
- data/sorbet/rbi/gems/yard-sorbet@0.8.0.rbi +441 -0
- data/sorbet/rbi/gems/yard@0.9.28.rbi +17816 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +4 -0
- data/spec/functional/paperback/cli_spec.rb +195 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/paperback_spec.rb +1 -0
- metadata +91 -7
data/lib/paperback/preparer.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'base64'
|
@@ -12,37 +13,67 @@ module Paperback
|
|
12
13
|
# Class wrapping functions to prepare data for paperback storage, including
|
13
14
|
# QR code and sixword encoding.
|
14
15
|
class Preparer
|
16
|
+
extend T::Sig
|
17
|
+
|
18
|
+
sig {returns(String)}
|
15
19
|
attr_reader :data
|
20
|
+
|
21
|
+
sig {returns(T::Hash[String, T.untyped])}
|
16
22
|
attr_reader :labels
|
23
|
+
|
24
|
+
sig {returns(T::Boolean)}
|
17
25
|
attr_reader :qr_base64
|
26
|
+
|
27
|
+
sig {returns(T::Boolean)}
|
18
28
|
attr_reader :encrypt
|
29
|
+
|
30
|
+
sig {returns(T.nilable(String))}
|
19
31
|
attr_reader :passphrase_file
|
20
32
|
|
33
|
+
sig do
|
34
|
+
params(
|
35
|
+
filename: String,
|
36
|
+
encrypt: T::Boolean,
|
37
|
+
qr_base64: T::Boolean,
|
38
|
+
qr_level: T.nilable(Symbol),
|
39
|
+
comment: T.nilable(String),
|
40
|
+
passphrase_file: T.nilable(String),
|
41
|
+
include_base64: T::Boolean,
|
42
|
+
).void
|
43
|
+
end
|
21
44
|
def initialize(filename:, encrypt: true, qr_base64: false, qr_level: nil,
|
22
|
-
comment: nil, passphrase_file: nil)
|
45
|
+
comment: nil, passphrase_file: nil, include_base64: true)
|
23
46
|
|
24
47
|
log.debug('Preparer#initialize')
|
25
48
|
|
49
|
+
# lazy initializers, all explicitly set to nil
|
50
|
+
@log = T.let(nil, T.nilable(Logger))
|
51
|
+
@qr_code = T.let(nil, T.nilable(RQRCode::QRCode))
|
52
|
+
@sixword_lines = T.let(nil, T.nilable(T::Array[String]))
|
53
|
+
@passphrase = T.let(nil, T.nilable(String))
|
54
|
+
|
26
55
|
log.info("Reading #{filename.inspect}")
|
27
56
|
plain_data = File.read(filename)
|
28
57
|
|
29
58
|
log.debug("Read #{plain_data.bytesize} bytes")
|
30
59
|
|
31
|
-
@encrypt = encrypt
|
60
|
+
@encrypt = T.let(encrypt, T::Boolean)
|
32
61
|
|
33
62
|
if encrypt
|
34
63
|
@data = self.class.gpg_encrypt(filename: filename, password: passphrase)
|
35
64
|
else
|
36
|
-
@data = plain_data
|
65
|
+
@data = T.let(plain_data, String)
|
37
66
|
end
|
38
|
-
@sha256 = Digest::SHA256.hexdigest(plain_data)
|
67
|
+
@sha256 = T.let(Digest::SHA256.hexdigest(plain_data), String)
|
39
68
|
|
40
|
-
@qr_base64 = qr_base64
|
41
|
-
@qr_level = qr_level
|
69
|
+
@qr_base64 = T.let(qr_base64, T::Boolean)
|
70
|
+
@qr_level = T.let(qr_level, T.nilable(Symbol))
|
42
71
|
|
43
|
-
@passphrase_file = passphrase_file
|
72
|
+
@passphrase_file = T.let(passphrase_file, T.nilable(String))
|
44
73
|
|
45
|
-
@
|
74
|
+
@include_base64 = T.let(!!include_base64, T::Boolean)
|
75
|
+
|
76
|
+
@labels = T.let({}, T::Hash[String, T.untyped])
|
46
77
|
@labels['Filename'] = filename
|
47
78
|
@labels['Backed up'] = Time.now.to_s
|
48
79
|
|
@@ -53,16 +84,21 @@ module Paperback
|
|
53
84
|
|
54
85
|
@labels['SHA256'] = Digest::SHA256.hexdigest(plain_data)
|
55
86
|
|
56
|
-
@document = Paperback::Document.new
|
87
|
+
@document = T.let(Paperback::Document.new, Paperback::Document)
|
57
88
|
end
|
58
89
|
|
90
|
+
@log = T.let(nil, T.nilable(Logger))
|
91
|
+
|
92
|
+
sig {returns(Logger)}
|
59
93
|
def log
|
60
94
|
@log ||= Paperback.class_log(self.class)
|
61
95
|
end
|
96
|
+
sig {returns(Logger)}
|
62
97
|
def self.log
|
63
98
|
@log ||= Paperback.class_log(self)
|
64
99
|
end
|
65
100
|
|
101
|
+
sig {params(output_filename: String, extra_draw_opts: T::Hash[T.untyped, T.untyped]).void}
|
66
102
|
def render(output_filename:, extra_draw_opts: {})
|
67
103
|
log.debug('Preparer#render')
|
68
104
|
|
@@ -73,12 +109,20 @@ module Paperback
|
|
73
109
|
sixword_bytes: data.bytesize,
|
74
110
|
}
|
75
111
|
|
112
|
+
if include_base64?
|
113
|
+
opts[:base64_content] = base64_content
|
114
|
+
opts[:base64_bytes] = data.bytesize
|
115
|
+
end
|
116
|
+
|
76
117
|
if encrypt
|
77
118
|
opts[:passphrase_sha] = self.class.truncated_sha256(passphrase)
|
78
119
|
opts[:passphrase_len] = passphrase.length
|
79
120
|
if passphrase_file
|
80
|
-
File.open(
|
81
|
-
|
121
|
+
File.open(
|
122
|
+
T.must(passphrase_file),
|
123
|
+
File::CREAT | File::EXCL | File::WRONLY,
|
124
|
+
0o400
|
125
|
+
) do |f|
|
82
126
|
f.write(passphrase)
|
83
127
|
end
|
84
128
|
log.info("Wrote passphrase to #{passphrase_file.inspect}")
|
@@ -91,18 +135,30 @@ module Paperback
|
|
91
135
|
|
92
136
|
log.info('Render complete')
|
93
137
|
|
94
|
-
if encrypt
|
95
|
-
puts
|
138
|
+
if encrypt
|
139
|
+
puts 'SHA256(passphrase)[0...16]: ' + opts.fetch(:passphrase_sha)
|
140
|
+
if !passphrase_file
|
141
|
+
puts "Passphrase: #{passphrase}"
|
142
|
+
end
|
143
|
+
else
|
144
|
+
log.info('Content was not encrypted')
|
96
145
|
end
|
97
146
|
end
|
98
147
|
|
148
|
+
sig {returns(String)}
|
99
149
|
def passphrase
|
100
150
|
raise "Can't have passphrase without encrypt" unless encrypt
|
101
151
|
@passphrase ||= self.class.random_passphrase
|
102
152
|
end
|
103
153
|
|
104
|
-
PassChars =
|
154
|
+
PassChars = T.let(
|
155
|
+
[*'a'..'z', *'A'..'Z', *'0'..'9'].freeze, T::Array[String]
|
156
|
+
)
|
105
157
|
|
158
|
+
sig do
|
159
|
+
params(entropy_bits: Integer, char_set: T::Array[String])
|
160
|
+
.returns(String)
|
161
|
+
end
|
106
162
|
def self.random_passphrase(entropy_bits: 256, char_set: PassChars)
|
107
163
|
chars_needed = (entropy_bits / Math.log2(char_set.length)).ceil
|
108
164
|
(0...chars_needed).map {
|
@@ -111,35 +167,40 @@ module Paperback
|
|
111
167
|
end
|
112
168
|
|
113
169
|
# Compute a truncated SHA256 digest
|
170
|
+
sig {params(content: String).returns(String)}
|
114
171
|
def self.truncated_sha256(content)
|
115
172
|
Digest::SHA256.hexdigest(content)[0...16]
|
116
173
|
end
|
117
174
|
|
175
|
+
sig {params(filename: String, password: String).returns(String)}
|
118
176
|
def self.gpg_encrypt(filename:, password:)
|
119
177
|
cmd = %w[
|
120
178
|
gpg -c -o - --batch --cipher-algo aes256 --passphrase-fd 0 --
|
121
179
|
] + [filename]
|
122
|
-
out = nil
|
180
|
+
out = T.let(nil, T.nilable(String))
|
123
181
|
|
124
182
|
log.debug('+ ' + cmd.join(' '))
|
125
183
|
Subprocess.check_call(cmd, stdin: Subprocess::PIPE,
|
126
|
-
|
184
|
+
stdout: Subprocess::PIPE) do |p|
|
127
185
|
out, _err = p.communicate(password)
|
128
186
|
end
|
129
187
|
|
130
|
-
out
|
188
|
+
T.must(out)
|
131
189
|
end
|
132
190
|
|
191
|
+
sig {params(data: String, strip_comments: T::Boolean).returns(String)}
|
133
192
|
def self.gpg_ascii_enarmor(data, strip_comments: true)
|
134
193
|
cmd = %w[gpg --batch --enarmor]
|
135
|
-
out = nil
|
194
|
+
out = T.let(nil, T.nilable(String))
|
136
195
|
|
137
196
|
log.debug('+ ' + cmd.join(' '))
|
138
197
|
Subprocess.check_call(cmd, stdin: Subprocess::PIPE,
|
139
|
-
|
198
|
+
stdout: Subprocess::PIPE) do |p|
|
140
199
|
out, _err = p.communicate(data)
|
141
200
|
end
|
142
201
|
|
202
|
+
out = T.must(out)
|
203
|
+
|
143
204
|
if strip_comments
|
144
205
|
out = out.each_line.select { |l| !l.start_with?('Comment: ') }.join
|
145
206
|
end
|
@@ -147,37 +208,42 @@ module Paperback
|
|
147
208
|
out
|
148
209
|
end
|
149
210
|
|
211
|
+
sig {params(data: String).returns(String)}
|
150
212
|
def self.gpg_ascii_dearmor(data)
|
151
213
|
cmd = %w[gpg --batch --dearmor]
|
152
|
-
out = nil
|
214
|
+
out = T.let(nil, T.nilable(String))
|
153
215
|
|
154
216
|
log.debug('+ ' + cmd.join(' '))
|
155
217
|
Subprocess.check_call(cmd, stdin: Subprocess::PIPE,
|
156
|
-
|
218
|
+
stdout: Subprocess::PIPE) do |p|
|
157
219
|
out, _err = p.communicate(data)
|
158
220
|
end
|
159
221
|
|
160
|
-
out
|
222
|
+
T.must(out)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Whether to add the Base64 encoding to the generated document.
|
226
|
+
#
|
227
|
+
# @return [Boolean]
|
228
|
+
sig {returns(T::Boolean)}
|
229
|
+
def include_base64?
|
230
|
+
!!@include_base64
|
161
231
|
end
|
162
232
|
|
163
233
|
private
|
164
234
|
|
235
|
+
sig {returns(RQRCode::QRCode)}
|
165
236
|
def qr_code
|
166
237
|
@qr_code ||= qr_code!
|
167
238
|
end
|
168
239
|
|
240
|
+
sig {returns(RQRCode::QRCode)}
|
169
241
|
def qr_code!
|
170
242
|
log.info('Generating QR code')
|
171
243
|
|
172
244
|
# Base64 encode data prior to QR encoding as requested
|
173
245
|
if qr_base64
|
174
|
-
|
175
|
-
# If data is already GPG encrypted, use GPG's base64 armor
|
176
|
-
input = self.class.gpg_ascii_enarmor(data)
|
177
|
-
else
|
178
|
-
# Otherwise do plain Base64
|
179
|
-
input = Base64.encode64(data)
|
180
|
-
end
|
246
|
+
input = base64_content
|
181
247
|
else
|
182
248
|
input = data
|
183
249
|
end
|
@@ -198,11 +264,23 @@ module Paperback
|
|
198
264
|
RQRCode::QRCode.new(input, level: @qr_level)
|
199
265
|
end
|
200
266
|
|
267
|
+
sig {returns(T::Array[String])}
|
201
268
|
def sixword_lines
|
202
269
|
log.info('Encoding with Sixword')
|
203
270
|
@sixword_lines ||=
|
204
271
|
Sixword.pad_encode_to_sentences(data).map(&:downcase)
|
205
272
|
end
|
206
273
|
|
274
|
+
sig {returns(String)}
|
275
|
+
def base64_content
|
276
|
+
log.debug('Encoding with Base64')
|
277
|
+
if encrypt
|
278
|
+
# If data is already GPG encrypted, use GPG's base64 armor
|
279
|
+
self.class.gpg_ascii_enarmor(data)
|
280
|
+
else
|
281
|
+
# Otherwise do plain Base64
|
282
|
+
Base64.encode64(data)
|
283
|
+
end
|
284
|
+
end
|
207
285
|
end
|
208
286
|
end
|
data/lib/paperback/version.rb
CHANGED
data/lib/paperback.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
+
# typed: strict
|
1
2
|
require 'logger'
|
3
|
+
require 'sorbet-runtime'
|
2
4
|
|
3
5
|
# Paperback is a library for creating paper backups of sensitive data.
|
4
6
|
module Paperback
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
@log = T.let(nil, T.nilable(Logger))
|
10
|
+
|
11
|
+
sig {returns(Logger)}
|
5
12
|
def self.log
|
6
13
|
return @log if @log
|
7
14
|
@log = Logger.new(STDERR)
|
@@ -10,6 +17,7 @@ module Paperback
|
|
10
17
|
@log
|
11
18
|
end
|
12
19
|
|
20
|
+
sig {params(klass: Class, stream: IO).returns(Logger)}
|
13
21
|
def self.class_log(klass, stream=STDERR)
|
14
22
|
log = Logger.new(stream)
|
15
23
|
log.progname = klass.name
|
@@ -17,10 +25,14 @@ module Paperback
|
|
17
25
|
log
|
18
26
|
end
|
19
27
|
|
28
|
+
@log_level = T.let(nil, T.nilable(Integer))
|
29
|
+
|
30
|
+
sig {returns(Integer)}
|
20
31
|
def self.log_level
|
21
32
|
@log_level ||= Logger::INFO
|
22
33
|
end
|
23
34
|
|
35
|
+
sig {params(val: Integer).returns(Integer)}
|
24
36
|
def self.log_level=(val)
|
25
37
|
@log_level = val
|
26
38
|
end
|
data/paperback.gemspec
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require 'paperback/version'
|
3
|
+
require_relative 'lib/paperback/version'
|
6
4
|
|
7
5
|
Gem::Specification.new do |spec|
|
8
6
|
spec.name = 'paperback'
|
@@ -17,22 +15,27 @@ Gem::Specification.new do |spec|
|
|
17
15
|
spec.homepage = 'https://github.com/ab/paperback'
|
18
16
|
spec.license = 'GPL-3'
|
19
17
|
|
20
|
-
spec.files = `git ls-files`.split($/)
|
18
|
+
spec.files = `git ls-files`.split($/).reject { |s|
|
19
|
+
s.start_with?('sample/')
|
20
|
+
}
|
21
21
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
22
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
23
|
spec.require_paths = ['lib']
|
24
24
|
|
25
|
-
spec.add_development_dependency 'bundler', '~>
|
25
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
26
26
|
spec.add_development_dependency 'pry'
|
27
27
|
spec.add_development_dependency 'rake'
|
28
28
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
29
29
|
spec.add_development_dependency 'rubocop', '~> 0.50'
|
30
|
+
spec.add_development_dependency 'sorbet', '~> 0.5'
|
31
|
+
spec.add_development_dependency 'tapioca', '~> 0.10'
|
30
32
|
spec.add_development_dependency 'yard'
|
31
33
|
|
32
34
|
spec.add_dependency('prawn', '~> 1.3')
|
33
35
|
spec.add_dependency('rqrcode', '~> 0.10')
|
34
36
|
spec.add_dependency('sixword', '~> 0.3')
|
37
|
+
spec.add_dependency('sorbet-runtime', '~> 0.5')
|
35
38
|
spec.add_dependency('subprocess', '~> 1.3')
|
36
39
|
|
37
|
-
spec.required_ruby_version = '>= 2.
|
40
|
+
spec.required_ruby_version = '>= 2.7'
|
38
41
|
end
|
data/sorbet/config
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
# DO NOT EDIT MANUALLY
|
4
|
+
# This file was pulled from a central RBI files repository.
|
5
|
+
# Please run `bin/tapioca annotations` to update it.
|
6
|
+
|
7
|
+
module Rainbow
|
8
|
+
# @shim: https://github.com/sickill/rainbow/blob/master/lib/rainbow.rb#L10-L12
|
9
|
+
sig { returns(T::Boolean) }
|
10
|
+
attr_accessor :enabled
|
11
|
+
|
12
|
+
class Color
|
13
|
+
sig { returns(Symbol) }
|
14
|
+
attr_reader :ground
|
15
|
+
|
16
|
+
sig { params(ground: Symbol, values: T.any([Integer], [Integer, Integer, Integer])).returns(Color) }
|
17
|
+
def self.build(ground, values); end
|
18
|
+
|
19
|
+
sig { params(hex: String).returns([Integer, Integer, Integer]) }
|
20
|
+
def self.parse_hex_color(hex); end
|
21
|
+
|
22
|
+
class Indexed < Rainbow::Color
|
23
|
+
sig { returns(Integer) }
|
24
|
+
attr_reader :num
|
25
|
+
|
26
|
+
sig { params(ground: Symbol, num: Integer).void }
|
27
|
+
def initialize(ground, num); end
|
28
|
+
|
29
|
+
sig { returns(T::Array[Integer]) }
|
30
|
+
def codes; end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Named < Rainbow::Color::Indexed
|
34
|
+
NAMES = T.let(nil, T::Hash[Symbol, Integer])
|
35
|
+
|
36
|
+
sig { params(ground: Symbol, name: Symbol).void }
|
37
|
+
def initialize(ground, name); end
|
38
|
+
|
39
|
+
sig { returns(T::Array[Symbol]) }
|
40
|
+
def self.color_names; end
|
41
|
+
|
42
|
+
sig { returns(String) }
|
43
|
+
def self.valid_names; end
|
44
|
+
end
|
45
|
+
|
46
|
+
class RGB < Rainbow::Color::Indexed
|
47
|
+
sig { returns(Integer) }
|
48
|
+
attr_reader :r, :g, :b
|
49
|
+
|
50
|
+
sig { params(ground: Symbol, values: Integer).void }
|
51
|
+
def initialize(ground, *values); end
|
52
|
+
|
53
|
+
sig { returns(T::Array[Integer]) }
|
54
|
+
def codes; end
|
55
|
+
|
56
|
+
sig { params(value: Numeric).returns(Integer) }
|
57
|
+
def self.to_ansi_domain(value); end
|
58
|
+
end
|
59
|
+
|
60
|
+
class X11Named < Rainbow::Color::RGB
|
61
|
+
include Rainbow::X11ColorNames
|
62
|
+
|
63
|
+
sig { returns(T::Array[Symbol]) }
|
64
|
+
def self.color_names; end
|
65
|
+
|
66
|
+
sig { returns(String) }
|
67
|
+
def self.valid_names; end
|
68
|
+
|
69
|
+
sig { params(ground: Symbol, name: Symbol).void }
|
70
|
+
def initialize(ground, name); end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
sig { returns(Wrapper) }
|
75
|
+
def self.global; end
|
76
|
+
|
77
|
+
sig { returns(T::Boolean) }
|
78
|
+
def self.enabled; end
|
79
|
+
|
80
|
+
sig { params(value: T::Boolean).returns(T::Boolean) }
|
81
|
+
def self.enabled=(value); end
|
82
|
+
|
83
|
+
sig { params(string: String).returns(String) }
|
84
|
+
def self.uncolor(string); end
|
85
|
+
|
86
|
+
class NullPresenter < String
|
87
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(NullPresenter) }
|
88
|
+
def color(*values); end
|
89
|
+
|
90
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(NullPresenter) }
|
91
|
+
def foreground(*values); end
|
92
|
+
|
93
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(NullPresenter) }
|
94
|
+
def fg(*values); end
|
95
|
+
|
96
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(NullPresenter) }
|
97
|
+
def background(*values); end
|
98
|
+
|
99
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(NullPresenter) }
|
100
|
+
def bg(*values); end
|
101
|
+
|
102
|
+
sig { returns(NullPresenter) }
|
103
|
+
def reset; end
|
104
|
+
|
105
|
+
sig { returns(NullPresenter) }
|
106
|
+
def bright; end
|
107
|
+
|
108
|
+
sig { returns(NullPresenter) }
|
109
|
+
def faint; end
|
110
|
+
|
111
|
+
sig { returns(NullPresenter) }
|
112
|
+
def italic; end
|
113
|
+
|
114
|
+
sig { returns(NullPresenter) }
|
115
|
+
def underline; end
|
116
|
+
|
117
|
+
sig { returns(NullPresenter) }
|
118
|
+
def blink; end
|
119
|
+
|
120
|
+
sig { returns(NullPresenter) }
|
121
|
+
def inverse; end
|
122
|
+
|
123
|
+
sig { returns(NullPresenter) }
|
124
|
+
def hide; end
|
125
|
+
|
126
|
+
sig { returns(NullPresenter) }
|
127
|
+
def cross_out; end
|
128
|
+
|
129
|
+
sig { returns(NullPresenter) }
|
130
|
+
def black; end
|
131
|
+
|
132
|
+
sig { returns(NullPresenter) }
|
133
|
+
def red; end
|
134
|
+
|
135
|
+
sig { returns(NullPresenter) }
|
136
|
+
def green; end
|
137
|
+
|
138
|
+
sig { returns(NullPresenter) }
|
139
|
+
def yellow; end
|
140
|
+
|
141
|
+
sig { returns(NullPresenter) }
|
142
|
+
def blue; end
|
143
|
+
|
144
|
+
sig { returns(NullPresenter) }
|
145
|
+
def magenta; end
|
146
|
+
|
147
|
+
sig { returns(NullPresenter) }
|
148
|
+
def cyan; end
|
149
|
+
|
150
|
+
sig { returns(NullPresenter) }
|
151
|
+
def white; end
|
152
|
+
|
153
|
+
sig { returns(NullPresenter) }
|
154
|
+
def bold; end
|
155
|
+
|
156
|
+
sig { returns(NullPresenter) }
|
157
|
+
def dark; end
|
158
|
+
|
159
|
+
sig { returns(NullPresenter) }
|
160
|
+
def strike; end
|
161
|
+
end
|
162
|
+
|
163
|
+
class Presenter < String
|
164
|
+
TERM_EFFECTS = T.let(nil, T::Hash[Symbol, Integer])
|
165
|
+
|
166
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(Presenter) }
|
167
|
+
def color(*values); end
|
168
|
+
|
169
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(Presenter) }
|
170
|
+
def foreground(*values); end
|
171
|
+
|
172
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(Presenter) }
|
173
|
+
def fg(*values); end
|
174
|
+
|
175
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(Presenter) }
|
176
|
+
def background(*values); end
|
177
|
+
|
178
|
+
sig { params(values: T.any([Integer], [Integer, Integer, Integer])).returns(Presenter) }
|
179
|
+
def bg(*values); end
|
180
|
+
|
181
|
+
sig { returns(Presenter) }
|
182
|
+
def reset; end
|
183
|
+
|
184
|
+
sig { returns(Presenter) }
|
185
|
+
def bright; end
|
186
|
+
|
187
|
+
sig { returns(Presenter) }
|
188
|
+
def faint; end
|
189
|
+
|
190
|
+
sig { returns(Presenter) }
|
191
|
+
def italic; end
|
192
|
+
|
193
|
+
sig { returns(Presenter) }
|
194
|
+
def underline; end
|
195
|
+
|
196
|
+
sig { returns(Presenter) }
|
197
|
+
def blink; end
|
198
|
+
|
199
|
+
sig { returns(Presenter) }
|
200
|
+
def inverse; end
|
201
|
+
|
202
|
+
sig { returns(Presenter) }
|
203
|
+
def hide; end
|
204
|
+
|
205
|
+
sig { returns(Presenter) }
|
206
|
+
def cross_out; end
|
207
|
+
|
208
|
+
sig { returns(Presenter) }
|
209
|
+
def black; end
|
210
|
+
|
211
|
+
sig { returns(Presenter) }
|
212
|
+
def red; end
|
213
|
+
|
214
|
+
sig { returns(Presenter) }
|
215
|
+
def green; end
|
216
|
+
|
217
|
+
sig { returns(Presenter) }
|
218
|
+
def yellow; end
|
219
|
+
|
220
|
+
sig { returns(Presenter) }
|
221
|
+
def blue; end
|
222
|
+
|
223
|
+
sig { returns(Presenter) }
|
224
|
+
def magenta; end
|
225
|
+
|
226
|
+
sig { returns(Presenter) }
|
227
|
+
def cyan; end
|
228
|
+
|
229
|
+
sig { returns(Presenter) }
|
230
|
+
def white; end
|
231
|
+
|
232
|
+
sig { returns(Presenter) }
|
233
|
+
def bold; end
|
234
|
+
|
235
|
+
sig { returns(Presenter) }
|
236
|
+
def dark; end
|
237
|
+
|
238
|
+
sig { returns(Presenter) }
|
239
|
+
def strike; end
|
240
|
+
end
|
241
|
+
|
242
|
+
class StringUtils
|
243
|
+
sig { params(string: String, codes: T::Array[Integer]).returns(String) }
|
244
|
+
def self.wrap_with_sgr(string, codes); end
|
245
|
+
|
246
|
+
sig { params(string: String).returns(String) }
|
247
|
+
def self.uncolor(string); end
|
248
|
+
end
|
249
|
+
|
250
|
+
VERSION = T.let(nil, String)
|
251
|
+
|
252
|
+
class Wrapper
|
253
|
+
sig { returns(T::Boolean) }
|
254
|
+
attr_accessor :enabled
|
255
|
+
|
256
|
+
sig { params(enabled: T::Boolean).void }
|
257
|
+
def initialize(enabled = true); end
|
258
|
+
|
259
|
+
sig { params(string: String).returns(T.any(Rainbow::Presenter, Rainbow::NullPresenter)) }
|
260
|
+
def wrap(string); end
|
261
|
+
end
|
262
|
+
|
263
|
+
module X11ColorNames
|
264
|
+
NAMES = T.let(nil, T::Hash[Symbol, [Integer, Integer, Integer]])
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
sig { params(string: String).returns(Rainbow::Presenter) }
|
269
|
+
def Rainbow(string); end
|