ansi 1.2.5 → 1.3.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.
- data/.ruby +34 -31
- data/HISTORY.rdoc +18 -0
- data/LICENSE/BSD-2-Clause.txt +25 -0
- data/LICENSE/GPL-2.0.txt +339 -0
- data/LICENSE/MIT.txt +21 -0
- data/LICENSE/RUBY.txt +60 -0
- data/NOTICE.rdoc +116 -4
- data/README.rdoc +6 -12
- data/lib/ansi.rb +6 -0
- data/lib/ansi.rbz +40 -0
- data/lib/ansi.yml +34 -31
- data/lib/ansi/bbcode.rb +3 -0
- data/lib/ansi/chart.rb +95 -0
- data/lib/ansi/code.rb +189 -260
- data/lib/ansi/constants.rb +18 -0
- data/lib/ansi/core.rb +24 -0
- data/lib/ansi/diff.rb +98 -61
- data/lib/ansi/string.rb +7 -8
- data/lib/ansi/terminal.rb +3 -3
- data/qed/01_ansicode.rdoc +0 -7
- data/qed/09_diff.rb +5 -5
- data/qed/10_core.rdoc +11 -0
- data/test/case_ansicode.rb +20 -10
- data/test/case_bbcode.rb +7 -8
- data/test/case_mixin.rb +14 -7
- data/test/case_progressbar.rb +2 -2
- metadata +26 -27
- data/LICENSE +0 -205
- data/Rakefile +0 -4
@@ -0,0 +1,18 @@
|
|
1
|
+
module ANSI
|
2
|
+
|
3
|
+
# Converts {CHART} and {SPECIAL_CHART} entries into constants.
|
4
|
+
module Constants
|
5
|
+
|
6
|
+
require 'ansi/chart'
|
7
|
+
|
8
|
+
CHART.each do |name, code|
|
9
|
+
const_set(name.to_s.upcase, "\e[#{code}m")
|
10
|
+
end
|
11
|
+
|
12
|
+
SPECIAL_CHART.each do |name, code|
|
13
|
+
const_set(name.to_s.upcase, code)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/lib/ansi/core.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'ansi/code'
|
2
|
+
|
3
|
+
class ::String
|
4
|
+
#
|
5
|
+
def ansi(*codes)
|
6
|
+
ANSI::Code.ansi(self, *codes)
|
7
|
+
end
|
8
|
+
|
9
|
+
#
|
10
|
+
def ansi!(*codes)
|
11
|
+
replace(ansi(*codes))
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
def unansi
|
16
|
+
ANSI::Code.unansi(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
def unansi!
|
21
|
+
replace(unansi)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
data/lib/ansi/diff.rb
CHANGED
@@ -3,8 +3,6 @@ require 'ansi/code'
|
|
3
3
|
module ANSI
|
4
4
|
|
5
5
|
# Diff can produced a colorized difference of two string or objects.
|
6
|
-
#
|
7
|
-
# IMPORTANT! This class is still a very much a work in progress.
|
8
6
|
class Diff
|
9
7
|
|
10
8
|
#
|
@@ -34,65 +32,8 @@ module ANSI
|
|
34
32
|
|
35
33
|
# Take two plain strings and produce colorized
|
36
34
|
# versions of each highlighting their differences.
|
37
|
-
|
38
|
-
|
39
|
-
# but for now this suffices.
|
40
|
-
def diff_string(str1, str2)
|
41
|
-
i1, i2 = 0, 0
|
42
|
-
m1, m2 = nil, nil
|
43
|
-
s1, s2 = "", ""
|
44
|
-
t1, t2 = "", ""
|
45
|
-
c = 0
|
46
|
-
|
47
|
-
loop do
|
48
|
-
if str1[i1,1] == str2[i2,1]
|
49
|
-
s1 << red(t1); t1 = "" unless t1 == ""
|
50
|
-
s2 << red(t2); t2 = "" unless t2 == ""
|
51
|
-
s1 << str1[i1,1].to_s
|
52
|
-
s2 << str2[i2,1].to_s
|
53
|
-
i1 += 1; i2 += 1
|
54
|
-
#m1 += 1; m2 += 1
|
55
|
-
else
|
56
|
-
if m1 && str1[m1,1] == str2[i2,1]
|
57
|
-
s2 << color1(t2)
|
58
|
-
t1, t2 = "", ""
|
59
|
-
i1 = m1
|
60
|
-
m1, m2 = nil, nil
|
61
|
-
elsif m2 && str1[i1,1] == str2[m2,1]
|
62
|
-
s1 << color2(t1)
|
63
|
-
t1, t2 = "", ""
|
64
|
-
i2 = m2
|
65
|
-
m1, m2 = nil, nil
|
66
|
-
else
|
67
|
-
t1 << str1[i1,1].to_s
|
68
|
-
t2 << str2[i2,1].to_s
|
69
|
-
m1, m2 = i1, i2 if m1 == nil
|
70
|
-
i1 += 1; i2 += 1
|
71
|
-
end
|
72
|
-
end
|
73
|
-
break if i1 >= str1.size && i2 >= str2.size
|
74
|
-
end
|
75
|
-
s1 << red(t1); t1 = "" unless t1 == ""
|
76
|
-
s2 << red(t2); t2 = "" unless t2 == ""
|
77
|
-
#s1 << ANSI::Code::CLEAR
|
78
|
-
#s2 << ANSI::Code::CLEAR
|
79
|
-
|
80
|
-
return s1, s2
|
81
|
-
end
|
82
|
-
|
83
|
-
#
|
84
|
-
def red(str)
|
85
|
-
ANSI.color(:red){ str }
|
86
|
-
end
|
87
|
-
|
88
|
-
#
|
89
|
-
def color1(str)
|
90
|
-
ANSI.color(:blue){ str }
|
91
|
-
end
|
92
|
-
|
93
|
-
#
|
94
|
-
def color2(str)
|
95
|
-
ANSI.color(:green){ str }
|
35
|
+
def diff_string(string1, string2)
|
36
|
+
compare(string1, string2)
|
96
37
|
end
|
97
38
|
|
98
39
|
# Ensure the object of comparison is a string. If +object+ is not
|
@@ -108,6 +49,102 @@ module ANSI
|
|
108
49
|
end
|
109
50
|
end
|
110
51
|
|
52
|
+
# Rotation of colors for diff output.
|
53
|
+
COLORS = [:red, :yellow, :magenta]
|
54
|
+
|
55
|
+
#
|
56
|
+
def compare(x, y)
|
57
|
+
c = common(x, y)
|
58
|
+
a = x.dup
|
59
|
+
b = y.dup
|
60
|
+
oi = 0
|
61
|
+
oj = 0
|
62
|
+
c.each_with_index do |m, q|
|
63
|
+
i = a.index(m, oi)
|
64
|
+
j = b.index(m, oj)
|
65
|
+
a[i,m.size] = ANSI.ansi(m, COLORS[q%3]) if i
|
66
|
+
b[j,m.size] = ANSI.ansi(m, COLORS[q%3]) if j
|
67
|
+
oi = i + m.size if i
|
68
|
+
oj = j + m.size if j
|
69
|
+
end
|
70
|
+
return a, b
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
def common(x,y)
|
75
|
+
c = lcs(x, y)
|
76
|
+
|
77
|
+
i = x.index(c)
|
78
|
+
j = y.index(c)
|
79
|
+
|
80
|
+
ix = i + c.size
|
81
|
+
jx = j + c.size
|
82
|
+
|
83
|
+
if i == 0
|
84
|
+
l = y[0...j]
|
85
|
+
elsif j == 0
|
86
|
+
l = x[0...i]
|
87
|
+
else
|
88
|
+
l = common(x[0...i], y[0...j])
|
89
|
+
end
|
90
|
+
|
91
|
+
if ix == x.size - 1
|
92
|
+
r = y[jx..-1]
|
93
|
+
elsif jx = y.size - 1
|
94
|
+
r = x[ix..-1]
|
95
|
+
else
|
96
|
+
r = common(x[ix..-1], y[jx..-1])
|
97
|
+
end
|
98
|
+
|
99
|
+
[l, c, r].flatten.reject{ |s| s.empty? }
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
def lcs_size(s1, s2)
|
104
|
+
num=Array.new(s1.size){Array.new(s2.size)}
|
105
|
+
len,ans=0
|
106
|
+
s1.scan(/./).each_with_index do |l1,i |
|
107
|
+
s2.scan(/./).each_with_index do |l2,j |
|
108
|
+
unless l1==l2
|
109
|
+
num[i][j]=0
|
110
|
+
else
|
111
|
+
(i==0 || j==0)? num[i][j]=1 : num[i][j]=1 + num[i-1][j-1]
|
112
|
+
len = ans = num[i][j] if num[i][j] > len
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
ans
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
def lcs(s1, s2)
|
121
|
+
res=""
|
122
|
+
num=Array.new(s1.size){Array.new(s2.size)}
|
123
|
+
len,ans=0
|
124
|
+
lastsub=0
|
125
|
+
s1.scan(/./).each_with_index do |l1,i |
|
126
|
+
s2.scan(/./).each_with_index do |l2,j |
|
127
|
+
unless l1==l2
|
128
|
+
num[i][j]=0
|
129
|
+
else
|
130
|
+
(i==0 || j==0)? num[i][j]=1 : num[i][j]=1 + num[i-1][j-1]
|
131
|
+
if num[i][j] > len
|
132
|
+
len = ans = num[i][j]
|
133
|
+
thissub = i
|
134
|
+
thissub -= num[i-1][j-1] unless num[i-1][j-1].nil?
|
135
|
+
if lastsub==thissub
|
136
|
+
res+=s1[i,1]
|
137
|
+
else
|
138
|
+
lastsub=thissub
|
139
|
+
res=s1[lastsub, (i+1)-lastsub]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
res
|
146
|
+
end
|
147
|
+
|
111
148
|
end
|
112
149
|
|
113
150
|
end
|
data/lib/ansi/string.rb
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
require 'ansi/code'
|
2
2
|
#require 'ansi/layout/split'
|
3
|
-
#require 'clio/facets/string'
|
4
3
|
|
5
4
|
# Create a new Ansi::String object.
|
6
5
|
def ANSI.string(str)
|
7
6
|
ANSI::String.new(str)
|
8
7
|
end
|
9
8
|
|
10
|
-
#
|
9
|
+
# IMPORTANT! ANSI::String is experimental!!!
|
11
10
|
#
|
12
|
-
# ANSI
|
13
|
-
#
|
11
|
+
# ANSI::String stores a regular string (`@text`) and an associative
|
12
|
+
# array that ties a character index to an ANSI code (`marks`).
|
14
13
|
# For example is we have the string:
|
15
14
|
#
|
16
15
|
# "Big Apple"
|
17
16
|
#
|
18
|
-
# And applied the color red to it, the marks
|
17
|
+
# And applied the color red to it, the marks list would be:
|
19
18
|
#
|
20
|
-
#
|
19
|
+
# [[0, :red], [9, :clear]]
|
21
20
|
#
|
22
21
|
# TODO: In the future we may be able to subclass String,
|
23
22
|
# instead of delegating via @text, but not until it is more
|
@@ -25,7 +24,7 @@ end
|
|
25
24
|
#
|
26
25
|
class ANSI::String
|
27
26
|
|
28
|
-
CLR = ANSI::Code
|
27
|
+
CLR = ANSI::Code::CLEAR
|
29
28
|
|
30
29
|
attr :text
|
31
30
|
attr :marks
|
@@ -41,7 +40,7 @@ class ANSI::String
|
|
41
40
|
# This converts the intental markup codes to ANSI codes.
|
42
41
|
def to_s
|
43
42
|
s = text.dup
|
44
|
-
m = marks.sort do |
|
43
|
+
m = marks.sort do |a,b|
|
45
44
|
v = b[0] <=> a[0]
|
46
45
|
if v == 0
|
47
46
|
(b[1] == :clear or b[1] == :reset) ? -1 : 1
|
data/lib/ansi/terminal.rb
CHANGED
@@ -16,10 +16,10 @@ module ANSI
|
|
16
16
|
|
17
17
|
modes = %w{win32 termios curses stty}
|
18
18
|
|
19
|
-
#
|
20
19
|
# This section builds character reading and terminal size functions
|
21
|
-
# to suit the proper platform we're running on.
|
22
|
-
#
|
20
|
+
# to suit the proper platform we're running on.
|
21
|
+
#
|
22
|
+
# Be warned: Here be dragons!
|
23
23
|
#
|
24
24
|
begin
|
25
25
|
require 'ansi/terminal/' + (mode = modes.pop)
|
data/qed/01_ansicode.rdoc
CHANGED
@@ -44,13 +44,6 @@ As well as combined color methods.
|
|
44
44
|
str = white_on_red + "Hello"
|
45
45
|
str.assert == "\e[37m\e[41mHello"
|
46
46
|
|
47
|
-
In addition the library offers an extension to String class
|
48
|
-
called #ansi, which allows some of the ANSI::Code methods
|
49
|
-
to be called in a more object-oriented fashion.
|
50
|
-
|
51
|
-
str = "Hello".ansi(:red) + "World".ansi(:blue)
|
52
|
-
str.assert == "\e[31mHello\e[0m\e[34mWorld\e[0m"
|
53
|
-
|
54
47
|
The ANSI::Code module supports most standard ANSI codes, though
|
55
48
|
not all platforms support every code, so YMMV.
|
56
49
|
|
data/qed/09_diff.rb
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
diff = ANSI::Diff.new(a,b)
|
9
9
|
|
10
|
-
|
10
|
+
diff.to_s.assert == "\e[31mabc\e[0m\e[33mYefg\e[0m\n\e[31mabc\e[0mXefg"
|
11
11
|
|
12
12
|
Try another.
|
13
13
|
|
@@ -16,7 +16,7 @@ Try another.
|
|
16
16
|
|
17
17
|
diff = ANSI::Diff.new(a,b)
|
18
18
|
|
19
|
-
|
19
|
+
diff.to_s.assert == "\e[31mabc\e[0m\n\e[31mabc\e[0mdef"
|
20
20
|
|
21
21
|
And another.
|
22
22
|
|
@@ -25,7 +25,7 @@ And another.
|
|
25
25
|
|
26
26
|
diff = ANSI::Diff.new(a,b)
|
27
27
|
|
28
|
-
|
28
|
+
diff.to_s.assert == "\e[31mabc\e[0m\e[33mXXXghi\e[0m\n\e[31mabc\e[0mdefghi"
|
29
29
|
|
30
30
|
And another.
|
31
31
|
|
@@ -34,7 +34,7 @@ And another.
|
|
34
34
|
|
35
35
|
diff = ANSI::Diff.new(a,b)
|
36
36
|
|
37
|
-
|
37
|
+
diff.to_s.assert == "\e[31mabc\e[0m\e[33mXXX\e[0m\e[35mdefghi\e[0m\n\e[31mabc\e[0m\e[35mdefghi\e[0m"
|
38
38
|
|
39
39
|
Comparison that is mostly different.
|
40
40
|
|
@@ -43,5 +43,5 @@ Comparison that is mostly different.
|
|
43
43
|
|
44
44
|
diff = ANSI::Diff.new(a,b)
|
45
45
|
|
46
|
-
|
46
|
+
diff.to_s.assert == "\e[31mabc\e[0m\e[33mpppz123\e[0m\n\e[31mabc\e[0mxyzzz43"
|
47
47
|
|
data/qed/10_core.rdoc
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
= String Extensions
|
2
|
+
|
3
|
+
In addition the library offers an extension to String class
|
4
|
+
called #ansi, which allows some of the ANSI::Code methods
|
5
|
+
to be called in a more object-oriented fashion.
|
6
|
+
|
7
|
+
require 'ansi/core'
|
8
|
+
|
9
|
+
str = "Hello".ansi(:red) + "World".ansi(:blue)
|
10
|
+
str.assert == "\e[31mHello\e[0m\e[34mWorld\e[0m"
|
11
|
+
|
data/test/case_ansicode.rb
CHANGED
@@ -1,19 +1,29 @@
|
|
1
1
|
require 'ansi/code'
|
2
2
|
|
3
|
-
|
3
|
+
testcase ANSI::Code do
|
4
4
|
|
5
|
-
|
5
|
+
unit :red do
|
6
|
+
str = ANSI::Code.red
|
7
|
+
out = "\e[31m"
|
8
|
+
out.assert == str
|
9
|
+
end
|
10
|
+
|
11
|
+
unit :red => "with block notation" do
|
12
|
+
str = ANSI::Code.red { "Hello" }
|
13
|
+
out = "\e[31mHello\e[0m"
|
14
|
+
out.assert == str
|
15
|
+
end
|
6
16
|
|
7
|
-
|
8
|
-
str =
|
9
|
-
out = "\e[
|
10
|
-
out == str
|
17
|
+
unit :blue do
|
18
|
+
str = ANSI::Code.blue
|
19
|
+
out = "\e[34m"
|
20
|
+
out.assert == str
|
11
21
|
end
|
12
22
|
|
13
|
-
|
14
|
-
str =
|
15
|
-
out = "\e[
|
16
|
-
out == str
|
23
|
+
unit :blue => "with block notation" do
|
24
|
+
str = ANSI::Code.blue { "World" }
|
25
|
+
out = "\e[34mWorld\e[0m"
|
26
|
+
out.assert == str
|
17
27
|
end
|
18
28
|
|
19
29
|
end
|
data/test/case_bbcode.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
1
|
require 'ansi/bbcode'
|
2
2
|
|
3
|
-
|
3
|
+
testcase ANSI::BBCode do
|
4
4
|
|
5
|
-
|
5
|
+
meta :bbcode_to_ansi do
|
6
6
|
str = "this is [COLOR=red]red[/COLOR], this is [B]bold[/B]"
|
7
7
|
out = "this is \e[0;31mred\e[0m, this is \e[1mbold\e[0m\n"
|
8
|
-
out == ANSI::BBCode.bbcode_to_ansi(str)
|
8
|
+
out.assert == ANSI::BBCode.bbcode_to_ansi(str)
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
meta :bbcode_to_html do
|
12
12
|
str = "this is [COLOR=red]red[/COLOR], this is [B]bold[/B]"
|
13
13
|
out = "this is <font color=\"red\">red</font>, this is <strong>bold</strong><br />\n"
|
14
|
-
out == ANSI::BBCode.bbcode_to_html(str)
|
14
|
+
out.assert == ANSI::BBCode.bbcode_to_html(str)
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
meta :ansi_to_html do
|
18
18
|
str = "this is \e[0;31mred\e[0m, this is \e[1mbold\e[0m\n" +
|
19
19
|
"this is a line without any ansi code\n" +
|
20
20
|
"this is \e[0;31mred\e[0m, this is \e[1mbold\e[0m\n"
|
21
21
|
out = "this is <font color=\"red\">red</font>, this is <strong>bold</strong><br />\n" +
|
22
22
|
"this is a line without any ansi code<br />\n" +
|
23
23
|
"this is <font color=\"red\">red</font>, this is <strong>bold</strong><br />\n"
|
24
|
-
out == ANSI::BBCode.ansi_to_html(str)
|
24
|
+
out.assert == ANSI::BBCode.ansi_to_html(str)
|
25
25
|
end
|
26
26
|
|
27
27
|
end
|
28
|
-
|
data/test/case_mixin.rb
CHANGED
@@ -1,21 +1,28 @@
|
|
1
1
|
require 'ansi/mixin'
|
2
2
|
|
3
|
-
|
3
|
+
testcase ANSI::Mixin do
|
4
4
|
|
5
|
+
# TODO: subclass
|
5
6
|
class ::String
|
6
7
|
include ANSI::Mixin
|
7
8
|
end
|
8
9
|
|
9
|
-
|
10
|
-
str = "Hello".red
|
11
|
-
out = "\e[31mHello\e[0m
|
12
|
-
out == str
|
10
|
+
unit :red do
|
11
|
+
str = "Hello".red
|
12
|
+
out = "\e[31mHello\e[0m"
|
13
|
+
out.assert == str
|
13
14
|
end
|
14
15
|
|
15
|
-
|
16
|
+
unit :blue do
|
17
|
+
str = "World".blue
|
18
|
+
out = "\e[34mWorld\e[0m"
|
19
|
+
out.assert == str
|
20
|
+
end
|
21
|
+
|
22
|
+
unit :display do
|
16
23
|
str = "Hello".display(4,10)
|
17
24
|
out = "\e[s\e[4;10HHello\e[u"
|
18
|
-
out == str
|
25
|
+
out.assert == str
|
19
26
|
end
|
20
27
|
|
21
28
|
end
|