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.
@@ -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
@@ -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
+
@@ -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
- # TODO: I am sure there are better ways to do this,
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
@@ -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
- # = String
9
+ # IMPORTANT! ANSI::String is experimental!!!
11
10
  #
12
- # ANSI Strings store a regular string (@text) and
13
- # a Hash mapping character index to ANSI codes (@marks).
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 hash would be:
17
+ # And applied the color red to it, the marks list would be:
19
18
  #
20
- # { 0=>[:red] , 9=>[:clear] }
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.clear
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 |(a,b)|
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
@@ -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. Be warned: Here be
22
- # dragons!
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)
@@ -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
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  diff = ANSI::Diff.new(a,b)
9
9
 
10
- puts diff.to_s
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
- puts diff.to_s
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
- puts diff.to_s
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
- puts diff.to_s
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
- puts diff.to_s
46
+ diff.to_s.assert == "\e[31mabc\e[0m\e[33mpppz123\e[0m\n\e[31mabc\e[0mxyzzz43"
47
47
 
@@ -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
+
@@ -1,19 +1,29 @@
1
1
  require 'ansi/code'
2
2
 
3
- class TestANSICode < KO::TestCase
3
+ testcase ANSI::Code do
4
4
 
5
- include ANSI::Code
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
- test "base methods" do
8
- str = red + "Hello" + blue + "World"
9
- out = "\e[31mHello\e[34mWorld"
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
- test "block notation" do
14
- str = red { "Hello" } + blue { "World" }
15
- out = "\e[31mHello\e[0m\e[34mWorld\e[0m"
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
@@ -1,28 +1,27 @@
1
1
  require 'ansi/bbcode'
2
2
 
3
- class TC_BBCode < KO::TestCase
3
+ testcase ANSI::BBCode do
4
4
 
5
- test "to_ansi" do
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
- test "to_html" do
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
- test "ansi_to_html" do
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
-
@@ -1,21 +1,28 @@
1
1
  require 'ansi/mixin'
2
2
 
3
- class TestANSIMixin < KO::TestCase
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
- test "methods" do
10
- str = "Hello".red + "World".blue
11
- out = "\e[31mHello\e[0m\e[34mWorld\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
- test "display" do
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