paintbrush 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -0
- data/lib/paintbrush/bounded_color_element.rb +49 -0
- data/lib/paintbrush/color_element.rb +27 -0
- data/lib/paintbrush/colorized_string.rb +24 -11
- data/lib/paintbrush/colors.rb +1 -9
- data/lib/paintbrush/element_tree.rb +46 -0
- data/lib/paintbrush/escapes.rb +15 -0
- data/lib/paintbrush/version.rb +1 -1
- data/lib/paintbrush.rb +8 -2
- data/rspec-documentation/bundle/introduction.html +312 -0
- data/rspec-documentation/pages/Introduction.md +36 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb568b4656208e4b1d5e134b9a6982a50be63f9da4a776aa7210a302f65a59ce
|
4
|
+
data.tar.gz: cc92c16814e12eb90e089c5affaa6c4739ecbec1f9121093739c6e776e2aaf0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbc3a7c11aedf89c5191e1a538b902235c84e7a540b7d155ee008c1ad58e56a2eb4f139f151d681f06ba93fc7345221130ba0972d7d331ac6e793ef8b7752172
|
7
|
+
data.tar.gz: c2bc6bb3a2e09ec5c9aa2d25c47f1b118cf01e2d10eef340e430806531c05421b11e7292d677d96f12112f1d252d64cb1c673a1f50bcf99d6ac8c0a493a98116
|
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Paintbrush
|
4
|
+
# Wraps a Paintbrush::ColorElement instance and maps its start and end boundaries within a
|
5
|
+
# compiled escaped string by matching specific unique (indexed) escape codes. Provides
|
6
|
+
# `#surround?` for detecting if another element exists within the current element's boundaries.
|
7
|
+
class BoundedColorElement
|
8
|
+
def initialize(color_element:, escaped_output:)
|
9
|
+
@color_element = color_element
|
10
|
+
@escaped_output = escaped_output
|
11
|
+
end
|
12
|
+
|
13
|
+
def surround?(element)
|
14
|
+
return false if element == self
|
15
|
+
return false unless element.open_index.between?(open_index, close_index)
|
16
|
+
return false unless element.close_index.between?(open_index, close_index)
|
17
|
+
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"<#{self.class} boundaries=#{boundaries}>"
|
23
|
+
end
|
24
|
+
|
25
|
+
def index
|
26
|
+
color_element.index
|
27
|
+
end
|
28
|
+
|
29
|
+
def code
|
30
|
+
color_element.code
|
31
|
+
end
|
32
|
+
|
33
|
+
def boundaries
|
34
|
+
@boundaries ||= [open_index, close_index]
|
35
|
+
end
|
36
|
+
|
37
|
+
def open_index
|
38
|
+
@open_index ||= escaped_output.index(Escapes.open(index))
|
39
|
+
end
|
40
|
+
|
41
|
+
def close_index
|
42
|
+
escaped_output.index(Escapes.close(index))
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
attr_reader :escaped_output, :color_element
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Paintbrush
|
4
|
+
# Provides a substring enclosed in unique escape codes for later colorization when the full
|
5
|
+
# string has been created and all interpolation is completed. Adds itself to a provided stack
|
6
|
+
# of ColorElement objects on initialization.
|
7
|
+
class ColorElement
|
8
|
+
attr_reader :stack, :code, :string, :index
|
9
|
+
attr_accessor :open_index, :close_index
|
10
|
+
|
11
|
+
def initialize(stack:, code:, string:)
|
12
|
+
@stack = stack
|
13
|
+
@code = code
|
14
|
+
@string = string
|
15
|
+
@index = stack.size
|
16
|
+
stack << self
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#{Escapes.open(index)}#{string}#{Escapes.close(index)}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
"<#{self.class.name} index=#{index} code=#{code}>"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -7,7 +7,7 @@ module Paintbrush
|
|
7
7
|
class ColorizedString
|
8
8
|
def initialize(&block)
|
9
9
|
@block = block
|
10
|
-
@
|
10
|
+
@stack = []
|
11
11
|
end
|
12
12
|
|
13
13
|
# Returns a colorized string by injecting escape codes into the various calls to each color
|
@@ -19,30 +19,43 @@ module Paintbrush
|
|
19
19
|
|
20
20
|
private
|
21
21
|
|
22
|
-
attr_reader :block, :
|
22
|
+
attr_reader :block, :stack
|
23
23
|
|
24
|
-
def colorized_string
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
def colorized_string(string: escaped_output, tree: element_tree)
|
25
|
+
tree[:children].reduce(string) do |output, child|
|
26
|
+
subbed = subbed_string(output, child[:node], tree[:node])
|
27
|
+
next subbed if child[:children].empty?
|
28
|
+
|
29
|
+
colorized_string(string: subbed, tree: child)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def bounded_color_elements
|
34
|
+
@bounded_color_elements ||= stack.map do |color_element|
|
35
|
+
BoundedColorElement.new(color_element: color_element, escaped_output: escaped_output)
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
31
|
-
def
|
39
|
+
def element_tree
|
40
|
+
@element_tree ||= ElementTree.new(bounded_color_elements: bounded_color_elements).tree
|
41
|
+
end
|
42
|
+
|
43
|
+
def subbed_string(string, color_element, parent_color_element)
|
44
|
+
restored_color_code = parent_color_element.nil? ? '0' : parent_color_element.code
|
32
45
|
string
|
33
|
-
.sub(
|
34
|
-
.sub(
|
46
|
+
.sub(Escapes.open(color_element.index).to_s, "\e[#{color_element.code}m")
|
47
|
+
.sub(Escapes.close(color_element.index).to_s, "\e[0m\e[#{restored_color_code}m")
|
35
48
|
end
|
36
49
|
|
37
50
|
def escaped_output
|
38
|
-
context.instance_eval(&block)
|
51
|
+
@escaped_output ||= context.instance_eval(&block)
|
39
52
|
end
|
40
53
|
|
41
54
|
def context
|
42
55
|
eval('self', block.binding, __FILE__, __LINE__).dup.tap do |context|
|
43
56
|
context.send(:include, Paintbrush::Colors) if context.respond_to?(:include)
|
44
57
|
context.send(:extend, Paintbrush::Colors) if context.respond_to?(:extend)
|
45
|
-
context.send(:instance_variable_set, :@
|
58
|
+
context.send(:instance_variable_set, :@__stack, stack)
|
46
59
|
end
|
47
60
|
end
|
48
61
|
end
|
data/lib/paintbrush/colors.rb
CHANGED
@@ -6,11 +6,6 @@ module Paintbrush
|
|
6
6
|
# string to be reconstituted afterwards with nested strings restoring the previous color once
|
7
7
|
# they have terminated.
|
8
8
|
module Colors
|
9
|
-
ESCAPE_START_OPEN = "\e[3;15;17]OPEN:"
|
10
|
-
ESCAPE_START_CLOSE = "\e[3;15;17]CLOSE:"
|
11
|
-
ESCAPE_END_OPEN = "\e[17;15;3]OPEN:"
|
12
|
-
ESCAPE_END_CLOSE = "\e[17;15;3]CLOSE:"
|
13
|
-
|
14
9
|
COLOR_CODES = {
|
15
10
|
black: '30',
|
16
11
|
red: '31',
|
@@ -25,10 +20,7 @@ module Paintbrush
|
|
25
20
|
|
26
21
|
COLOR_CODES.each do |name, code|
|
27
22
|
define_method name do |string|
|
28
|
-
|
29
|
-
"#{ESCAPE_START_OPEN}#{@__codes.size - 1}#{ESCAPE_START_CLOSE}" \
|
30
|
-
"#{string}" \
|
31
|
-
"#{ESCAPE_END_OPEN}#{@__codes.size - 1}#{ESCAPE_END_CLOSE}"
|
23
|
+
ColorElement.new(stack: @__stack, code: code, string: string).to_s
|
32
24
|
end
|
33
25
|
end
|
34
26
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Paintbrush
|
4
|
+
# A tree of BoundedColorElement objects. Used to build a full tree of colorized substrings in
|
5
|
+
# order to allow discovery of parent substrings and use their color code to restore to when the
|
6
|
+
# substring is terminated. Allows deeply-nested colorized strings.
|
7
|
+
class ElementTree
|
8
|
+
attr_reader :tree
|
9
|
+
|
10
|
+
def initialize(bounded_color_elements:)
|
11
|
+
@bounded_color_elements = bounded_color_elements
|
12
|
+
@tree = { node: nil, children: [] }
|
13
|
+
build_tree(boundary_end: bounded_color_elements.map(&:close_index).max)
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_tree(boundary_end:, root: @tree, elements: bounded_color_elements, boundary_start: 0)
|
17
|
+
root_nodes, non_root_nodes = partitioned_elements(elements, boundary_start, boundary_end)
|
18
|
+
|
19
|
+
root_nodes.each do |node|
|
20
|
+
root[:children] << child_node(node)
|
21
|
+
build_tree(
|
22
|
+
root: root[:children].last,
|
23
|
+
elements: non_root_nodes,
|
24
|
+
boundary_start: node.open_index,
|
25
|
+
boundary_end: node.close_index
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :bounded_color_elements
|
33
|
+
|
34
|
+
def child_node(node)
|
35
|
+
{ node: node, children: [] }
|
36
|
+
end
|
37
|
+
|
38
|
+
def partitioned_elements(elements, boundary_start, boundary_end)
|
39
|
+
elements.partition do |element|
|
40
|
+
next false if elements.any? { |child| child.surround?(element) }
|
41
|
+
|
42
|
+
element.boundaries.all? { |index| index.between?(boundary_start, boundary_end) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Paintbrush
|
4
|
+
# Provides an authority on escape code generation. Provides `.close` and `.open`, both of which
|
5
|
+
# receive an index (i.e. the current size of the stack). Used for escape code insertion and comparison.
|
6
|
+
module Escapes
|
7
|
+
def self.open(index)
|
8
|
+
"\e[3;15;17]START_OPEN:#{index}:\e[3;15;17]START_CLOSE"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.close(index)
|
12
|
+
"\e[17;15;3]END_OPEN:#{index}:\e[17;15;3]END_CLOSE"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/paintbrush/version.rb
CHANGED
data/lib/paintbrush.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'paintbrush/version'
|
4
|
+
require_relative 'paintbrush/escapes'
|
4
5
|
require_relative 'paintbrush/colors'
|
5
6
|
require_relative 'paintbrush/colorized_string'
|
7
|
+
require_relative 'paintbrush/color_element'
|
8
|
+
require_relative 'paintbrush/bounded_color_element'
|
9
|
+
require_relative 'paintbrush/element_tree'
|
6
10
|
|
7
11
|
# Colorizes a string, provides `#paintbrush`. When included/extended in a class, call
|
8
12
|
# `#paintbrush` and pass a block to use the provided dynamically defined methods, e.g.:
|
@@ -16,9 +20,11 @@ require_relative 'paintbrush/colorized_string'
|
|
16
20
|
# end
|
17
21
|
# ```
|
18
22
|
module Paintbrush
|
19
|
-
|
23
|
+
def self.paintbrush(&block)
|
24
|
+
ColorizedString.new(&block).colorized
|
25
|
+
end
|
20
26
|
|
21
27
|
def paintbrush(&block)
|
22
|
-
|
28
|
+
Paintbrush.paintbrush(&block)
|
23
29
|
end
|
24
30
|
end
|
@@ -0,0 +1,312 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<link rel="stylesheet"
|
4
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css"
|
5
|
+
integrity="sha512-SbiR/eusphKoMVVXysTKG/7VseWii+Y3FdHrt0EpKgpToZeemhqHeZeLWLhJutz/2ut2Vw1uQEj2MbRF+TVBUA=="
|
6
|
+
crossorigin="anonymous"
|
7
|
+
referrerpolicy="no-referrer" />
|
8
|
+
<style>
|
9
|
+
|
10
|
+
.code {
|
11
|
+
font-family: monospace;
|
12
|
+
max-height: 30rem;
|
13
|
+
overflow-y: auto;
|
14
|
+
}
|
15
|
+
|
16
|
+
h1.title {
|
17
|
+
display: inline;
|
18
|
+
}
|
19
|
+
|
20
|
+
.header .separator {
|
21
|
+
display: inline-block;
|
22
|
+
height: 2.5rem;
|
23
|
+
}
|
24
|
+
|
25
|
+
.version {
|
26
|
+
color: #bbb;
|
27
|
+
font-size: 2rem;
|
28
|
+
}
|
29
|
+
|
30
|
+
.ansi-html {
|
31
|
+
display: inline-block;
|
32
|
+
background-color: #2e2e2e;
|
33
|
+
border: 5px solid #2e2e2e;
|
34
|
+
border-radius: 10px;
|
35
|
+
}
|
36
|
+
|
37
|
+
.ansi-html .ansi-color-0 { color: #555555; }
|
38
|
+
.ansi-html .ansi-color-1 { color: #ff0000; }
|
39
|
+
.ansi-html .ansi-color-2 { color: #47ff47; }
|
40
|
+
.ansi-html .ansi-color-3 { color: #e9e947; }
|
41
|
+
.ansi-html .ansi-color-4 { color: #49a0dd; }
|
42
|
+
.ansi-html .ansi-color-5 { color: #8d7eeb; }
|
43
|
+
.ansi-html .ansi-color-6 { color: #2eecff; }
|
44
|
+
.ansi-html .ansi-color-7 { color: #ffffff; }
|
45
|
+
.ansi-html .ansi-color-9 { color: #606060; }
|
46
|
+
.ansi-html .ansi-color-reset { color: #dddddd; }
|
47
|
+
|
48
|
+
.highlight table td { padding: 5px; }
|
49
|
+
.highlight table pre { margin: 0; }
|
50
|
+
.highlight, .highlight .w {
|
51
|
+
color: #24292f;
|
52
|
+
background-color: #f6f8fa;
|
53
|
+
}
|
54
|
+
.highlight .k, .highlight .kd, .highlight .kn, .highlight .kp, .highlight .kr, .highlight .kt, .highlight .kv {
|
55
|
+
color: #cf222e;
|
56
|
+
}
|
57
|
+
.highlight .gr {
|
58
|
+
color: #f6f8fa;
|
59
|
+
}
|
60
|
+
.highlight .gd {
|
61
|
+
color: #82071e;
|
62
|
+
background-color: #ffebe9;
|
63
|
+
}
|
64
|
+
.highlight .nb {
|
65
|
+
color: #953800;
|
66
|
+
}
|
67
|
+
.highlight .nc {
|
68
|
+
color: #953800;
|
69
|
+
}
|
70
|
+
.highlight .no {
|
71
|
+
color: #953800;
|
72
|
+
}
|
73
|
+
.highlight .nn {
|
74
|
+
color: #953800;
|
75
|
+
}
|
76
|
+
.highlight .sr {
|
77
|
+
color: #116329;
|
78
|
+
}
|
79
|
+
.highlight .na {
|
80
|
+
color: #116329;
|
81
|
+
}
|
82
|
+
.highlight .nt {
|
83
|
+
color: #116329;
|
84
|
+
}
|
85
|
+
.highlight .gi {
|
86
|
+
color: #116329;
|
87
|
+
background-color: #dafbe1;
|
88
|
+
}
|
89
|
+
.highlight .kc {
|
90
|
+
color: #0550ae;
|
91
|
+
}
|
92
|
+
.highlight .l, .highlight .ld, .highlight .m, .highlight .mb, .highlight .mf, .highlight .mh, .highlight .mi, .highlight .il, .highlight .mo, .highlight .mx {
|
93
|
+
color: #0550ae;
|
94
|
+
}
|
95
|
+
.highlight .sb {
|
96
|
+
color: #0550ae;
|
97
|
+
}
|
98
|
+
.highlight .bp {
|
99
|
+
color: #0550ae;
|
100
|
+
}
|
101
|
+
.highlight .ne {
|
102
|
+
color: #0550ae;
|
103
|
+
}
|
104
|
+
.highlight .nl {
|
105
|
+
color: #0550ae;
|
106
|
+
}
|
107
|
+
.highlight .py {
|
108
|
+
color: #0550ae;
|
109
|
+
}
|
110
|
+
.highlight .nv, .highlight .vc, .highlight .vg, .highlight .vi, .highlight .vm {
|
111
|
+
color: #0550ae;
|
112
|
+
}
|
113
|
+
.highlight .o, .highlight .ow {
|
114
|
+
color: #0550ae;
|
115
|
+
}
|
116
|
+
.highlight .gh {
|
117
|
+
color: #0550ae;
|
118
|
+
font-weight: bold;
|
119
|
+
}
|
120
|
+
.highlight .gu {
|
121
|
+
color: #0550ae;
|
122
|
+
font-weight: bold;
|
123
|
+
}
|
124
|
+
.highlight .s, .highlight .sa, .highlight .sc, .highlight .dl, .highlight .sd, .highlight .s2, .highlight .se, .highlight .sh, .highlight .sx, .highlight .s1, .highlight .ss {
|
125
|
+
color: #0a3069;
|
126
|
+
}
|
127
|
+
.highlight .nd {
|
128
|
+
color: #8250df;
|
129
|
+
}
|
130
|
+
.highlight .nf, .highlight .fm {
|
131
|
+
color: #8250df;
|
132
|
+
}
|
133
|
+
.highlight .err {
|
134
|
+
color: #f6f8fa;
|
135
|
+
background-color: #82071e;
|
136
|
+
}
|
137
|
+
.highlight .c, .highlight .ch, .highlight .cd, .highlight .cm, .highlight .cp, .highlight .cpf, .highlight .c1, .highlight .cs {
|
138
|
+
color: #6e7781;
|
139
|
+
}
|
140
|
+
.highlight .gl {
|
141
|
+
color: #6e7781;
|
142
|
+
}
|
143
|
+
.highlight .gt {
|
144
|
+
color: #6e7781;
|
145
|
+
}
|
146
|
+
.highlight .ni {
|
147
|
+
color: #24292f;
|
148
|
+
}
|
149
|
+
.highlight .si {
|
150
|
+
color: #24292f;
|
151
|
+
}
|
152
|
+
.highlight .ge {
|
153
|
+
color: #24292f;
|
154
|
+
font-style: italic;
|
155
|
+
}
|
156
|
+
.highlight .gs {
|
157
|
+
color: #24292f;
|
158
|
+
font-weight: bold;
|
159
|
+
}
|
160
|
+
|
161
|
+
</style>
|
162
|
+
</head>
|
163
|
+
|
164
|
+
<body>
|
165
|
+
<div class="container m-3 p-3">
|
166
|
+
<div class="header p-3 m-3 w-90 text-end">
|
167
|
+
<h1 class="title">paintbrush</h1>
|
168
|
+
<span class="separator border-end pb-2 ms-2 me-2"></span>
|
169
|
+
<span class="version">0.1.0</span>
|
170
|
+
</div>
|
171
|
+
|
172
|
+
<hr/>
|
173
|
+
|
174
|
+
|
175
|
+
<div class="row">
|
176
|
+
<div class="col-auto page-tree fs-6 mt-1 ms-3 me-3">
|
177
|
+
|
178
|
+
<li>
|
179
|
+
|
180
|
+
<a href='/home/bob/dev/paintbrush/rspec-documentation/bundle/introduction.html'>Introduction</a>
|
181
|
+
|
182
|
+
</li>
|
183
|
+
|
184
|
+
<ul>
|
185
|
+
|
186
|
+
</ul>
|
187
|
+
|
188
|
+
</div>
|
189
|
+
|
190
|
+
<div class="col">
|
191
|
+
<h1 id="paintbrush">Paintbrush</h1>
|
192
|
+
|
193
|
+
<p>Simple and concise string colorization for <em>Ruby</em> without overloading <code>String</code> methods or requiring verbose class/method invocation.</p>
|
194
|
+
|
195
|
+
<p><em>Paintbrush</em> has zero dependencies and does not pollute any namespaces or objects outside of the <code>#paintbrush</code> method wherever you include the <code>Paintbrush</code> module.</p>
|
196
|
+
|
197
|
+
<p>Nesting is supported, allowing you to use multiple colors within the same string. The previous color is automatically restored.</p>
|
198
|
+
|
199
|
+
<div location="9"><button type="button" class="btn btn-primary float-end" data-bs-toggle="modal" data-bs-target="#modal-15cae418-087d-45aa-b936-ea2c34033c01-side-by-side"> View Side-by-side </button> <div class="modal fade" id="modal-15cae418-087d-45aa-b936-ea2c34033c01-side-by-side" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
200
|
+
<div class="modal-dialog modal-xl">
|
201
|
+
<div class="modal-content">
|
202
|
+
<div class="modal-header">
|
203
|
+
<h5 class="modal-title" id="modal-15cae418-087d-45aa-b936-ea2c34033c01-side-by-side-label">Side-by-side view</h5>
|
204
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
205
|
+
</div>
|
206
|
+
<div class="modal-body">
|
207
|
+
<div class="container p-3">
|
208
|
+
<div class="row border">
|
209
|
+
<div class="col border">
|
210
|
+
<div class="p-3 mb-5 code highlight">
|
211
|
+
<span class="nb">require</span> <span class="s1">'paintbrush'</span><br /><br /><span class="kp">extend</span> <span class="no">Paintbrush</span><br /><br /><span class="n">output</span> <span class="o">=</span> <span class="n">paintbrush</span> <span class="p">{</span> <span class="n">purple</span> <span class="s2">"You used </span><span class="si">#{</span><span class="n">green</span> <span class="s1">'four'</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">blue</span> <span class="s2">"(</span><span class="si">#{</span><span class="n">cyan</span> <span class="s1">'4'</span><span class="si">}</span><span class="s2">)"</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">yellow</span> <span class="s1">'colors'</span><span class="si">}</span><span class="s2"> today!"</span> <span class="p">}</span><br /><span class="n">it_documents</span> <span class="n">output</span> <span class="k">do</span><br /> <span class="n">expect</span><span class="p">(</span><span class="n">output</span><span class="p">).</span><span class="nf">to</span> <span class="n">eql</span> <span class="s2">"</span><span class="se">\e</span><span class="s2">[35mYou used </span><span class="se">\e</span><span class="s2">[32mfour</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[35m "</span> <span class="p">\</span><br /> <span class="s2">"</span><span class="se">\e</span><span class="s2">[34m(</span><span class="se">\e</span><span class="s2">[36m4</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[34m)</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[35m "</span> <span class="p">\</span><br /> <span class="s2">"</span><span class="se">\e</span><span class="s2">[33mcolors</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[35m today!</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[0m"</span><br /><span class="k">end</span><br />
|
212
|
+
</div>
|
213
|
+
</div>
|
214
|
+
<div class="col border">
|
215
|
+
<div class="p-3 mb-5 code highlight">
|
216
|
+
<div class="ansi-html border m-1 p-4">
|
217
|
+
<span></span><span class="ansi-color-5">You used </span><span class="ansi-color-2">four</span><span class="ansi-color-reset"></span><span class="ansi-color-5"> </span><span class="ansi-color-4">(</span><span class="ansi-color-6">4</span><span class="ansi-color-reset"></span><span class="ansi-color-4">)</span><span class="ansi-color-reset"></span><span class="ansi-color-5"> </span><span class="ansi-color-3">colors</span><span class="ansi-color-reset"></span><span class="ansi-color-5"> today!</span><span class="ansi-color-reset"></span><span class="ansi-color-reset"></span>
|
218
|
+
</div>
|
219
|
+
</div>
|
220
|
+
</div>
|
221
|
+
</div>
|
222
|
+
</div>
|
223
|
+
</div>
|
224
|
+
<div class="modal-footer">
|
225
|
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
226
|
+
</div>
|
227
|
+
</div>
|
228
|
+
</div>
|
229
|
+
</div>
|
230
|
+
<ul class="nav nav-tabs" id="html-tabs-15cae418-087d-45aa-b936-ea2c34033c01" role="tablist">
|
231
|
+
<li class="nav-item" role="presentation"><button class="nav-link active" id="code-source-15cae418-087d-45aa-b936-ea2c34033c01-tab" data-bs-toggle="tab" data-bs-target="#code-source-15cae418-087d-45aa-b936-ea2c34033c01" type="button" role="tab" aria-controls="code-source" aria-selected="true">Code</button></li>
|
232
|
+
<li class="nav-item" role="presentation"><button class="nav-link" id="rendered-15cae418-087d-45aa-b936-ea2c34033c01-tab" data-bs-toggle="tab" data-bs-target="#rendered-15cae418-087d-45aa-b936-ea2c34033c01" type="button" role="tab" aria-controls="rendered" aria-selected="false">Output</button></li>
|
233
|
+
</ul>
|
234
|
+
<div class="tab-content" id="html-tab-content-15cae418-087d-45aa-b936-ea2c34033c01">
|
235
|
+
<div class="tab-pane fade show active" id="code-source-15cae418-087d-45aa-b936-ea2c34033c01" role="tabpanel" aria-labelledby="code-source-15cae418-087d-45aa-b936-ea2c34033c01-tab">
|
236
|
+
<div class="p-3 mb-5 code highlight">
|
237
|
+
<span class="nb">require</span> <span class="s1">'paintbrush'</span><br /><br /><span class="kp">extend</span> <span class="no">Paintbrush</span><br /><br /><span class="n">output</span> <span class="o">=</span> <span class="n">paintbrush</span> <span class="p">{</span> <span class="n">purple</span> <span class="s2">"You used </span><span class="si">#{</span><span class="n">green</span> <span class="s1">'four'</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">blue</span> <span class="s2">"(</span><span class="si">#{</span><span class="n">cyan</span> <span class="s1">'4'</span><span class="si">}</span><span class="s2">)"</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">yellow</span> <span class="s1">'colors'</span><span class="si">}</span><span class="s2"> today!"</span> <span class="p">}</span><br /><span class="n">it_documents</span> <span class="n">output</span> <span class="k">do</span><br /> <span class="n">expect</span><span class="p">(</span><span class="n">output</span><span class="p">).</span><span class="nf">to</span> <span class="n">eql</span> <span class="s2">"</span><span class="se">\e</span><span class="s2">[35mYou used </span><span class="se">\e</span><span class="s2">[32mfour</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[35m "</span> <span class="p">\</span><br /> <span class="s2">"</span><span class="se">\e</span><span class="s2">[34m(</span><span class="se">\e</span><span class="s2">[36m4</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[34m)</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[35m "</span> <span class="p">\</span><br /> <span class="s2">"</span><span class="se">\e</span><span class="s2">[33mcolors</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[35m today!</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[0m"</span><br /><span class="k">end</span><br />
|
238
|
+
</div>
|
239
|
+
</div>
|
240
|
+
<div class="tab-pane fade" id="rendered-15cae418-087d-45aa-b936-ea2c34033c01" role="tabpanel" aria-labelledby="rendered-15cae418-087d-45aa-b936-ea2c34033c01-tab">
|
241
|
+
<div class="p-3 mb-5 code highlight">
|
242
|
+
<div class="ansi-html border m-1 p-4">
|
243
|
+
<span></span><span class="ansi-color-5">You used </span><span class="ansi-color-2">four</span><span class="ansi-color-reset"></span><span class="ansi-color-5"> </span><span class="ansi-color-4">(</span><span class="ansi-color-6">4</span><span class="ansi-color-reset"></span><span class="ansi-color-4">)</span><span class="ansi-color-reset"></span><span class="ansi-color-5"> </span><span class="ansi-color-3">colors</span><span class="ansi-color-reset"></span><span class="ansi-color-5"> today!</span><span class="ansi-color-reset"></span><span class="ansi-color-reset"></span>
|
244
|
+
</div>
|
245
|
+
</div>
|
246
|
+
</div>
|
247
|
+
</div>
|
248
|
+
</div>
|
249
|
+
|
250
|
+
<div location="22"><button type="button" class="btn btn-primary float-end" data-bs-toggle="modal" data-bs-target="#modal-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0-side-by-side"> View Side-by-side </button> <div class="modal fade" id="modal-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0-side-by-side" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
251
|
+
<div class="modal-dialog modal-xl">
|
252
|
+
<div class="modal-content">
|
253
|
+
<div class="modal-header">
|
254
|
+
<h5 class="modal-title" id="modal-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0-side-by-side-label">Side-by-side view</h5>
|
255
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
256
|
+
</div>
|
257
|
+
<div class="modal-body">
|
258
|
+
<div class="container p-3">
|
259
|
+
<div class="row border">
|
260
|
+
<div class="col border">
|
261
|
+
<div class="p-3 mb-5 code highlight">
|
262
|
+
<span class="nb">require</span> <span class="s1">'paintbrush'</span><br /><br /><span class="kp">extend</span> <span class="no">Paintbrush</span><br /><br /><span class="n">output</span> <span class="o">=</span> <span class="n">paintbrush</span> <span class="k">do</span><br /> <span class="s2">"</span><span class="si">#{</span><span class="n">blue</span> <span class="s1">'foo'</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">green</span> <span class="s2">"bar </span><span class="si">#{</span><span class="n">cyan</span> <span class="sx">%w[foo bar baz]</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">', '</span><span class="p">)</span><span class="si">}</span><span class="s2"> with </span><span class="si">#{</span><span class="n">cyan</span> <span class="s1">'qux'</span><span class="si">}</span><span class="s2"> and quux"</span><span class="si">}</span><span class="s2"> and corge"</span><br /><span class="k">end</span><br /><br /><span class="n">it_documents</span> <span class="n">output</span> <span class="k">do</span><br /> <span class="n">expect</span><span class="p">(</span><span class="n">output</span><span class="p">).</span><span class="nf">to</span> <span class="n">eql</span> <span class="s2">"</span><span class="se">\e</span><span class="s2">[34mfoo</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[0m </span><span class="se">\e</span><span class="s2">[32mbar </span><span class="se">\e</span><span class="s2">[36mfoo, bar, baz"</span> <span class="p">\</span><br /> <span class="s2">"</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[32m with </span><span class="se">\e</span><span class="s2">[36mqux</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[32m "</span><span class="p">\</span><br /> <span class="s2">"and quux</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[0m and corge"</span><br /><span class="k">end</span><br />
|
263
|
+
</div>
|
264
|
+
</div>
|
265
|
+
<div class="col border">
|
266
|
+
<div class="p-3 mb-5 code highlight">
|
267
|
+
<div class="ansi-html border m-1 p-4">
|
268
|
+
<span></span><span class="ansi-color-4">foo</span><span class="ansi-color-reset"></span><span class="ansi-color-reset"> </span><span class="ansi-color-2">bar </span><span class="ansi-color-6">foo, bar, baz</span><span class="ansi-color-reset"></span><span class="ansi-color-2"> with </span><span class="ansi-color-6">qux</span><span class="ansi-color-reset"></span><span class="ansi-color-2"> and quux</span><span class="ansi-color-reset"></span><span class="ansi-color-reset"> and corge</span>
|
269
|
+
</div>
|
270
|
+
</div>
|
271
|
+
</div>
|
272
|
+
</div>
|
273
|
+
</div>
|
274
|
+
</div>
|
275
|
+
<div class="modal-footer">
|
276
|
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
277
|
+
</div>
|
278
|
+
</div>
|
279
|
+
</div>
|
280
|
+
</div>
|
281
|
+
<ul class="nav nav-tabs" id="html-tabs-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0" role="tablist">
|
282
|
+
<li class="nav-item" role="presentation"><button class="nav-link active" id="code-source-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0-tab" data-bs-toggle="tab" data-bs-target="#code-source-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0" type="button" role="tab" aria-controls="code-source" aria-selected="true">Code</button></li>
|
283
|
+
<li class="nav-item" role="presentation"><button class="nav-link" id="rendered-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0-tab" data-bs-toggle="tab" data-bs-target="#rendered-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0" type="button" role="tab" aria-controls="rendered" aria-selected="false">Output</button></li>
|
284
|
+
</ul>
|
285
|
+
<div class="tab-content" id="html-tab-content-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0">
|
286
|
+
<div class="tab-pane fade show active" id="code-source-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0" role="tabpanel" aria-labelledby="code-source-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0-tab">
|
287
|
+
<div class="p-3 mb-5 code highlight">
|
288
|
+
<span class="nb">require</span> <span class="s1">'paintbrush'</span><br /><br /><span class="kp">extend</span> <span class="no">Paintbrush</span><br /><br /><span class="n">output</span> <span class="o">=</span> <span class="n">paintbrush</span> <span class="k">do</span><br /> <span class="s2">"</span><span class="si">#{</span><span class="n">blue</span> <span class="s1">'foo'</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">green</span> <span class="s2">"bar </span><span class="si">#{</span><span class="n">cyan</span> <span class="sx">%w[foo bar baz]</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">', '</span><span class="p">)</span><span class="si">}</span><span class="s2"> with </span><span class="si">#{</span><span class="n">cyan</span> <span class="s1">'qux'</span><span class="si">}</span><span class="s2"> and quux"</span><span class="si">}</span><span class="s2"> and corge"</span><br /><span class="k">end</span><br /><br /><span class="n">it_documents</span> <span class="n">output</span> <span class="k">do</span><br /> <span class="n">expect</span><span class="p">(</span><span class="n">output</span><span class="p">).</span><span class="nf">to</span> <span class="n">eql</span> <span class="s2">"</span><span class="se">\e</span><span class="s2">[34mfoo</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[0m </span><span class="se">\e</span><span class="s2">[32mbar </span><span class="se">\e</span><span class="s2">[36mfoo, bar, baz"</span> <span class="p">\</span><br /> <span class="s2">"</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[32m with </span><span class="se">\e</span><span class="s2">[36mqux</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[32m "</span><span class="p">\</span><br /> <span class="s2">"and quux</span><span class="se">\e</span><span class="s2">[0m</span><span class="se">\e</span><span class="s2">[0m and corge"</span><br /><span class="k">end</span><br />
|
289
|
+
</div>
|
290
|
+
</div>
|
291
|
+
<div class="tab-pane fade" id="rendered-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0" role="tabpanel" aria-labelledby="rendered-c3e2bbb8-9a13-4400-93a1-0e6c9847cba0-tab">
|
292
|
+
<div class="p-3 mb-5 code highlight">
|
293
|
+
<div class="ansi-html border m-1 p-4">
|
294
|
+
<span></span><span class="ansi-color-4">foo</span><span class="ansi-color-reset"></span><span class="ansi-color-reset"> </span><span class="ansi-color-2">bar </span><span class="ansi-color-6">foo, bar, baz</span><span class="ansi-color-reset"></span><span class="ansi-color-2"> with </span><span class="ansi-color-6">qux</span><span class="ansi-color-reset"></span><span class="ansi-color-2"> and quux</span><span class="ansi-color-reset"></span><span class="ansi-color-reset"> and corge</span>
|
295
|
+
</div>
|
296
|
+
</div>
|
297
|
+
</div>
|
298
|
+
</div>
|
299
|
+
</div>
|
300
|
+
|
301
|
+
</div>
|
302
|
+
</div>
|
303
|
+
<hr/>
|
304
|
+
|
305
|
+
</div>
|
306
|
+
|
307
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.bundle.min.js"
|
308
|
+
integrity="sha512-i9cEfJwUwViEPFKdC1enz4ZRGBj8YQo6QByFTF92YXHi7waCqyexvRD75S5NVTsSiTv7rKWqG9Y5eFxmRsOn0A=="
|
309
|
+
crossorigin="anonymous"
|
310
|
+
referrerpolicy="no-referrer"></script>
|
311
|
+
</body>
|
312
|
+
</html>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Paintbrush
|
2
|
+
|
3
|
+
Simple and concise string colorization for _Ruby_ without overloading `String` methods or requiring verbose class/method invocation.
|
4
|
+
|
5
|
+
_Paintbrush_ has zero dependencies and does not pollute any namespaces or objects outside of the `#paintbrush` method wherever you include the `Paintbrush` module.
|
6
|
+
|
7
|
+
Nesting is supported, allowing you to use multiple colors within the same string. The previous color is automatically restored.
|
8
|
+
|
9
|
+
```rspec:ansi
|
10
|
+
require 'paintbrush'
|
11
|
+
|
12
|
+
extend Paintbrush
|
13
|
+
|
14
|
+
output = paintbrush { purple "You used #{green 'four'} #{blue "(#{cyan '4'})"} #{yellow 'colors'} today!" }
|
15
|
+
it_documents output do
|
16
|
+
expect(output).to eql "\e[35mYou used \e[32mfour\e[0m\e[35m " \
|
17
|
+
"\e[34m(\e[36m4\e[0m\e[34m)\e[0m\e[35m " \
|
18
|
+
"\e[33mcolors\e[0m\e[35m today!\e[0m\e[0m"
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
```rspec:ansi
|
23
|
+
require 'paintbrush'
|
24
|
+
|
25
|
+
extend Paintbrush
|
26
|
+
|
27
|
+
output = paintbrush do
|
28
|
+
"#{blue 'foo'} #{green "bar #{cyan %w[foo bar baz].join(', ')} with #{cyan 'qux'} and quux"} and corge"
|
29
|
+
end
|
30
|
+
|
31
|
+
it_documents output do
|
32
|
+
expect(output).to eql "\e[34mfoo\e[0m\e[0m \e[32mbar \e[36mfoo, bar, baz" \
|
33
|
+
"\e[0m\e[32m with \e[36mqux\e[0m\e[32m "\
|
34
|
+
"and quux\e[0m\e[0m and corge"
|
35
|
+
end
|
36
|
+
```
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paintbrush
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Farrell
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-05-
|
11
|
+
date: 2023-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Provides a set of encapsulated methods for nested colorization of strings.
|
14
14
|
email:
|
@@ -28,10 +28,16 @@ files:
|
|
28
28
|
- Rakefile
|
29
29
|
- doc/example.png
|
30
30
|
- lib/paintbrush.rb
|
31
|
+
- lib/paintbrush/bounded_color_element.rb
|
32
|
+
- lib/paintbrush/color_element.rb
|
31
33
|
- lib/paintbrush/colorized_string.rb
|
32
34
|
- lib/paintbrush/colors.rb
|
35
|
+
- lib/paintbrush/element_tree.rb
|
36
|
+
- lib/paintbrush/escapes.rb
|
33
37
|
- lib/paintbrush/version.rb
|
34
38
|
- paintbrush.gemspec
|
39
|
+
- rspec-documentation/bundle/introduction.html
|
40
|
+
- rspec-documentation/pages/Introduction.md
|
35
41
|
- sig/paintbrush.rbs
|
36
42
|
homepage: https://github.com/bobf/paintbrush
|
37
43
|
licenses: []
|