ex_aequo_color 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +339 -22
- data/lib/ex_aequo/color/all.rb +10 -0
- data/lib/ex_aequo/color/ansi_color_names.rb +239 -0
- data/lib/ex_aequo/color/color_definitions.rb +49 -0
- data/lib/ex_aequo/color/colorizer.rb +134 -0
- data/lib/ex_aequo/color/encode.rb +55 -0
- data/lib/ex_aequo/color/output.rb +21 -0
- data/lib/ex_aequo/color/string.rb +11 -0
- data/lib/ex_aequo/color/version.rb +1 -1
- data/lib/ex_aequo/color.rb +15 -29
- data/lib/ex_aequo/ostruct.rb +13 -0
- metadata +14 -9
- data/lib/ex_aequo/colorize/color_definitions.rb +0 -513
- data/lib/ex_aequo/colorizer.rb +0 -130
- data/lib/ex_aequo.rb +0 -6
@@ -0,0 +1,134 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExAequo
|
4
|
+
module Color
|
5
|
+
SyntaxError = Class.new(RuntimeError)
|
6
|
+
|
7
|
+
module Colorizer extend self
|
8
|
+
def colorize(line, reset: false)
|
9
|
+
line = line.chomp
|
10
|
+
no_color = ENV.fetch('NO_COLOR', false)
|
11
|
+
result = parse(line.grapheme_clusters, no_color)
|
12
|
+
case result
|
13
|
+
in {ok: true, result:}
|
14
|
+
Result.ok(join_result(result, no_color:, reset:))
|
15
|
+
else
|
16
|
+
result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def colorize!(line, reset: false)
|
21
|
+
case colorize(line, reset:)
|
22
|
+
in {ok: true, result:}
|
23
|
+
result
|
24
|
+
in {ok: false, error:}
|
25
|
+
raise SyntaxError, error
|
26
|
+
else
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def colorize_file(file, device: $stdout, reset: false)
|
31
|
+
file = File.open(file, 'r') if String === file
|
32
|
+
|
33
|
+
at_exit do
|
34
|
+
file.close rescue nil
|
35
|
+
end
|
36
|
+
colorize_lines(file.readlines(chomp: true), device:, reset:)
|
37
|
+
end
|
38
|
+
|
39
|
+
def colorize_lines(lines, reset: false, device: $stdout)
|
40
|
+
lines = lines.split(%r{\n\r?}) if String === lines
|
41
|
+
lines
|
42
|
+
.each_with_index do | line, idx |
|
43
|
+
result = colorize(line, reset:).extract { |r|
|
44
|
+
$stderr.puts("ERROR in line #{idx.succ} ** #{r.error} **")
|
45
|
+
}
|
46
|
+
device.puts result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def app(ary, ary_or_elem)
|
53
|
+
case ary_or_elem
|
54
|
+
when Array
|
55
|
+
[*ary, *ary_or_elem]
|
56
|
+
else
|
57
|
+
[*ary, ary_or_elem]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_color_definition(rest, no_color,color)
|
62
|
+
colored = ColorDefinitions.get(color, no_color)
|
63
|
+
Result.from_value colored, error: "undefined color #{color}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_color!(color, no_color)
|
67
|
+
color_def = ColorDefinitions.get(color, no_color)
|
68
|
+
return color_def if color_def
|
69
|
+
|
70
|
+
raise "Bad color definition #{color.inspect}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def join_result(result, no_color:, reset:)
|
74
|
+
app(result, reset ? get_color!(:reset, no_color) : '')
|
75
|
+
.join
|
76
|
+
end
|
77
|
+
|
78
|
+
def parse(line, no_color, result = [])
|
79
|
+
case line
|
80
|
+
in []
|
81
|
+
Result.ok(result)
|
82
|
+
in ['<', '<', *rest]
|
83
|
+
parse(rest, no_color, app(result, '<'))
|
84
|
+
in ['$', '$', *rest]
|
85
|
+
parse(rest, no_color, app(result, '$'))
|
86
|
+
in ['$', *rest]
|
87
|
+
parse(rest, no_color, app(result, reset(no_color)))
|
88
|
+
in ['<', *rest]
|
89
|
+
parse_color(rest, no_color, result)
|
90
|
+
else
|
91
|
+
parse(line.drop(1), no_color, app(result, line.first))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse_color(line, no_color, result, color=[])
|
96
|
+
case line
|
97
|
+
in []
|
98
|
+
Result.nok("Incomplete Color Spec #{color.join}")
|
99
|
+
in ['>', *rest]
|
100
|
+
parse_continue_after_color(rest, no_color, result, color.join)
|
101
|
+
in [',', *rest]
|
102
|
+
parse_next_color(rest, no_color, result, color.join)
|
103
|
+
else
|
104
|
+
parse_color(line.drop(1), no_color, result, app(color, line.first))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def parse_continue_after_color(rest, no_color, result, color)
|
109
|
+
checked = check_color_definition(rest, no_color, color)
|
110
|
+
case checked
|
111
|
+
in {ok: true, result: color}
|
112
|
+
parse(rest, no_color, app(result, color))
|
113
|
+
else
|
114
|
+
checked
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def parse_next_color(rest, no_color, result, color)
|
119
|
+
color_def = check_color_definition(rest, no_color, color)
|
120
|
+
case color_def
|
121
|
+
in {ok: true, result: color}
|
122
|
+
parse_color(rest, no_color, app(result, color))
|
123
|
+
else
|
124
|
+
color_def
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def reset(no_color)
|
129
|
+
get_color!(:reset, no_color)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExAequo
|
4
|
+
module Color
|
5
|
+
module Encode extend self
|
6
|
+
|
7
|
+
def color(*chunks, reset: true)
|
8
|
+
_colors(chunks.flatten) => {needs_reset:, colorized:}
|
9
|
+
colorized << _color_code(:reset) if needs_reset && reset
|
10
|
+
|
11
|
+
colorized.join
|
12
|
+
end
|
13
|
+
|
14
|
+
def sgc(value)
|
15
|
+
return '' if _no_color
|
16
|
+
|
17
|
+
ColorDefinitions.sgc(value)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def _colors(chunks) =
|
22
|
+
# need the [""] to get the correct encoding (WTH?)
|
23
|
+
chunks.inject(OpenStruct.new(needs_reset: false, colorized: [""])) do |acc, chunk|
|
24
|
+
_color(acc, chunk)
|
25
|
+
end
|
26
|
+
|
27
|
+
def _color(acc, chunk)
|
28
|
+
case chunk
|
29
|
+
when Symbol
|
30
|
+
acc.colorized << _color_code(chunk)
|
31
|
+
acc.update(needs_reset: chunk != :reset)
|
32
|
+
when String
|
33
|
+
acc.colorized << chunk
|
34
|
+
when 0
|
35
|
+
acc.colorized << _color_code(:reset)
|
36
|
+
acc.update(needs_reset: false)
|
37
|
+
else
|
38
|
+
raise ArgumentError, "need a colorspec by symbol, a string or 0 (short for :reset), but got #{chunk.inspect}"
|
39
|
+
end
|
40
|
+
acc
|
41
|
+
end
|
42
|
+
|
43
|
+
def _color_code(color) =
|
44
|
+
ColorDefinitions.get(color, _no_color).tap do
|
45
|
+
raise BadColorSpecification, "bad color specification: #{color}" unless it
|
46
|
+
end
|
47
|
+
|
48
|
+
def _no_color
|
49
|
+
@___no_color__ ||= ENV['NO_COLOR']
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'encode'
|
4
|
+
module ExAequo
|
5
|
+
module Color
|
6
|
+
module Output extend self
|
7
|
+
|
8
|
+
def putc(*chunks, reset: false, device: $stdout)
|
9
|
+
output = Encode.color(*chunks, reset:)
|
10
|
+
device.print(output)
|
11
|
+
end
|
12
|
+
|
13
|
+
def putcs(*chunks, reset: true, device: $stdout)
|
14
|
+
output = Encode.color(*chunks, reset:)
|
15
|
+
device.puts(output)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class String
|
4
|
+
def colored(color, reset: true)
|
5
|
+
Color.color(color, self, reset:)
|
6
|
+
end
|
7
|
+
|
8
|
+
def pcolored(color, reset: true, device: $stdout) = Color.pcolored(color, self, reset:, device:)
|
9
|
+
end
|
10
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
11
|
+
|
data/lib/ex_aequo/color.rb
CHANGED
@@ -1,41 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'ex_aequo/base/result/import'
|
4
|
+
|
5
|
+
require_relative 'color/color_definitions'
|
6
|
+
require_relative 'color/colorizer'
|
7
|
+
require_relative 'color/output'
|
4
8
|
require 'forwardable'
|
9
|
+
require_relative 'ostruct'
|
5
10
|
module ExAequo
|
6
11
|
module Color extend self
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def color(*chunks, reset: true)
|
12
|
-
colorized = _colors(chunks.flatten)
|
13
|
-
return colorized unless reset
|
12
|
+
BadColorSpecification = Class.new(RuntimeError)
|
13
|
+
extend Encode
|
14
|
+
extend Output
|
14
15
|
|
15
|
-
|
16
|
+
def self.included(into)
|
17
|
+
into.send(:include, Encode)
|
18
|
+
into.send(:include, Output)
|
16
19
|
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
def _color(chunk)
|
22
|
-
case chunk
|
23
|
-
when Symbol
|
24
|
-
_get_color(chunk)
|
25
|
-
when String
|
26
|
-
chunk
|
27
|
-
when 0
|
28
|
-
_get_color(:reset)
|
29
|
-
else
|
30
|
-
raise ArgumentError, "need a colorspec by symbol, a string or 0 (short for :reset)"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def _get_color(color) = Colorizer::ColorDefinitions.get(color, _no_color)
|
21
|
+
extend Forwardable
|
22
|
+
def_delegators Colorizer, :colorize, :colorize!, :colorize_file, :colorize_lines
|
35
23
|
|
36
|
-
def
|
37
|
-
@___no_color__ ||= ENV['NO_COLOR']
|
38
|
-
end
|
24
|
+
def pcolored(*chunks, reset: true, device: $stderr) = device.puts(color(*chunks, reset:))
|
39
25
|
end
|
40
26
|
end
|
41
27
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ex_aequo_color
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
@@ -10,19 +10,19 @@ cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
|
-
name:
|
13
|
+
name: ex_aequo_base
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
16
|
- - "~>"
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: 0.
|
18
|
+
version: 0.3.5
|
19
19
|
type: :runtime
|
20
20
|
prerelease: false
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
22
22
|
requirements:
|
23
23
|
- - "~>"
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version: 0.
|
25
|
+
version: 0.3.5
|
26
26
|
description: Rainbows in your shell
|
27
27
|
email: robert.dober@gmail.com
|
28
28
|
executables: []
|
@@ -31,11 +31,16 @@ extra_rdoc_files: []
|
|
31
31
|
files:
|
32
32
|
- LICENSE
|
33
33
|
- README.md
|
34
|
-
- lib/ex_aequo.rb
|
35
34
|
- lib/ex_aequo/color.rb
|
35
|
+
- lib/ex_aequo/color/all.rb
|
36
|
+
- lib/ex_aequo/color/ansi_color_names.rb
|
37
|
+
- lib/ex_aequo/color/color_definitions.rb
|
38
|
+
- lib/ex_aequo/color/colorizer.rb
|
39
|
+
- lib/ex_aequo/color/encode.rb
|
40
|
+
- lib/ex_aequo/color/output.rb
|
41
|
+
- lib/ex_aequo/color/string.rb
|
36
42
|
- lib/ex_aequo/color/version.rb
|
37
|
-
- lib/ex_aequo/
|
38
|
-
- lib/ex_aequo/colorizer.rb
|
43
|
+
- lib/ex_aequo/ostruct.rb
|
39
44
|
homepage: https://codeberg.org/lab419/rb_ex_aequo_color.git
|
40
45
|
licenses:
|
41
46
|
- AGPL-3.0-or-later
|
@@ -47,14 +52,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
52
|
requirements:
|
48
53
|
- - ">="
|
49
54
|
- !ruby/object:Gem::Version
|
50
|
-
version: 3.4.
|
55
|
+
version: 3.4.5
|
51
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
57
|
requirements:
|
53
58
|
- - ">="
|
54
59
|
- !ruby/object:Gem::Version
|
55
60
|
version: '0'
|
56
61
|
requirements: []
|
57
|
-
rubygems_version: 3.
|
62
|
+
rubygems_version: 3.7.1
|
58
63
|
specification_version: 4
|
59
64
|
summary: Rainbows in your shell
|
60
65
|
test_files: []
|