hilighter 1.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/hilight +192 -0
- data/bin/hl +192 -0
- data/lib/hilighter.rb +109 -0
- data/lib/hilighter/codes.rb +151 -0
- data/lib/hilighter/methods.rb +103 -0
- data/lib/string.rb +5 -0
- metadata +72 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 12de20d926f333f17c63422220db0c8c5baf18e7870127de78e8ad55cf4598d6
|
4
|
+
data.tar.gz: 23057327a183158182505494e5943733c8da2ab55995af832d363c315dd61b1f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fd5a67726beb497ed99e5357275fe6cabb23ca575152172010fab86873faa40039db76050dad00bcafa987df923dbca75ff12024adfd0ddb4e0f6aa1bf74cf0b
|
7
|
+
data.tar.gz: e139afef30ae8387e7e9dde274a48b907f41d62df8c091a1c2f9eed8eb34c4e3f870c9ce4bcf4a20e23f0f33ff9084dcd8cb705878f90dbcb5829d41baff95ff
|
data/bin/hilight
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "hilighter"
|
4
|
+
require "io/wait"
|
5
|
+
require "optparse"
|
6
|
+
|
7
|
+
### Helpers begin
|
8
|
+
def err(msg)
|
9
|
+
puts("[!] #{msg}".red)
|
10
|
+
end
|
11
|
+
def errx(msg)
|
12
|
+
raise Exception.new(msg)
|
13
|
+
end
|
14
|
+
def good(msg)
|
15
|
+
puts("[+] #{msg}".green)
|
16
|
+
end
|
17
|
+
def info(msg)
|
18
|
+
puts("[*] #{msg}".white)
|
19
|
+
end
|
20
|
+
def subinfo(msg)
|
21
|
+
puts("[=] #{msg}".cyan)
|
22
|
+
end
|
23
|
+
def warn(msg)
|
24
|
+
puts("[-] #{msg}".yellow)
|
25
|
+
end
|
26
|
+
### Helpers end
|
27
|
+
|
28
|
+
class HilighterExit
|
29
|
+
GOOD = 0
|
30
|
+
INVALID_OPTION = 1
|
31
|
+
INVALID_ARGUMENT = 2
|
32
|
+
MISSING_ARGUMENT = 3
|
33
|
+
EXTRA_ARGUMENTS = 4
|
34
|
+
EXCEPTION = 5
|
35
|
+
AMBIGUOUS_ARGUMENT = 6
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse(args)
|
39
|
+
options = Hash.new
|
40
|
+
options["action"] = "default"
|
41
|
+
options["verbose"] = false
|
42
|
+
|
43
|
+
info = [
|
44
|
+
"Hilights the text from stdin using the methods passed on",
|
45
|
+
"the CLI."
|
46
|
+
].join(" ")
|
47
|
+
|
48
|
+
parser = OptionParser.new do |opts|
|
49
|
+
opts.summary_width = 19
|
50
|
+
|
51
|
+
opts.banner = [
|
52
|
+
"Usage: #{File.basename($0)} [OPTIONS] [color1]...",
|
53
|
+
"[colorN]"
|
54
|
+
].join(" ")
|
55
|
+
|
56
|
+
opts.on("", "DESCRIPTION")
|
57
|
+
|
58
|
+
info.wrap(76).each_line do |line|
|
59
|
+
opts.on(" #{line.chomp}")
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("", "OPTIONS")
|
63
|
+
|
64
|
+
opts.on("-h", "--help", "Display this help message") do
|
65
|
+
puts(opts)
|
66
|
+
exit HilighterExit::GOOD
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("--[no-]color", "Disable colorized output") do |c|
|
70
|
+
Hilighter.disable if (!c)
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on(
|
74
|
+
"-s",
|
75
|
+
"--sample",
|
76
|
+
"Show sample foreground/background colors"
|
77
|
+
) do
|
78
|
+
options["action"] = "sample"
|
79
|
+
end
|
80
|
+
|
81
|
+
opts.on("-t", "--table", "Show the color table") do
|
82
|
+
options["action"] = "table"
|
83
|
+
end
|
84
|
+
|
85
|
+
opts.on(
|
86
|
+
"-v",
|
87
|
+
"--verbose",
|
88
|
+
"Show backtrace when error occurs"
|
89
|
+
) do
|
90
|
+
options["verbose"] = true
|
91
|
+
end
|
92
|
+
|
93
|
+
opts.on("-V", "--version", "Show version") do
|
94
|
+
__FILE__.match(/hilighter-(\d+\.\d+\.\d+)/) do |m|
|
95
|
+
puts(m[1])
|
96
|
+
end
|
97
|
+
exit HilighterExit::GOOD
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
begin
|
102
|
+
parser.parse!
|
103
|
+
rescue OptionParser::InvalidOption => e
|
104
|
+
puts(e.message)
|
105
|
+
puts(parser)
|
106
|
+
exit HilighterExit::INVALID_OPTION
|
107
|
+
rescue OptionParser::InvalidArgument => e
|
108
|
+
puts(e.message)
|
109
|
+
puts(parser)
|
110
|
+
exit HilighterExit::INVALID_ARGUMENT
|
111
|
+
rescue OptionParser::MissingArgument => e
|
112
|
+
puts(e.message)
|
113
|
+
puts(parser)
|
114
|
+
exit HilighterExit::MISSING_ARGUMENT
|
115
|
+
rescue OptionParser::AmbiguousOption => e
|
116
|
+
puts(e.message)
|
117
|
+
puts(parser)
|
118
|
+
exit Exit::AMBIGUOUS_ARGUMENT
|
119
|
+
end
|
120
|
+
|
121
|
+
return options
|
122
|
+
end
|
123
|
+
|
124
|
+
begin
|
125
|
+
options = parse(ARGV)
|
126
|
+
rescue Interrupt
|
127
|
+
# Exit gracefully on ^C
|
128
|
+
exit HilighterExit::GOOD
|
129
|
+
end
|
130
|
+
|
131
|
+
begin
|
132
|
+
case options["action"]
|
133
|
+
when "sample"
|
134
|
+
Hilighter.sample
|
135
|
+
when "table"
|
136
|
+
Hilighter.table
|
137
|
+
else
|
138
|
+
bad = Array.new
|
139
|
+
loop do
|
140
|
+
# Get input
|
141
|
+
input = STDIN.gets
|
142
|
+
|
143
|
+
# Break if EOF, otherwise remove existing color codes
|
144
|
+
break if (input.nil?)
|
145
|
+
|
146
|
+
# Apply all requested color codes
|
147
|
+
ARGV.each do |color|
|
148
|
+
begin
|
149
|
+
input = input.send(color)
|
150
|
+
rescue NoMethodError
|
151
|
+
bad.push(color)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
break if (!bad.empty?)
|
155
|
+
|
156
|
+
# Output
|
157
|
+
puts(input)
|
158
|
+
end
|
159
|
+
puts("Invalid colors: #{bad.join(", ")}") if (!bad.empty?)
|
160
|
+
end
|
161
|
+
rescue Interrupt
|
162
|
+
# Exit gracefully on ^C
|
163
|
+
rescue Errno::EPIPE
|
164
|
+
# Do nothing. This can happen if piping to another program such as
|
165
|
+
# less. Usually if less is closed before we're done with STDOUT.
|
166
|
+
rescue Exception => e
|
167
|
+
$stderr.puts(
|
168
|
+
[
|
169
|
+
"Oops! Looks like an error has occured! If the error",
|
170
|
+
"persists, file a bug at:"
|
171
|
+
].join(" ").wrap
|
172
|
+
)
|
173
|
+
$stderr.puts
|
174
|
+
$stderr.puts(" https://gitlab.com/mjwhitta/hilighter/issues")
|
175
|
+
$stderr.puts
|
176
|
+
$stderr.puts(
|
177
|
+
[
|
178
|
+
"Maybe the message below will help. If not, you can use",
|
179
|
+
"the --verbose flag to get a backtrace."
|
180
|
+
].join(" ").wrap
|
181
|
+
)
|
182
|
+
$stderr.puts
|
183
|
+
|
184
|
+
$stderr.puts(e.message.white.on_red)
|
185
|
+
if (options["verbose"])
|
186
|
+
e.backtrace.each do |line|
|
187
|
+
$stderr.puts(line.light_yellow)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
exit HilighterExit::EXCEPTION
|
191
|
+
end
|
192
|
+
exit HilighterExit::GOOD
|
data/bin/hl
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "hilighter"
|
4
|
+
require "io/wait"
|
5
|
+
require "optparse"
|
6
|
+
|
7
|
+
### Helpers begin
|
8
|
+
def err(msg)
|
9
|
+
puts("[!] #{msg}".red)
|
10
|
+
end
|
11
|
+
def errx(msg)
|
12
|
+
raise Exception.new(msg)
|
13
|
+
end
|
14
|
+
def good(msg)
|
15
|
+
puts("[+] #{msg}".green)
|
16
|
+
end
|
17
|
+
def info(msg)
|
18
|
+
puts("[*] #{msg}".white)
|
19
|
+
end
|
20
|
+
def subinfo(msg)
|
21
|
+
puts("[=] #{msg}".cyan)
|
22
|
+
end
|
23
|
+
def warn(msg)
|
24
|
+
puts("[-] #{msg}".yellow)
|
25
|
+
end
|
26
|
+
### Helpers end
|
27
|
+
|
28
|
+
class HilighterExit
|
29
|
+
GOOD = 0
|
30
|
+
INVALID_OPTION = 1
|
31
|
+
INVALID_ARGUMENT = 2
|
32
|
+
MISSING_ARGUMENT = 3
|
33
|
+
EXTRA_ARGUMENTS = 4
|
34
|
+
EXCEPTION = 5
|
35
|
+
AMBIGUOUS_ARGUMENT = 6
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse(args)
|
39
|
+
options = Hash.new
|
40
|
+
options["action"] = "default"
|
41
|
+
options["verbose"] = false
|
42
|
+
|
43
|
+
info = [
|
44
|
+
"Hilights the text from stdin using the methods passed on",
|
45
|
+
"the CLI."
|
46
|
+
].join(" ")
|
47
|
+
|
48
|
+
parser = OptionParser.new do |opts|
|
49
|
+
opts.summary_width = 19
|
50
|
+
|
51
|
+
opts.banner = [
|
52
|
+
"Usage: #{File.basename($0)} [OPTIONS] [color1]...",
|
53
|
+
"[colorN]"
|
54
|
+
].join(" ")
|
55
|
+
|
56
|
+
opts.on("", "DESCRIPTION")
|
57
|
+
|
58
|
+
info.wrap(76).each_line do |line|
|
59
|
+
opts.on(" #{line.chomp}")
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("", "OPTIONS")
|
63
|
+
|
64
|
+
opts.on("-h", "--help", "Display this help message") do
|
65
|
+
puts(opts)
|
66
|
+
exit HilighterExit::GOOD
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("--[no-]color", "Disable colorized output") do |c|
|
70
|
+
Hilighter.disable if (!c)
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on(
|
74
|
+
"-s",
|
75
|
+
"--sample",
|
76
|
+
"Show sample foreground/background colors"
|
77
|
+
) do
|
78
|
+
options["action"] = "sample"
|
79
|
+
end
|
80
|
+
|
81
|
+
opts.on("-t", "--table", "Show the color table") do
|
82
|
+
options["action"] = "table"
|
83
|
+
end
|
84
|
+
|
85
|
+
opts.on(
|
86
|
+
"-v",
|
87
|
+
"--verbose",
|
88
|
+
"Show backtrace when error occurs"
|
89
|
+
) do
|
90
|
+
options["verbose"] = true
|
91
|
+
end
|
92
|
+
|
93
|
+
opts.on("-V", "--version", "Show version") do
|
94
|
+
__FILE__.match(/hilighter-(\d+\.\d+\.\d+)/) do |m|
|
95
|
+
puts(m[1])
|
96
|
+
end
|
97
|
+
exit HilighterExit::GOOD
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
begin
|
102
|
+
parser.parse!
|
103
|
+
rescue OptionParser::InvalidOption => e
|
104
|
+
puts(e.message)
|
105
|
+
puts(parser)
|
106
|
+
exit HilighterExit::INVALID_OPTION
|
107
|
+
rescue OptionParser::InvalidArgument => e
|
108
|
+
puts(e.message)
|
109
|
+
puts(parser)
|
110
|
+
exit HilighterExit::INVALID_ARGUMENT
|
111
|
+
rescue OptionParser::MissingArgument => e
|
112
|
+
puts(e.message)
|
113
|
+
puts(parser)
|
114
|
+
exit HilighterExit::MISSING_ARGUMENT
|
115
|
+
rescue OptionParser::AmbiguousOption => e
|
116
|
+
puts(e.message)
|
117
|
+
puts(parser)
|
118
|
+
exit Exit::AMBIGUOUS_ARGUMENT
|
119
|
+
end
|
120
|
+
|
121
|
+
return options
|
122
|
+
end
|
123
|
+
|
124
|
+
begin
|
125
|
+
options = parse(ARGV)
|
126
|
+
rescue Interrupt
|
127
|
+
# Exit gracefully on ^C
|
128
|
+
exit HilighterExit::GOOD
|
129
|
+
end
|
130
|
+
|
131
|
+
begin
|
132
|
+
case options["action"]
|
133
|
+
when "sample"
|
134
|
+
Hilighter.sample
|
135
|
+
when "table"
|
136
|
+
Hilighter.table
|
137
|
+
else
|
138
|
+
bad = Array.new
|
139
|
+
loop do
|
140
|
+
# Get input
|
141
|
+
input = STDIN.gets
|
142
|
+
|
143
|
+
# Break if EOF, otherwise remove existing color codes
|
144
|
+
break if (input.nil?)
|
145
|
+
|
146
|
+
# Apply all requested color codes
|
147
|
+
ARGV.each do |color|
|
148
|
+
begin
|
149
|
+
input = input.send(color)
|
150
|
+
rescue NoMethodError
|
151
|
+
bad.push(color)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
break if (!bad.empty?)
|
155
|
+
|
156
|
+
# Output
|
157
|
+
puts(input)
|
158
|
+
end
|
159
|
+
puts("Invalid colors: #{bad.join(", ")}") if (!bad.empty?)
|
160
|
+
end
|
161
|
+
rescue Interrupt
|
162
|
+
# Exit gracefully on ^C
|
163
|
+
rescue Errno::EPIPE
|
164
|
+
# Do nothing. This can happen if piping to another program such as
|
165
|
+
# less. Usually if less is closed before we're done with STDOUT.
|
166
|
+
rescue Exception => e
|
167
|
+
$stderr.puts(
|
168
|
+
[
|
169
|
+
"Oops! Looks like an error has occured! If the error",
|
170
|
+
"persists, file a bug at:"
|
171
|
+
].join(" ").wrap
|
172
|
+
)
|
173
|
+
$stderr.puts
|
174
|
+
$stderr.puts(" https://gitlab.com/mjwhitta/hilighter/issues")
|
175
|
+
$stderr.puts
|
176
|
+
$stderr.puts(
|
177
|
+
[
|
178
|
+
"Maybe the message below will help. If not, you can use",
|
179
|
+
"the --verbose flag to get a backtrace."
|
180
|
+
].join(" ").wrap
|
181
|
+
)
|
182
|
+
$stderr.puts
|
183
|
+
|
184
|
+
$stderr.puts(e.message.white.on_red)
|
185
|
+
if (options["verbose"])
|
186
|
+
e.backtrace.each do |line|
|
187
|
+
$stderr.puts(line.light_yellow)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
exit HilighterExit::EXCEPTION
|
191
|
+
end
|
192
|
+
exit HilighterExit::GOOD
|
data/lib/hilighter.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
class Hilighter
|
2
|
+
def self.disable(val = true)
|
3
|
+
@@disable = val
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.disable?
|
7
|
+
@@disable ||= false
|
8
|
+
return @@disable
|
9
|
+
end
|
10
|
+
|
11
|
+
# Convert hex to xterm-256 8-bit value
|
12
|
+
# https://stackoverflow.com/questions/11765623/convert-hex-hex_to_256bitto-closest-x11-color-number
|
13
|
+
def self.hex_to_x256(hex)
|
14
|
+
@@cached_codes ||= Hash.new
|
15
|
+
cache = @@cached_codes[hex]
|
16
|
+
return "color_#{cache}" if (!cache.nil?)
|
17
|
+
|
18
|
+
# For simplicity, assume RGB space is perceptually uniform.
|
19
|
+
# There are 5 places where one of two outputs needs to be
|
20
|
+
# chosen when the input is the exact middle:
|
21
|
+
# - The r/g/b channels and the gray value:
|
22
|
+
# - the higher value output is chosen
|
23
|
+
# - If the gray and color values have same distance from the
|
24
|
+
# input
|
25
|
+
# - color is chosen
|
26
|
+
|
27
|
+
# Calculate the nearest 0-based color index at 16..231
|
28
|
+
r = g = b = 0
|
29
|
+
x = "[A-Fa-f0-9]{2}"
|
30
|
+
hex.match(/^#?(#{x})(#{x})(#{x})(#{x})?$/) do |m|
|
31
|
+
r = m[1].to_i(16)
|
32
|
+
g = m[2].to_i(16)
|
33
|
+
b = m[3].to_i(16)
|
34
|
+
end
|
35
|
+
|
36
|
+
# 0..5 each
|
37
|
+
ir = (r < 48) ? 0 : (r < 115) ? 1 : ((r - 35) / 40)
|
38
|
+
ig = (g < 48) ? 0 : (g < 115) ? 1 : ((g - 35) / 40)
|
39
|
+
ib = (b < 48) ? 0 : (b < 115) ? 1 : ((b - 35) / 40)
|
40
|
+
|
41
|
+
# 0..215 lazy evaluation
|
42
|
+
cidx = (36 * ir) + (6 * ig) + ib + 16
|
43
|
+
|
44
|
+
# Calculate the nearest 0-based gray index at 232..255
|
45
|
+
average = (r + g + b) / 3
|
46
|
+
|
47
|
+
# 0..23
|
48
|
+
gidx = (average > 238) ? 23 : (average - 3) / 10
|
49
|
+
|
50
|
+
# Calculate the represented colors back from the index
|
51
|
+
i2cv = [0, 0x5f, 0x87, 0xaf, 0xd7, 0xff]
|
52
|
+
|
53
|
+
# r/g/b 0..255 each
|
54
|
+
cr = i2cv[ir]
|
55
|
+
cg = i2cv[ig]
|
56
|
+
cb = i2cv[ib]
|
57
|
+
|
58
|
+
# same value for r/g/b 0..255
|
59
|
+
gv = (10 * gidx) + 8
|
60
|
+
|
61
|
+
# Return the one which is nearer to the original rgb
|
62
|
+
# values
|
63
|
+
clr_err = ((cr - r) ** 2 + (cg - g) ** 2 + (cb - b) ** 2)
|
64
|
+
gray_err = ((gv - r) ** 2 + (gv - g) ** 2 + (gv - b) ** 2)
|
65
|
+
|
66
|
+
if (clr_err <= gray_err)
|
67
|
+
@@cached_codes[hex] = cidx.to_s.rjust(3, "0")
|
68
|
+
else
|
69
|
+
@@cached_codes[hex] = (gidx + 232).to_s.rjust(3, "0")
|
70
|
+
end
|
71
|
+
|
72
|
+
return "color_#{@@cached_codes[hex]}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.sample
|
76
|
+
String.colors.keys[0..15].each do |fg|
|
77
|
+
String.colors.keys[16..31].each do |bg|
|
78
|
+
print(" mw ".send(fg).send(bg))
|
79
|
+
end
|
80
|
+
puts
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.table
|
85
|
+
(0..15).each do |i|
|
86
|
+
bg = i.to_s.rjust(3, "0")
|
87
|
+
print(" ".send("on_color_#{bg}"))
|
88
|
+
print(bg.black.send("on_color_#{bg}"))
|
89
|
+
print(" ".send("on_color_#{bg}"))
|
90
|
+
print(bg.white.send("on_color_#{bg}"))
|
91
|
+
print(" ".send("on_color_#{bg}"))
|
92
|
+
puts if (((i + 1) % 8) == 0)
|
93
|
+
end
|
94
|
+
|
95
|
+
(16..255).each do |i|
|
96
|
+
bg = i.to_s.rjust(3, "0")
|
97
|
+
print(" ".send("on_color_#{bg}"))
|
98
|
+
print(bg.black.send("on_color_#{bg}"))
|
99
|
+
print(" ".send("on_color_#{bg}"))
|
100
|
+
print(bg.white.send("on_color_#{bg}"))
|
101
|
+
print(" ".send("on_color_#{bg}"))
|
102
|
+
puts if (((i - 15) % 6) == 0)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
require "hilighter/codes"
|
108
|
+
require "hilighter/methods"
|
109
|
+
require "string"
|
@@ -0,0 +1,151 @@
|
|
1
|
+
class Hilighter
|
2
|
+
module Codes
|
3
|
+
def add_methods
|
4
|
+
color_regex = /(^|\n)(\e\[([0-9;]+m|K))+(\n|$)/
|
5
|
+
|
6
|
+
colors.each do |key, val|
|
7
|
+
if (key.start_with?("on_"))
|
8
|
+
on_default = colors["on_default"]
|
9
|
+
define_method key do
|
10
|
+
return self.plain if (Hilighter.disable?)
|
11
|
+
|
12
|
+
return [
|
13
|
+
"\e[#{val}m",
|
14
|
+
self.plain_bg.gsub(
|
15
|
+
/\n/,
|
16
|
+
"\e[#{on_default}m\n\e[#{val}m"
|
17
|
+
),
|
18
|
+
"\e[#{on_default}m"
|
19
|
+
].join.gsub(color_regex, "\\1\\4")
|
20
|
+
end
|
21
|
+
else
|
22
|
+
default = colors["default"]
|
23
|
+
define_method key do
|
24
|
+
return self.plain if (Hilighter.disable?)
|
25
|
+
|
26
|
+
return [
|
27
|
+
"\e[#{val}m",
|
28
|
+
self.plain_fg.gsub(
|
29
|
+
/\n/,
|
30
|
+
"\e[#{default}m\n\e[#{val}m"
|
31
|
+
),
|
32
|
+
"\e[#{default}m"
|
33
|
+
].join.gsub(color_regex, "\\1\\4")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
modes.each do |key, val|
|
39
|
+
rm = [
|
40
|
+
modes[key],
|
41
|
+
modes["no_#{key}".gsub(/^no_no_/, "")]
|
42
|
+
].delete_if(&:nil?).uniq.join("|")
|
43
|
+
|
44
|
+
off = "no_#{key}"
|
45
|
+
if modes.has_key?(off)
|
46
|
+
off = "\e[#{modes[off]}m"
|
47
|
+
else
|
48
|
+
off = ""
|
49
|
+
end
|
50
|
+
|
51
|
+
define_method key do
|
52
|
+
return self.plain if (Hilighter.disable?)
|
53
|
+
self.gsub!(/\e\[(#{rm})m/, "")
|
54
|
+
return "\e[#{val}m#{self}#{off}".gsub(
|
55
|
+
color_regex,
|
56
|
+
"\\1\\4"
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def colors
|
63
|
+
@valid_colors ||= {
|
64
|
+
"black" => 30,
|
65
|
+
"red" => 31,
|
66
|
+
"green" => 32,
|
67
|
+
"yellow" => 33,
|
68
|
+
"blue" => 34,
|
69
|
+
"magenta" => 35,
|
70
|
+
"cyan" => 36,
|
71
|
+
"white" => 37,
|
72
|
+
"light_black" => 90,
|
73
|
+
"light_red" => 91,
|
74
|
+
"light_green" => 92,
|
75
|
+
"light_yellow" => 93,
|
76
|
+
"light_blue" => 94,
|
77
|
+
"light_magenta" => 95,
|
78
|
+
"light_cyan" => 96,
|
79
|
+
"light_white" => 97,
|
80
|
+
|
81
|
+
"on_black" => 40,
|
82
|
+
"on_red" => 41,
|
83
|
+
"on_green" => 42,
|
84
|
+
"on_yellow" => 43,
|
85
|
+
"on_blue" => 44,
|
86
|
+
"on_magenta" => 45,
|
87
|
+
"on_cyan" => 46,
|
88
|
+
"on_white" => 47,
|
89
|
+
"on_light_black" => 100,
|
90
|
+
"on_light_red" => 101,
|
91
|
+
"on_light_green" => 102,
|
92
|
+
"on_light_yellow" => 103,
|
93
|
+
"on_light_blue" => 104,
|
94
|
+
"on_light_magenta" => 105,
|
95
|
+
"on_light_cyan" => 106,
|
96
|
+
"on_light_white" => 107,
|
97
|
+
|
98
|
+
"default" => 39,
|
99
|
+
"on_default" => 49
|
100
|
+
}
|
101
|
+
if (@valid_colors.length < 256)
|
102
|
+
256.times.each do |i|
|
103
|
+
clr = i.to_s.rjust(3, "0")
|
104
|
+
@valid_colors["color_#{clr}"] = "38;5;#{clr}"
|
105
|
+
@valid_colors["on_color_#{clr}"] = "48;5;#{clr}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
return @valid_colors
|
109
|
+
end
|
110
|
+
|
111
|
+
def modes
|
112
|
+
return {
|
113
|
+
"reset" => 0,
|
114
|
+
"normal" => 0,
|
115
|
+
"bold" => 1,
|
116
|
+
"dim" => 2,
|
117
|
+
"faint" => 2,
|
118
|
+
"italic" => 3,
|
119
|
+
"underline" => 4,
|
120
|
+
"blink" => 5,
|
121
|
+
"blink_slow" => 5,
|
122
|
+
"blink_rapid" => 6,
|
123
|
+
"inverse" => 7,
|
124
|
+
"negative" => 7,
|
125
|
+
"swap" => 7,
|
126
|
+
"hide" => 8,
|
127
|
+
"conceal" => 8,
|
128
|
+
"crossed_out" => 9,
|
129
|
+
"strikethrough" => 9,
|
130
|
+
"fraktur" => 20,
|
131
|
+
|
132
|
+
"no_bold" => 21,
|
133
|
+
"no_dim" => 22,
|
134
|
+
"no_faint" => 22,
|
135
|
+
"no_italic" => 23,
|
136
|
+
"no_fraktur" => 23,
|
137
|
+
"no_underline" => 24,
|
138
|
+
"no_blink" => 25,
|
139
|
+
"no_blink_slow" => 25,
|
140
|
+
"no_blink_rapid" => 26,
|
141
|
+
"no_inverse" => 27,
|
142
|
+
"no_negative" => 27,
|
143
|
+
"no_swap" => 27,
|
144
|
+
"no_hide" => 28,
|
145
|
+
"no_conceal" => 28,
|
146
|
+
"no_crossed_out" => 29,
|
147
|
+
"no_strikethrough" => 29
|
148
|
+
}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
class Hilighter
|
2
|
+
module Methods
|
3
|
+
def color_regex
|
4
|
+
return /\e\[([0-9;]*m|K)/
|
5
|
+
end
|
6
|
+
private :color_regex
|
7
|
+
|
8
|
+
def hex_color(hex)
|
9
|
+
return self.send(Hilighter.hex_to_x256(hex))
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(method_name, *args)
|
13
|
+
method_name.to_s.match(/^([A-Fa-f0-9]{6})$/) do |m|
|
14
|
+
return self.hex_color(m[1])
|
15
|
+
end
|
16
|
+
method_name.to_s.match(/^on_([A-Fa-f0-9]{6})$/) do |m|
|
17
|
+
return self.on_hex_color(m[1])
|
18
|
+
end
|
19
|
+
method_name.to_s.match(/^wrap(_(\d+))?$/) do |m|
|
20
|
+
width = nil
|
21
|
+
width = m[2].to_i if (!m[1].nil?)
|
22
|
+
return self.wrap(width)
|
23
|
+
end
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_hex_color(hex)
|
28
|
+
return self.send("on_#{Hilighter.hex_to_x256(hex)}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_rainbow
|
32
|
+
return self.plain if (Hilighter.disable?)
|
33
|
+
|
34
|
+
clrs = rainbow_colors
|
35
|
+
out = Array.new
|
36
|
+
|
37
|
+
self.plain_bg.each_line do |line|
|
38
|
+
line.chomp!
|
39
|
+
colorized = line.scan(
|
40
|
+
/((#{color_regex})*[^\e](#{color_regex})*)/
|
41
|
+
).map.with_index do |c, i|
|
42
|
+
"\e[#{clrs[i % clrs.length] + 10}m#{c[0]}"
|
43
|
+
end.join
|
44
|
+
out.push("#{colorized}\e[49m\n")
|
45
|
+
end
|
46
|
+
|
47
|
+
return out.join.gsub(/^(#{color_regex})+$/, "")
|
48
|
+
end
|
49
|
+
|
50
|
+
def plain
|
51
|
+
return self.gsub(color_regex, "")
|
52
|
+
end
|
53
|
+
|
54
|
+
def plain_bg
|
55
|
+
return self.gsub(/\e\[(4|10)[0-9;]+m/, "")
|
56
|
+
end
|
57
|
+
|
58
|
+
def plain_fg
|
59
|
+
return self.gsub(/\e\[[39][0-9;]+m/, "")
|
60
|
+
end
|
61
|
+
|
62
|
+
def rainbow_colors
|
63
|
+
return [31, 32, 33, 34, 35, 36, 91, 92, 93, 94, 95, 96]
|
64
|
+
end
|
65
|
+
private :rainbow_colors
|
66
|
+
|
67
|
+
def rainbow
|
68
|
+
return self.plain if (Hilighter.disable?)
|
69
|
+
|
70
|
+
clrs = rainbow_colors
|
71
|
+
out = Array.new
|
72
|
+
|
73
|
+
self.plain_fg.each_line do |line|
|
74
|
+
line.chomp!
|
75
|
+
colorized = line.scan(
|
76
|
+
/((#{color_regex})*[^\e](#{color_regex})*)/
|
77
|
+
).map.with_index do |c, i|
|
78
|
+
"\e[#{clrs[i % clrs.length]}m#{c[0]}"
|
79
|
+
end.join
|
80
|
+
out.push("#{colorized}\n")
|
81
|
+
end
|
82
|
+
|
83
|
+
return out.join.gsub(/^(#{color_regex})+$/, "")
|
84
|
+
end
|
85
|
+
|
86
|
+
def wrap(width = 80)
|
87
|
+
line = ""
|
88
|
+
lines = Array.new
|
89
|
+
self.split(/\s+/).each do |word|
|
90
|
+
if ((line.plain.size + word.plain.size) > width)
|
91
|
+
lines.push("#{line}\n")
|
92
|
+
line = word
|
93
|
+
elsif (line.empty?)
|
94
|
+
line = word
|
95
|
+
else
|
96
|
+
line += " #{word}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
lines.push("#{line}\n") if (!line.empty?)
|
100
|
+
return lines.join
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/string.rb
ADDED
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hilighter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.5.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Miles Whittaker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-11-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 13.0.0
|
20
|
+
- - "~>"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '13.0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 13.0.0
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '13.0'
|
33
|
+
description: Adds color methods to String class. Also allows for string wrapping that
|
34
|
+
accounts for color escape codes.
|
35
|
+
email: mj@whitta.dev
|
36
|
+
executables:
|
37
|
+
- hl
|
38
|
+
- hilight
|
39
|
+
extensions: []
|
40
|
+
extra_rdoc_files: []
|
41
|
+
files:
|
42
|
+
- bin/hilight
|
43
|
+
- bin/hl
|
44
|
+
- lib/hilighter.rb
|
45
|
+
- lib/hilighter/codes.rb
|
46
|
+
- lib/hilighter/methods.rb
|
47
|
+
- lib/string.rb
|
48
|
+
homepage: https://gitlab.com/mjwhitta/hilighter/tree/ruby
|
49
|
+
licenses:
|
50
|
+
- GPL-3.0
|
51
|
+
metadata:
|
52
|
+
source_code_uri: https://gitlab.com/mjwhitta/hilighter/tree/ruby
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubygems_version: 3.0.6
|
69
|
+
signing_key:
|
70
|
+
specification_version: 4
|
71
|
+
summary: Adds color methods to String class
|
72
|
+
test_files: []
|