ansi 1.2.5 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|