tone 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/LICENSE.adoc +134 -0
- data/README.adoc +453 -0
- data/lib/tone/aliaser.rb +63 -0
- data/lib/tone/client.rb +41 -0
- data/lib/tone/configuration/defaults.yml +44 -0
- data/lib/tone/configuration/loader.rb +20 -0
- data/lib/tone/decoder.rb +51 -0
- data/lib/tone/encoder.rb +37 -0
- data/lib/tone/error.rb +7 -0
- data/lib/tone.rb +13 -0
- data/tone.gemspec +31 -0
- data.tar.gz.sig +0 -0
- metadata +118 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0d3017ae0f1faf02c19825100422d443e068b901b29e6568c0b07d912452970f
|
4
|
+
data.tar.gz: 4d86df41de0b4f81cfac5924e065f7f17fa5e73e484e86c7071fcc5218fcb906
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b5701133e078fa303fdeb3fa3be36a2b7e0059fe0f0b42f7dae2a5320ed6744dc51021ea19d0d2ec107ed15e312a0c1a8c0e0a8eef295f84afa600941e1a972d
|
7
|
+
data.tar.gz: 2f18052fcd993427dd8e0accf3df23ca0cfbfdb59b38c29f72930864025bb01c2837c9c7401312d69759a32235c536f5ccfaa4eaeea574a37b9245e6fa669582
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data/LICENSE.adoc
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
= Hippocratic License
|
2
|
+
|
3
|
+
Version: 2.1.0.
|
4
|
+
|
5
|
+
Purpose. The purpose of this License is for the Licensor named above to
|
6
|
+
permit the Licensee (as defined below) broad permission, if consistent
|
7
|
+
with Human Rights Laws and Human Rights Principles (as each is defined
|
8
|
+
below), to use and work with the Software (as defined below) within the
|
9
|
+
full scope of Licensor’s copyright and patent rights, if any, in the
|
10
|
+
Software, while ensuring attribution and protecting the Licensor from
|
11
|
+
liability.
|
12
|
+
|
13
|
+
Permission and Conditions. The Licensor grants permission by this
|
14
|
+
license ("License"), free of charge, to the extent of Licensor’s
|
15
|
+
rights under applicable copyright and patent law, to any person or
|
16
|
+
entity (the "Licensee") obtaining a copy of this software and
|
17
|
+
associated documentation files (the "Software"), to do everything with
|
18
|
+
the Software that would otherwise infringe (i) the Licensor’s copyright
|
19
|
+
in the Software or (ii) any patent claims to the Software that the
|
20
|
+
Licensor can license or becomes able to license, subject to all of the
|
21
|
+
following terms and conditions:
|
22
|
+
|
23
|
+
* Acceptance. This License is automatically offered to every person and
|
24
|
+
entity subject to its terms and conditions. Licensee accepts this
|
25
|
+
License and agrees to its terms and conditions by taking any action with
|
26
|
+
the Software that, absent this License, would infringe any intellectual
|
27
|
+
property right held by Licensor.
|
28
|
+
* Notice. Licensee must ensure that everyone who gets a copy of any part
|
29
|
+
of this Software from Licensee, with or without changes, also receives
|
30
|
+
the License and the above copyright notice (and if included by the
|
31
|
+
Licensor, patent, trademark and attribution notice). Licensee must cause
|
32
|
+
any modified versions of the Software to carry prominent notices stating
|
33
|
+
that Licensee changed the Software. For clarity, although Licensee is
|
34
|
+
free to create modifications of the Software and distribute only the
|
35
|
+
modified portion created by Licensee with additional or different terms,
|
36
|
+
the portion of the Software not modified must be distributed pursuant to
|
37
|
+
this License. If anyone notifies Licensee in writing that Licensee has
|
38
|
+
not complied with this Notice section, Licensee can keep this License by
|
39
|
+
taking all practical steps to comply within 30 days after the notice. If
|
40
|
+
Licensee does not do so, Licensee’s License (and all rights licensed
|
41
|
+
hereunder) shall end immediately.
|
42
|
+
* Compliance with Human Rights Principles and Human Rights Laws.
|
43
|
+
[arabic]
|
44
|
+
. Human Rights Principles.
|
45
|
+
[loweralpha]
|
46
|
+
.. Licensee is advised to consult the articles of the United Nations
|
47
|
+
Universal Declaration of Human Rights and the United Nations Global
|
48
|
+
Compact that define recognized principles of international human rights
|
49
|
+
(the "Human Rights Principles"). Licensee shall use the Software in a
|
50
|
+
manner consistent with Human Rights Principles.
|
51
|
+
.. Unless the Licensor and Licensee agree otherwise, any dispute,
|
52
|
+
controversy, or claim arising out of or relating to (i) Section 1(a)
|
53
|
+
regarding Human Rights Principles, including the breach of Section 1(a),
|
54
|
+
termination of this License for breach of the Human Rights Principles,
|
55
|
+
or invalidity of Section 1(a) or (ii) a determination of whether any Law
|
56
|
+
is consistent or in conflict with Human Rights Principles pursuant to
|
57
|
+
Section 2, below, shall be settled by arbitration in accordance with the
|
58
|
+
Hague Rules on Business and Human Rights Arbitration (the "Rules");
|
59
|
+
provided, however, that Licensee may elect not to participate in such
|
60
|
+
arbitration, in which event this License (and all rights licensed
|
61
|
+
hereunder) shall end immediately. The number of arbitrators shall be one
|
62
|
+
unless the Rules require otherwise.
|
63
|
+
+
|
64
|
+
Unless both the Licensor and Licensee agree to the contrary: (1) All
|
65
|
+
documents and information concerning the arbitration shall be public and
|
66
|
+
may be disclosed by any party; (2) The repository referred to under
|
67
|
+
Article 43 of the Rules shall make available to the public in a timely
|
68
|
+
manner all documents concerning the arbitration which are communicated
|
69
|
+
to it, including all submissions of the parties, all evidence admitted
|
70
|
+
into the record of the proceedings, all transcripts or other recordings
|
71
|
+
of hearings and all orders, decisions and awards of the arbitral
|
72
|
+
tribunal, subject only to the arbitral tribunal’s powers to take such
|
73
|
+
measures as may be necessary to safeguard the integrity of the arbitral
|
74
|
+
process pursuant to Articles 18, 33, 41 and 42 of the Rules; and (3)
|
75
|
+
Article 26(6) of the Rules shall not apply.
|
76
|
+
. Human Rights Laws. The Software shall not be used by any person or
|
77
|
+
entity for any systems, activities, or other uses that violate any Human
|
78
|
+
Rights Laws. "Human Rights Laws" means any applicable laws,
|
79
|
+
regulations, or rules (collectively, "Laws") that protect human,
|
80
|
+
civil, labor, privacy, political, environmental, security, economic, due
|
81
|
+
process, or similar rights; provided, however, that such Laws are
|
82
|
+
consistent and not in conflict with Human Rights Principles (a dispute
|
83
|
+
over the consistency or a conflict between Laws and Human Rights
|
84
|
+
Principles shall be determined by arbitration as stated above). Where
|
85
|
+
the Human Rights Laws of more than one jurisdiction are applicable or in
|
86
|
+
conflict with respect to the use of the Software, the Human Rights Laws
|
87
|
+
that are most protective of the individuals or groups harmed shall
|
88
|
+
apply.
|
89
|
+
. Indemnity. Licensee shall hold harmless and indemnify Licensor (and
|
90
|
+
any other contributor) against all losses, damages, liabilities,
|
91
|
+
deficiencies, claims, actions, judgments, settlements, interest, awards,
|
92
|
+
penalties, fines, costs, or expenses of whatever kind, including
|
93
|
+
Licensor’s reasonable attorneys’ fees, arising out of or relating to
|
94
|
+
Licensee’s use of the Software in violation of Human Rights Laws or
|
95
|
+
Human Rights Principles.
|
96
|
+
* Failure to Comply. Any failure of Licensee to act according to the
|
97
|
+
terms and conditions of this License is both a breach of the License and
|
98
|
+
an infringement of the intellectual property rights of the Licensor
|
99
|
+
(subject to exceptions under Laws, e.g., fair use). In the event of a
|
100
|
+
breach or infringement, the terms and conditions of this License may be
|
101
|
+
enforced by Licensor under the Laws of any jurisdiction to which
|
102
|
+
Licensee is subject. Licensee also agrees that the Licensor may enforce
|
103
|
+
the terms and conditions of this License against Licensee through
|
104
|
+
specific performance (or similar remedy under Laws) to the extent
|
105
|
+
permitted by Laws. For clarity, except in the event of a breach of this
|
106
|
+
License, infringement, or as otherwise stated in this License, Licensor
|
107
|
+
may not terminate this License with Licensee.
|
108
|
+
* Enforceability and Interpretation. If any term or provision of this
|
109
|
+
License is determined to be invalid, illegal, or unenforceable by a
|
110
|
+
court of competent jurisdiction, then such invalidity, illegality, or
|
111
|
+
unenforceability shall not affect any other term or provision of this
|
112
|
+
License or invalidate or render unenforceable such term or provision in
|
113
|
+
any other jurisdiction; provided, however, subject to a court
|
114
|
+
modification pursuant to the immediately following sentence, if any term
|
115
|
+
or provision of this License pertaining to Human Rights Laws or Human
|
116
|
+
Rights Principles is deemed invalid, illegal, or unenforceable against
|
117
|
+
Licensee by a court of competent jurisdiction, all rights in the
|
118
|
+
Software granted to Licensee shall be deemed null and void as between
|
119
|
+
Licensor and Licensee. Upon a determination that any term or provision
|
120
|
+
is invalid, illegal, or unenforceable, to the extent permitted by Laws,
|
121
|
+
the court may modify this License to affect the original purpose that
|
122
|
+
the Software be used in compliance with Human Rights Principles and
|
123
|
+
Human Rights Laws as closely as possible. The language in this License
|
124
|
+
shall be interpreted as to its fair meaning and not strictly for or
|
125
|
+
against any party.
|
126
|
+
* Disclaimer. TO THE FULL EXTENT ALLOWED BY LAW, THIS SOFTWARE COMES
|
127
|
+
"AS IS," WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED, AND LICENSOR AND
|
128
|
+
ANY OTHER CONTRIBUTOR SHALL NOT BE LIABLE TO ANYONE FOR ANY DAMAGES OR
|
129
|
+
OTHER LIABILITY ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE
|
130
|
+
OR THIS LICENSE, UNDER ANY KIND OF LEGAL CLAIM.
|
131
|
+
|
132
|
+
This Hippocratic License is an link:https://ethicalsource.dev[Ethical Source license] and is offered
|
133
|
+
for use by licensors and licensees at their own risk, on an "AS IS" basis, and with no warranties
|
134
|
+
express or implied, to the maximum extent permitted by Laws.
|
data/README.adoc
ADDED
@@ -0,0 +1,453 @@
|
|
1
|
+
:toc: macro
|
2
|
+
:toclevels: 5
|
3
|
+
:figure-caption!:
|
4
|
+
|
5
|
+
:amazing_print_link: link:https://github.com/amazing-print/amazing_print[Amazing Print]
|
6
|
+
:pattern_matching_link: link:https://alchemists.io/articles/ruby_pattern_matching[pattern matching]
|
7
|
+
|
8
|
+
= Tone
|
9
|
+
|
10
|
+
Provides a customizable link:https://stackoverflow.com/questions/4842424/list-of-ansi-color-escape-sequences[ANSI] text colorizer for your terminal. This allows you to encode plain text that renders as colorized output. This is great for enhancing Command Line Interfaces (CLIs) and terminal output in general.
|
11
|
+
|
12
|
+
toc::[]
|
13
|
+
|
14
|
+
== Features
|
15
|
+
|
16
|
+
* Provides default styles with multiple options for unique combinations.
|
17
|
+
* Provides a single object for encoding and decoding colorized text.
|
18
|
+
* Provides aliasing of color configurations.
|
19
|
+
* Provides quick access to default and aliased styles.
|
20
|
+
|
21
|
+
== Requirements
|
22
|
+
|
23
|
+
. link:https://www.ruby-lang.org[Ruby].
|
24
|
+
|
25
|
+
== Setup
|
26
|
+
|
27
|
+
To install, run:
|
28
|
+
|
29
|
+
[source,ruby]
|
30
|
+
----
|
31
|
+
gem install tone
|
32
|
+
----
|
33
|
+
|
34
|
+
You can also add the gem directly to your project (preferred):
|
35
|
+
|
36
|
+
[source,ruby]
|
37
|
+
----
|
38
|
+
bundle add tone
|
39
|
+
----
|
40
|
+
|
41
|
+
Once the gem is installed, you only need to require it:
|
42
|
+
|
43
|
+
```
|
44
|
+
require "tone"
|
45
|
+
```
|
46
|
+
|
47
|
+
== Usage
|
48
|
+
|
49
|
+
Basic usage is as follows:
|
50
|
+
|
51
|
+
[source,ruby]
|
52
|
+
----
|
53
|
+
tone = Tone.new
|
54
|
+
tone["Success!", :green] # "\e[32mSuccess!\e[0m"
|
55
|
+
----
|
56
|
+
|
57
|
+
There is a lot more you can do with this gem so the following sections will delve into the specifics.
|
58
|
+
|
59
|
+
=== Encode
|
60
|
+
|
61
|
+
As you saw earlier, you can encode plain text as colorized text using `+#[]+`. Use of the `+#[]+` method is an _alias_ to the longer `#encode` method. This allows you to use minimal syntax to create colorized text. Here's a few more examples:
|
62
|
+
|
63
|
+
[source,ruby]
|
64
|
+
----
|
65
|
+
tone = Tone.new
|
66
|
+
|
67
|
+
# With symbols.
|
68
|
+
tone["Success", :black, :on_green] # "\e[30;42mSuccess\e[0m"
|
69
|
+
|
70
|
+
# With strings.
|
71
|
+
tone["Success", "black", "on_green"] # "\e[30;42mSuccess\e[0m"
|
72
|
+
|
73
|
+
# With no styles.
|
74
|
+
tone["Success"] # "Success"
|
75
|
+
|
76
|
+
# With any object that responds to `#to_str` or `#to_s`.
|
77
|
+
tone[Object.new, :green] # "\e[32m#<Object:0x000000010f095668>\e[0m"
|
78
|
+
|
79
|
+
# With nil.
|
80
|
+
tone[nil] # ""
|
81
|
+
|
82
|
+
# With interspersed nils (nils are ignored).
|
83
|
+
tone["Success", nil, :green, nil] # "\e[32mSuccess\e[0m"
|
84
|
+
----
|
85
|
+
|
86
|
+
The first argument is the text you want to encode/colorize. This can be a word, phrase, paragraph, or entire document. All arguments that follow after the first argument are _style_ arguments which allow you to style the color of your text as you see fit. In this case, the `"Success"` text will use a _black foreground_ on a _green background_. The styles available for you to use will be explained shortly, though. For now, know that `+#[]+` is shorthand for `#encode` so any of the above examples could be replaced with `#encode` messages. Example:
|
87
|
+
|
88
|
+
[source,ruby]
|
89
|
+
----
|
90
|
+
tone = Tone.new
|
91
|
+
tone.encode "Success", :black, :on_green # "\e[30;42mSuccess\e[0m"
|
92
|
+
----
|
93
|
+
|
94
|
+
Both methods are available to use depending on your preference.
|
95
|
+
|
96
|
+
=== Decode
|
97
|
+
|
98
|
+
Once your text has been encoded with colors, it can be nice to decode the colorized text back to plain text along with additional metadata. This is helpful -- as an example -- for testing purposes since you might not always want to deal with the hard to read escape characters. If we build upon the examples from the _Encode_ section, we can decode our colorized text into plain text with extra metadata:
|
99
|
+
|
100
|
+
[source,ruby]
|
101
|
+
----
|
102
|
+
tone = Tone.new
|
103
|
+
|
104
|
+
tone.decode "\e[30;42mSuccess\e[0m" # [["Success", :black, :on_green]]
|
105
|
+
tone.decode "\e[37;41mFailure\e[0m" # [["Failure", :white, :on_red]]
|
106
|
+
----
|
107
|
+
|
108
|
+
Notice we get an array of sub arrays which mimic the original arguments passed to `#encode`. This allows you to encode and decode with minimal effort. Here's a more complex example where a sentence is used and formatted with the {amazing_print_link} gem:
|
109
|
+
|
110
|
+
[source,ruby]
|
111
|
+
----
|
112
|
+
tone = Tone.new
|
113
|
+
ap tone.decode("We turned a \e[37;41mfailure\e[0m into a \e[30;42msuccess\e[0m!")
|
114
|
+
|
115
|
+
# [
|
116
|
+
# [
|
117
|
+
# "We turned a "
|
118
|
+
# ],
|
119
|
+
# [
|
120
|
+
# "failure",
|
121
|
+
# :white,
|
122
|
+
# :on_red
|
123
|
+
# ],
|
124
|
+
# [
|
125
|
+
# " into a "
|
126
|
+
# ],
|
127
|
+
# [
|
128
|
+
# "success",
|
129
|
+
# :black,
|
130
|
+
# :on_green
|
131
|
+
# ],
|
132
|
+
# [
|
133
|
+
# "!"
|
134
|
+
# ]
|
135
|
+
# ]
|
136
|
+
----
|
137
|
+
|
138
|
+
For plain text, you get a single element array but for colorized text, it will be broken down into an array of arguments. This allows you to easily iterate over this structure for parsing, transformation, or {pattern_matching_link} purposes.
|
139
|
+
|
140
|
+
Here's another example where a paragraph is used:
|
141
|
+
|
142
|
+
[source,ruby]
|
143
|
+
----
|
144
|
+
tone = Tone.new
|
145
|
+
|
146
|
+
paragraph = <<~CONTENT.strip
|
147
|
+
Yesterday \e[30;42mwent well\e[0m
|
148
|
+
but tomorrow will be \e[37;41mmore challenging\e[0m.
|
149
|
+
CONTENT
|
150
|
+
|
151
|
+
ap tone.decode(paragraph)
|
152
|
+
|
153
|
+
# [
|
154
|
+
# [
|
155
|
+
# "Yesterday "
|
156
|
+
# ],
|
157
|
+
# [
|
158
|
+
# "went well",
|
159
|
+
# :black,
|
160
|
+
# :on_green
|
161
|
+
# ],
|
162
|
+
# [
|
163
|
+
# "\nbut tomorrow will be "
|
164
|
+
# ],
|
165
|
+
# [
|
166
|
+
# "more challenging",
|
167
|
+
# :white,
|
168
|
+
# :on_red
|
169
|
+
# ],
|
170
|
+
# [
|
171
|
+
# "."
|
172
|
+
# ]
|
173
|
+
# ]
|
174
|
+
----
|
175
|
+
|
176
|
+
=== Defaults
|
177
|
+
|
178
|
+
To display defaults, use:
|
179
|
+
|
180
|
+
``` ruby
|
181
|
+
tone = Tone.new
|
182
|
+
tone.defaults
|
183
|
+
```
|
184
|
+
|
185
|
+
The above will output something similar to what you see below (minus the categorization) of key and value which will allow you to pick and choose the style or combination of styles you desire.
|
186
|
+
|
187
|
+
* *Styles*
|
188
|
+
** `clear`
|
189
|
+
** `bold`
|
190
|
+
** `dim`
|
191
|
+
** `italic`
|
192
|
+
** `underline`
|
193
|
+
** `inverse`
|
194
|
+
** `hidden`
|
195
|
+
** `strikethrough`
|
196
|
+
* *Foregrounds*
|
197
|
+
** `black`
|
198
|
+
** `red`
|
199
|
+
** `green`
|
200
|
+
** `yellow`
|
201
|
+
** `blue`
|
202
|
+
** `purple`
|
203
|
+
** `cyan`
|
204
|
+
** `white`
|
205
|
+
** `bright_black`
|
206
|
+
** `bright_red`
|
207
|
+
** `bright_green`
|
208
|
+
** `bright_yellow`
|
209
|
+
** `bright_blue`
|
210
|
+
** `bright_purple`
|
211
|
+
** `bright_cyan`
|
212
|
+
** `bright_white`
|
213
|
+
* *Backgrounds*
|
214
|
+
** `on_black`
|
215
|
+
** `on_red`
|
216
|
+
** `on_green`
|
217
|
+
** `on_yellow`
|
218
|
+
** `on_blue`
|
219
|
+
** `on_purple`
|
220
|
+
** `on_cyan`
|
221
|
+
** `on_white`
|
222
|
+
** `on_bright_black`
|
223
|
+
** `on_bright_red`
|
224
|
+
** `on_bright_green`
|
225
|
+
** `on_bright_yellow`
|
226
|
+
** `on_bright_blue`
|
227
|
+
** `on_bright_purple`
|
228
|
+
** `on_bright_cyan`
|
229
|
+
** `on_bright_white`
|
230
|
+
|
231
|
+
These are the defaults for which you can mix-n-match as desired to produce colorful output. For example, if you want black text on a green background with an underline, you could use:
|
232
|
+
|
233
|
+
```
|
234
|
+
tone = Tone.new
|
235
|
+
puts tone["Success!", :black, :on_green, :strikethrough]
|
236
|
+
```
|
237
|
+
|
238
|
+
==== Codes
|
239
|
+
|
240
|
+
For situations where you'd like to find a code (or codes) for a symbol you can use the following:
|
241
|
+
|
242
|
+
[source,ruby]
|
243
|
+
----
|
244
|
+
tone = Tone.new
|
245
|
+
|
246
|
+
tone.find_code :green # 32
|
247
|
+
tone.find_code :bogus # nil
|
248
|
+
tone.find_codes :green # [32]
|
249
|
+
tone.find_codes :red, :green, :blue # [31, 32, 34]
|
250
|
+
tone.find_codes :bogus, :invalid # [nil, nil]
|
251
|
+
----
|
252
|
+
|
253
|
+
==== Symbols
|
254
|
+
|
255
|
+
Much like with the codes, mentioned above, you can find a symbol (or symbols) for a code too:
|
256
|
+
|
257
|
+
[source,ruby]
|
258
|
+
----
|
259
|
+
tone = Tone.new
|
260
|
+
|
261
|
+
tone.find_symbol 32 # :green
|
262
|
+
tone.find_symbol 666 # nil
|
263
|
+
tone.find_symbols 32 # [:green]
|
264
|
+
tone.find_symbols 31, 32, 34 # [:red, :green, :blue]
|
265
|
+
tone.find_symbols 666, 999 # [nil, nil]
|
266
|
+
----
|
267
|
+
|
268
|
+
=== Aliases
|
269
|
+
|
270
|
+
You can alias combinations of default styles with a descriptive name for shorthand reuse. This allows you to reduce duplicated effort and speed up your workflow. Here are a few examples:
|
271
|
+
|
272
|
+
[source,ruby]
|
273
|
+
----
|
274
|
+
tone = Tone.new
|
275
|
+
tone.add_alias :success, :black, :on_green
|
276
|
+
tone.add_alias :failure, :white, :on_red
|
277
|
+
|
278
|
+
tone["Success!", :success] # "\e[30;42mSuccess!\e[0m"
|
279
|
+
tone["Failure!", :failure] # "\e[37;41mFailure!\e[0m"
|
280
|
+
----
|
281
|
+
|
282
|
+
Notice that the first argument is your alias and _all arguments after the first argument_ is the list of styles. Once added, both the `:success` and `:failure` aliases can immediately be used. You can also add multiple aliases, at once, by chaining your messages:
|
283
|
+
|
284
|
+
``` ruby
|
285
|
+
tone = Tone.new
|
286
|
+
.add_alias(:success, :black, :on_green)
|
287
|
+
.add_alias :failure, :white, :on_red
|
288
|
+
|
289
|
+
tone["Success!", :success] # "\e[30;42mSuccess!\e[0m"
|
290
|
+
tone["Failure!", :failure] # "\e[37;41mFailure!\e[0m"
|
291
|
+
```
|
292
|
+
|
293
|
+
Aliases -- and associated styles -- can be symbols or strings. The following, despite using strings, is identical to the above:
|
294
|
+
|
295
|
+
[source,ruby]
|
296
|
+
----
|
297
|
+
tone = Tone.new
|
298
|
+
.add_alias("success", "black", "on_green")
|
299
|
+
.add_alias "failure", "white", "on_red"
|
300
|
+
|
301
|
+
tone["Success!", :success] # "\e[30;42mSuccess!\e[0m"
|
302
|
+
tone["Failure!", :failure] # "\e[37;41mFailure!\e[0m"
|
303
|
+
----
|
304
|
+
|
305
|
+
To see the list of all aliases added, use:
|
306
|
+
|
307
|
+
[source,ruby]
|
308
|
+
----
|
309
|
+
tone = Tone.new.add_alias(:success, :black, :on_green).add_alias :failure, :white, :on_red
|
310
|
+
ap tone.aliases
|
311
|
+
|
312
|
+
# {
|
313
|
+
# :success => [
|
314
|
+
# :black,
|
315
|
+
# :on_green
|
316
|
+
# ],
|
317
|
+
# :failure => [
|
318
|
+
# :white,
|
319
|
+
# :on_red
|
320
|
+
# ]
|
321
|
+
# }
|
322
|
+
----
|
323
|
+
|
324
|
+
To get a specific alias, use:
|
325
|
+
|
326
|
+
[source,ruby]
|
327
|
+
----
|
328
|
+
tone = Tone.new.add_alias :success, :black, :on_green
|
329
|
+
tone.get_alias :success
|
330
|
+
|
331
|
+
# [:black, :on_green]
|
332
|
+
----
|
333
|
+
|
334
|
+
In the case of a default, you'll only get back the given key:
|
335
|
+
|
336
|
+
[source,ruby]
|
337
|
+
----
|
338
|
+
Tone.new.get_alias :green # :green
|
339
|
+
----
|
340
|
+
|
341
|
+
=== Errors
|
342
|
+
|
343
|
+
There are several checks performed which might result in a `Tone::Error` if not properly used. Here's a few examples of what you might see.
|
344
|
+
|
345
|
+
[source,ruby]
|
346
|
+
----
|
347
|
+
tone = Tone.new
|
348
|
+
|
349
|
+
tone.add_alias :bogus
|
350
|
+
# Alias must have styles: :bogus. (Tone::Error)
|
351
|
+
|
352
|
+
tone.add_alias :bogus, nil
|
353
|
+
# Alias must have styles: :bogus. (Tone::Error)
|
354
|
+
|
355
|
+
tone.add_alias :red, :red
|
356
|
+
# Alias mustn't duplicate (override) default: :red. (Tone::Error)
|
357
|
+
|
358
|
+
tone.add_alias :bogus, :invalid
|
359
|
+
# Invalid style (:invalid) for key (:bogus). (Tone::Error)
|
360
|
+
|
361
|
+
tone.add_alias :success, :black, :on_green
|
362
|
+
tone.add_alias :success, :black, :on_green
|
363
|
+
# Duplicate alias detected (already exists): :success. (Tone::Error)
|
364
|
+
|
365
|
+
tone.get_alias nil
|
366
|
+
# Invalid alias or default: nil. (Tone::Error)
|
367
|
+
|
368
|
+
tone.get_alias :bogus
|
369
|
+
# Invalid alias or default: :bogus. (Tone::Error)
|
370
|
+
----
|
371
|
+
|
372
|
+
=== Guidelines
|
373
|
+
|
374
|
+
The following are worth considering, when using this gem, to help keep your implementation consistent.
|
375
|
+
|
376
|
+
Order your arguments by style, foreground, and background when encoding:
|
377
|
+
|
378
|
+
[source,ruby]
|
379
|
+
----
|
380
|
+
# No
|
381
|
+
tone["test, :underline, :on_black, :white]
|
382
|
+
tone["test, :white, :underline, :on_black]
|
383
|
+
tone["test, :on_black, :white, :underline]
|
384
|
+
|
385
|
+
# Yes
|
386
|
+
tone["test, :underline, :white, :on_black]
|
387
|
+
----
|
388
|
+
|
389
|
+
Order your arguments by style, foreground, and background when adding aliases:
|
390
|
+
|
391
|
+
[source,ruby]
|
392
|
+
----
|
393
|
+
# No
|
394
|
+
tone.add_alias :demo, :underline, :on_black, :white
|
395
|
+
tone.add_alias :demo, :white, :underline, :on_black
|
396
|
+
tone.add_alias :demo, :on_black, :white, :underline
|
397
|
+
|
398
|
+
# Yes
|
399
|
+
tone.add_alias :demo, :underline, :white, :on_black
|
400
|
+
----
|
401
|
+
|
402
|
+
These are not hard requirements but these little touches will help improve readability. 🎉
|
403
|
+
|
404
|
+
== Development
|
405
|
+
|
406
|
+
To contribute, run:
|
407
|
+
|
408
|
+
[source,bash]
|
409
|
+
----
|
410
|
+
git clone https://github.com/bkuhlmann/tone
|
411
|
+
cd tone
|
412
|
+
bin/setup
|
413
|
+
----
|
414
|
+
|
415
|
+
You use the IRB console for direct access to all objects:
|
416
|
+
|
417
|
+
[source,bash]
|
418
|
+
----
|
419
|
+
bin/console
|
420
|
+
----
|
421
|
+
|
422
|
+
Lastly, there is a `bin/show` script which can be run to display all default styles for quick visual convenience:
|
423
|
+
|
424
|
+
[source,bash]
|
425
|
+
----
|
426
|
+
bin/show
|
427
|
+
----
|
428
|
+
|
429
|
+
== Tests
|
430
|
+
|
431
|
+
To test, run:
|
432
|
+
|
433
|
+
[source,bash]
|
434
|
+
----
|
435
|
+
bin/rake
|
436
|
+
----
|
437
|
+
|
438
|
+
== link:https://alchemists.io/policies/license[License]
|
439
|
+
|
440
|
+
== link:https://alchemists.io/policies/security[Security]
|
441
|
+
|
442
|
+
== link:https://alchemists.io/policies/code_of_conduct[Code of Conduct]
|
443
|
+
|
444
|
+
== link:https://alchemists.io/policies/contributions[Contributions]
|
445
|
+
|
446
|
+
== link:https://alchemists.io/projects/tone/versions[Versions]
|
447
|
+
|
448
|
+
== link:https://alchemists.io/community[Community]
|
449
|
+
|
450
|
+
== Credits
|
451
|
+
|
452
|
+
* Built with link:https://alchemists.io/projects/gemsmith[Gemsmith].
|
453
|
+
* Engineered by link:https://alchemists.io/team/brooke_kuhlmann[Brooke Kuhlmann].
|
data/lib/tone/aliaser.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "refinements/arrays"
|
4
|
+
|
5
|
+
module Tone
|
6
|
+
# Allows storage of custom custom which can be referenced when colorizing text.
|
7
|
+
class Aliaser
|
8
|
+
using Refinements::Arrays
|
9
|
+
|
10
|
+
attr_reader :defaults
|
11
|
+
|
12
|
+
def initialize defaults: DEFAULTS
|
13
|
+
@defaults = defaults
|
14
|
+
@custom = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def get key
|
18
|
+
symbol = String(key).to_sym
|
19
|
+
|
20
|
+
custom.fetch symbol do
|
21
|
+
return key if defaults.key? symbol
|
22
|
+
|
23
|
+
usage = defaults.keys.append(*custom.keys).map(&:inspect).to_sentence conjunction: "and/or"
|
24
|
+
|
25
|
+
fail Error, "Invalid alias or default: #{key.inspect}. Use: #{usage}."
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def add(key, *styles)
|
30
|
+
fail Error, "Alias must have styles: #{key.inspect}." if styles.tap(&:compact!).empty?
|
31
|
+
|
32
|
+
custom[key.to_sym] = validate key, styles.map(&:to_sym)
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_h = custom.dup
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :custom
|
41
|
+
|
42
|
+
def validate key, styles
|
43
|
+
check_duplicate key
|
44
|
+
styles.each { |style| check_style key, style }
|
45
|
+
styles
|
46
|
+
end
|
47
|
+
|
48
|
+
def check_duplicate key
|
49
|
+
kind = key.inspect
|
50
|
+
|
51
|
+
fail Error, "Duplicate alias detected (already exists): #{kind}." if custom.key? key
|
52
|
+
fail Error, "Alias mustn't duplicate (override) default: #{kind}." if defaults.key? key
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_style key, style
|
56
|
+
defaults.fetch style do
|
57
|
+
usage = defaults.keys.map(&:inspect).to_sentence conjunction: "and/or"
|
58
|
+
|
59
|
+
fail Error, "Invalid style (#{style.inspect}) for key (#{key.inspect}). Use: #{usage}."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/tone/client.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tone
|
4
|
+
# The primary interface for working with colorized text.
|
5
|
+
class Client
|
6
|
+
def initialize enabled: $stdout.tty?, container: Tone::CONTAINER
|
7
|
+
@aliaser = container.fetch(:aliaser).new defaults: container.fetch(:defaults)
|
8
|
+
@encoder = container.fetch(:encoder).new(aliaser:, enabled:)
|
9
|
+
@decoder = container.fetch(:decoder).new defaults: aliaser.defaults
|
10
|
+
end
|
11
|
+
|
12
|
+
def defaults = aliaser.defaults
|
13
|
+
|
14
|
+
def aliases = aliaser.to_h
|
15
|
+
|
16
|
+
def add_alias(...)
|
17
|
+
aliaser.add(...)
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_alias(...) = aliaser.get(...)
|
22
|
+
|
23
|
+
def encode(...) = encoder.call(...)
|
24
|
+
|
25
|
+
alias [] encode
|
26
|
+
|
27
|
+
def decode(...) = decoder.call(...)
|
28
|
+
|
29
|
+
def find_code(key) = defaults[key]
|
30
|
+
|
31
|
+
def find_codes(*keys) = defaults.values_at(*keys)
|
32
|
+
|
33
|
+
def find_symbol(code) = defaults.invert[code]
|
34
|
+
|
35
|
+
def find_symbols(*codes) = defaults.invert.values_at(*codes)
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :aliaser, :encoder, :decoder
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
clear: 0
|
2
|
+
bold: 1
|
3
|
+
dim: 2
|
4
|
+
italic: 3
|
5
|
+
underline: 4
|
6
|
+
inverse: 7
|
7
|
+
hidden: 8
|
8
|
+
strikethrough: 9
|
9
|
+
|
10
|
+
black: 30
|
11
|
+
red: 31
|
12
|
+
green: 32
|
13
|
+
yellow: 33
|
14
|
+
blue: 34
|
15
|
+
purple: 35
|
16
|
+
cyan: 36
|
17
|
+
white: 37
|
18
|
+
|
19
|
+
bright_black: 90
|
20
|
+
bright_red: 91
|
21
|
+
bright_green: 92
|
22
|
+
bright_yellow: 93
|
23
|
+
bright_blue: 94
|
24
|
+
bright_purple: 95
|
25
|
+
bright_cyan: 96
|
26
|
+
bright_white: 97
|
27
|
+
|
28
|
+
on_black: 40
|
29
|
+
on_red: 41
|
30
|
+
on_green: 42
|
31
|
+
on_yellow: 43
|
32
|
+
on_blue: 44
|
33
|
+
on_purple: 45
|
34
|
+
on_cyan: 46
|
35
|
+
on_white: 47
|
36
|
+
|
37
|
+
on_bright_black: 100
|
38
|
+
on_bright_red: 101
|
39
|
+
on_bright_green: 102
|
40
|
+
on_bright_yellow: 103
|
41
|
+
on_bright_blue: 104
|
42
|
+
on_bright_purple: 105
|
43
|
+
on_bright_cyan: 106
|
44
|
+
on_bright_white: 107
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module Tone
|
6
|
+
module Configuration
|
7
|
+
# Loads the default configuration into memory as a frozen hash.
|
8
|
+
class Loader
|
9
|
+
def initialize path: Pathname("#{__dir__}/defaults.yml")
|
10
|
+
@path = path
|
11
|
+
end
|
12
|
+
|
13
|
+
def call = YAML.safe_load(path.read, symbolize_names: true).freeze
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_reader :path
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/tone/decoder.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "strscan"
|
4
|
+
|
5
|
+
module Tone
|
6
|
+
# Decodes color encoded text into metadata (hash).
|
7
|
+
class Decoder
|
8
|
+
PATTERN = /
|
9
|
+
\e\[ # Start prefix.
|
10
|
+
(?<codes>[\d;]+) # Style codes.
|
11
|
+
m # Start suffix.
|
12
|
+
(?<text>.+?) # Lazy text.
|
13
|
+
\e\[0m # Stop.
|
14
|
+
/mx
|
15
|
+
|
16
|
+
def initialize pattern: PATTERN, defaults: DEFAULTS, client: StringScanner
|
17
|
+
@pattern = pattern
|
18
|
+
@defaults = defaults
|
19
|
+
@client = client
|
20
|
+
@prefix_pattern = /.*#{pattern}/m
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(text) = scan client.new(String(text))
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :pattern, :defaults, :client, :prefix_pattern
|
28
|
+
|
29
|
+
def scan scanner, collection: []
|
30
|
+
until scanner.eos?
|
31
|
+
result = scanner.scan_until pattern
|
32
|
+
|
33
|
+
return collection.append [scanner.string[scanner.rest]] unless result
|
34
|
+
|
35
|
+
normal = scanner.pre_match.sub prefix_pattern, ""
|
36
|
+
|
37
|
+
collection << [normal] unless normal.empty?
|
38
|
+
collection << extract_captures(scanner)
|
39
|
+
end
|
40
|
+
|
41
|
+
collection
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract_captures scanner
|
45
|
+
codes, text = scanner.captures
|
46
|
+
[text, *symbolize(codes)]
|
47
|
+
end
|
48
|
+
|
49
|
+
def symbolize(codes) = defaults.invert.values_at(*String(codes).split(";").map(&:to_i))
|
50
|
+
end
|
51
|
+
end
|
data/lib/tone/encoder.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "refinements/arrays"
|
4
|
+
|
5
|
+
module Tone
|
6
|
+
# Encodes plain text as colorized text.
|
7
|
+
class Encoder
|
8
|
+
using Refinements::Arrays
|
9
|
+
|
10
|
+
def initialize aliaser: Aliaser.new, enabled: $stdout.tty?
|
11
|
+
@aliaser = aliaser
|
12
|
+
@enabled = enabled
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(text, *styles)
|
16
|
+
return "" if String(text).empty?
|
17
|
+
|
18
|
+
!enabled || styles.tap(&:compact!).empty? ? text : "#{start(*styles)}#{text}#{stop}"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :aliaser, :enabled
|
24
|
+
|
25
|
+
def start(*styles) = %(\e[#{escape(*styles)}m)
|
26
|
+
|
27
|
+
def stop = "\e[#{defaults.fetch :clear}m"
|
28
|
+
|
29
|
+
def escape(*styles)
|
30
|
+
styles.reduce([]) { |expansion, key| expansion.append(*aliaser.get(key)) }
|
31
|
+
.map { |key| defaults[key.to_sym] }
|
32
|
+
.join ";"
|
33
|
+
end
|
34
|
+
|
35
|
+
def defaults = aliaser.defaults
|
36
|
+
end
|
37
|
+
end
|
data/lib/tone/error.rb
ADDED
data/lib/tone.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zeitwerk"
|
4
|
+
|
5
|
+
Zeitwerk::Loader.for_gem.setup
|
6
|
+
|
7
|
+
# Main namespace.
|
8
|
+
module Tone
|
9
|
+
DEFAULTS = Configuration::Loader.new.call
|
10
|
+
CONTAINER = {defaults: DEFAULTS, aliaser: Aliaser, encoder: Encoder, decoder: Decoder}.freeze
|
11
|
+
|
12
|
+
def self.new(...) = Client.new(...)
|
13
|
+
end
|
data/tone.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "tone"
|
5
|
+
spec.version = "0.0.0"
|
6
|
+
spec.authors = ["Brooke Kuhlmann"]
|
7
|
+
spec.email = ["brooke@alchemists.io"]
|
8
|
+
spec.homepage = "https://alchemists.io/projects/tone"
|
9
|
+
spec.summary = "A customizable ANSI text colorizer for your terminal."
|
10
|
+
spec.license = "Hippocratic-2.1"
|
11
|
+
|
12
|
+
spec.metadata = {
|
13
|
+
"bug_tracker_uri" => "https://github.com/bkuhlmann/tone/issues",
|
14
|
+
"changelog_uri" => "https://alchemists.io/projects/tone/versions",
|
15
|
+
"documentation_uri" => "https://alchemists.io/projects/tone",
|
16
|
+
"funding_uri" => "https://github.com/sponsors/bkuhlmann",
|
17
|
+
"label" => "Tone",
|
18
|
+
"rubygems_mfa_required" => "true",
|
19
|
+
"source_code_uri" => "https://github.com/bkuhlmann/tone"
|
20
|
+
}
|
21
|
+
|
22
|
+
spec.signing_key = Gem.default_key_path
|
23
|
+
spec.cert_chain = [Gem.default_cert_path]
|
24
|
+
|
25
|
+
spec.required_ruby_version = "~> 3.2"
|
26
|
+
spec.add_dependency "refinements", "~> 10.0"
|
27
|
+
spec.add_dependency "zeitwerk", "~> 2.6"
|
28
|
+
|
29
|
+
spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
|
30
|
+
spec.files = Dir["*.gemspec", "lib/**/*"]
|
31
|
+
end
|
data.tar.gz.sig
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tone
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brooke Kuhlmann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIEeDCCAuCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBBMQ8wDQYDVQQDDAZicm9v
|
14
|
+
a2UxGjAYBgoJkiaJk/IsZAEZFgphbGNoZW1pc3RzMRIwEAYKCZImiZPyLGQBGRYC
|
15
|
+
aW8wHhcNMjMwMzIyMTYxNDQxWhcNMjUwMzIxMTYxNDQxWjBBMQ8wDQYDVQQDDAZi
|
16
|
+
cm9va2UxGjAYBgoJkiaJk/IsZAEZFgphbGNoZW1pc3RzMRIwEAYKCZImiZPyLGQB
|
17
|
+
GRYCaW8wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCro8tj5/E1Hg88
|
18
|
+
f4qfiwPVd2zJQHvdYt4GHVvuHRRgx4HGhJuNp+4BId08RBn7V6V1MW6MY3kezRBs
|
19
|
+
M+7QOQ4b1xNLTvY7FYQB1wGK5a4x7TTokDrPYQxDB2jmsdDYCzVbIMrAvUfcecRi
|
20
|
+
khyGZCdByiiCl4fKv77P12tTT+NfsvXkLt/AYCGwjOUyGKTQ01Z6eC09T27GayPH
|
21
|
+
QQvIkakyFgcJtzSyGzs8bzK5q9u7wQ12MNTjJoXzW69lqp0oNvDylu81EiSUb5S6
|
22
|
+
QzzPxZBiRB1sgtbt1gUbVI262ZDq1gR+HxPFmp+Cgt7ZLIJZAtesQvtcMzseXpfn
|
23
|
+
hpmm0Sw22KGhRAy/mqHBRhDl5HqS1SJp2Ko3lcnpXeFResp0HNlt8NSu13vhC08j
|
24
|
+
GUHU9MyIXbFOsnp3K3ADrAVjPWop8EZkmUR3MV/CUm00w2cZHCSGiXl1KMpiVKvk
|
25
|
+
Ywr1gd2ZME4QLSo+EXUtLxDUa/W3xnBS8dBOuMMz02FPWYr3PN8CAwEAAaN7MHkw
|
26
|
+
CQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFAFgmv0tYMZnItuPycSM
|
27
|
+
F5wykJEVMB8GA1UdEQQYMBaBFGJyb29rZUBhbGNoZW1pc3RzLmlvMB8GA1UdEgQY
|
28
|
+
MBaBFGJyb29rZUBhbGNoZW1pc3RzLmlvMA0GCSqGSIb3DQEBCwUAA4IBgQAX+EGY
|
29
|
+
9RLYGxF1VLZz+G1ACQc4uyrCB6kXwI06kzUa5dF9tPXqTX9ffnz3/W8ck2IQhKzu
|
30
|
+
MKO2FVijzbDWTsZeZGglS4E+4Jxpau1lU9HhOIcKolv6LeC6UdALTFudY+GLb8Xw
|
31
|
+
REXgaJkjzzhkUSILmEnRwEbY08dVSl7ZAaxVI679vfI2yapLlIwpbBgmQTiTvPr3
|
32
|
+
qyyLUno9flYEOv9fmGHunSrM+gE0/0niGTXa5GgXBXYGS2he4LQGgSBfGp/cTwMU
|
33
|
+
rDKJRcusZ12lNBeDfgqACz/BBJF8FLodgk6rGMRZz7+ZmjjHEmpG5bQpR6Q2BuWL
|
34
|
+
XMtYk/QzaWuhiR7pWjiF8jbdd7RO6or0ohq7iFkokz/5xrtQ/vPzU2RQ3Qc6YaKw
|
35
|
+
3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
|
36
|
+
gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
|
37
|
+
-----END CERTIFICATE-----
|
38
|
+
date: 2023-04-01 00:00:00.000000000 Z
|
39
|
+
dependencies:
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: refinements
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '10.0'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: zeitwerk
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2.6'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.6'
|
68
|
+
description:
|
69
|
+
email:
|
70
|
+
- brooke@alchemists.io
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files:
|
74
|
+
- README.adoc
|
75
|
+
- LICENSE.adoc
|
76
|
+
files:
|
77
|
+
- LICENSE.adoc
|
78
|
+
- README.adoc
|
79
|
+
- lib/tone.rb
|
80
|
+
- lib/tone/aliaser.rb
|
81
|
+
- lib/tone/client.rb
|
82
|
+
- lib/tone/configuration/defaults.yml
|
83
|
+
- lib/tone/configuration/loader.rb
|
84
|
+
- lib/tone/decoder.rb
|
85
|
+
- lib/tone/encoder.rb
|
86
|
+
- lib/tone/error.rb
|
87
|
+
- tone.gemspec
|
88
|
+
homepage: https://alchemists.io/projects/tone
|
89
|
+
licenses:
|
90
|
+
- Hippocratic-2.1
|
91
|
+
metadata:
|
92
|
+
bug_tracker_uri: https://github.com/bkuhlmann/tone/issues
|
93
|
+
changelog_uri: https://alchemists.io/projects/tone/versions
|
94
|
+
documentation_uri: https://alchemists.io/projects/tone
|
95
|
+
funding_uri: https://github.com/sponsors/bkuhlmann
|
96
|
+
label: Tone
|
97
|
+
rubygems_mfa_required: 'true'
|
98
|
+
source_code_uri: https://github.com/bkuhlmann/tone
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - "~>"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '3.2'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubygems_version: 3.4.10
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: A customizable ANSI text colorizer for your terminal.
|
118
|
+
test_files: []
|
metadata.gz.sig
ADDED
Binary file
|