ansi 1.4.1 → 1.4.2

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.
@@ -1,4 +1,4 @@
1
- # = BBCode
1
+ # BBCode
2
2
  #
3
3
  # Copyright (c) 2002 Thomas-Ivo Heinen
4
4
  #
@@ -9,31 +9,26 @@
9
9
  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
10
  # FOR A PARTICULAR PURPOSE.
11
11
 
12
+ #
12
13
  module ANSI
13
14
 
14
- # = BBCode
15
- #
15
+ # TODO: Integrate BBCode with Code module.
16
+
16
17
  # The BBCode module helps ease the separation of core and frontend with the
17
18
  # core (or submodules) being still able to say, what colors shall be used
18
19
  # in it's responses. This is achieved by encoding formatting information
19
20
  # using the BBCode tokens. This enables you to "pipe" layout information
20
- # such as colors, style, fonttype, size and alignment through the core to
21
+ # such as colors, style, font, size and alignment through the core to
21
22
  # the frontend.
22
23
  #
23
24
  # Additionally it converts markups/codes between ANSI, HTML and BBCode
24
25
  # almost freely ;)
25
26
  #
26
- # == Usage
27
- #
28
27
  # # Converting a bbcode string to ANSI and XHTML
29
- #
30
28
  # str = "this is [COLOR=red]red[/COLOR], this is [B]bold[/B]"
31
29
  # print( BBCode.bbcode_to_ansi(str) )
32
30
  # print( BBCode.bbcode_to_html(str) )
33
31
  #
34
- #--
35
- # TODO: integrate with Code module.
36
- #++
37
32
  module BBCode
38
33
 
39
34
  ## ANSIname => ANSIcode LUT
@@ -0,0 +1,50 @@
1
+ require 'ansi/code'
2
+
3
+ module ANSI
4
+
5
+ # ANSI::Chain was inspired by Kazuyoshi Tlacaelel's Isna library.
6
+ #
7
+ class Chain
8
+
9
+ #
10
+ def initialize(string)
11
+ @string = string.to_s
12
+ @codes = []
13
+ end
14
+
15
+ #
16
+ attr :string
17
+
18
+ #
19
+ attr :codes
20
+
21
+ #
22
+ def method_missing(s, *a, &b)
23
+ if ANSI::CHART.key?(s)
24
+ @codes << s
25
+ self
26
+ else
27
+ super(s, *a, &b)
28
+ end
29
+ end
30
+
31
+ #
32
+ def to_s
33
+ if codes.empty?
34
+ result = @string
35
+ else
36
+ result = Code.ansi(@string, *codes)
37
+ codes.clear
38
+ end
39
+ result
40
+ end
41
+
42
+ #
43
+ def to_str
44
+ to_s
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
@@ -19,6 +19,7 @@ module ANSI
19
19
  :slow_blink => 5,
20
20
  :rapid => 6,
21
21
  :rapid_blink => 6,
22
+ :invert => 7,
22
23
  :inverse => 7,
23
24
  :reverse => 7,
24
25
  :negative => 7,
@@ -17,6 +17,8 @@ module ANSI
17
17
  # NOTE: This has no effect of methods that return ANSI codes.
18
18
  $ansi = true
19
19
 
20
+ # TODO: up, down, right, left, etc could have yielding methods too?
21
+
20
22
  # ANSI Codes
21
23
  #
22
24
  # Ansi::Code module makes it very easy to use ANSI codes.
@@ -32,10 +34,6 @@ module ANSI
32
34
  #
33
35
  # See {ANSI::Code::CHART} for list of all supported codes.
34
36
  #
35
- #--
36
- # TODO: up, down, right, left, etc could have yielding methods too?
37
- #++
38
-
39
37
  module Code
40
38
  extend self
41
39
 
@@ -235,9 +233,13 @@ module ANSI
235
233
 
236
234
  return string unless $ansi
237
235
 
238
- code(*codes) + string + ENDCODE
236
+ c = code(*codes)
237
+
238
+ c + string.gsub(ENDCODE, ENDCODE + c) + ENDCODE
239
239
  end
240
240
 
241
+ # TODO: Allow selective removal using *codes argument?
242
+
241
243
  # Remove ANSI codes from string or block value.
242
244
  #
243
245
  # @param [String]
@@ -246,9 +248,6 @@ module ANSI
246
248
  # @return [String]
247
249
  # String wrapped ANSI code.
248
250
  #
249
- #--
250
- # TODO: Allow selective removal using *codes argument?
251
- #++
252
251
  def unansi(string=nil) #:yield:
253
252
  if block_given?
254
253
  string = yield.to_s
@@ -3,32 +3,47 @@ require 'ansi/terminal'
3
3
 
4
4
  module ANSI
5
5
 
6
+ #
6
7
  class Columns
7
8
 
8
9
  # Create a column-based layout.
9
10
  #
10
- # list - Multiline String or Array of strings to columnize
11
+ # @param [String,Array] list
12
+ # Multiline String or Array of strings to columnize.
11
13
  #
12
- # options[:columns] - number of columns
13
- # options[:align] - align :left or :right
14
- # options[:padding] - space to add to each cell
14
+ # @param [Hash] options
15
+ # Options to customize columnization.
16
+ #
17
+ # @option options [Fixnum] :columns
18
+ # Number of columns.
19
+ #
20
+ # @option options [Symbol] :align
21
+ # Column alignment, either :left, :right or :center.
22
+ #
23
+ # @option options [String,Fixnum] :padding
24
+ # String or number or spaces to append to each column.
15
25
  #
16
26
  # The +format+ block MUST return ANSI codes.
17
27
  def initialize(list, options={}, &format)
18
28
  self.list = list
19
29
 
20
- @columns = options[:columns]
21
- @padding = options[:padding] || 1
22
- @align = options[:align]
23
- #@ansi = [options[:ansi]].flatten
24
- @format = format
30
+ self.columns = options[:columns] || options[:cols]
31
+ self.padding = options[:padding] || 1
32
+ self.align = options[:align] || :left
33
+ #self.ansi = options[:ansi]
34
+ self.format = format
25
35
 
26
- @columns = nil if @columns == 0
36
+ #@columns = nil if @columns == 0
37
+ end
38
+
39
+ #
40
+ def inspect
41
+ "#<#{self.class}:#{object_id} #{list.inspect} x #{columns}>"
27
42
  end
28
43
 
29
44
  # List layout into columns. Each new line is taken to be
30
45
  # a row-column cell.
31
- attr_accessor :list
46
+ attr :list
32
47
 
33
48
  def list=(list)
34
49
  case list
@@ -41,38 +56,80 @@ module ANSI
41
56
 
42
57
  # Default number of columns to display. If nil then the number
43
58
  # of coumns is estimated from the size of the terminal.
44
- attr_accessor :columns
59
+ attr :columns
60
+
61
+ # Set column count ensuring value is either an integer or nil.
62
+ # The the value given is zero, it will be taken to mean the same
63
+ # as nil, which means fit-to-screen.
64
+ def columns=(integer)
65
+ integer = integer.to_i
66
+ @columns = (integer.zero? ? nil : integer)
67
+ end
45
68
 
46
69
  # Padding size to apply to cells.
47
- attr_accessor :padding
70
+ attr :padding
71
+
72
+ # Set padding to string or number (of spaces).
73
+ def padding=(pad)
74
+ case pad
75
+ when Numeric
76
+ @padding = ' ' * pad.to_i
77
+ else
78
+ @padding = pad.to_s
79
+ end
80
+ end
48
81
 
49
82
  # Alignment to apply to cells.
50
- attr_accessor :align
83
+ attr :align
84
+
85
+ # Set alignment ensuring value is a symbol.
86
+ #
87
+ # @param [Symbol] Either `:right`, `:left` or `:center`.
88
+ def align=(symbol)
89
+ symbol = symbol.to_sym
90
+ raise ArgumentError, "invalid alignment -- #{symbol.inspect}" \
91
+ unless [:left, :right, :center].include?(symbol)
92
+ @align = symbol
93
+ end
51
94
 
52
95
  # Formating to apply to cells.
53
- attr_accessor :format
96
+ attr :format
97
+
98
+ # Set formatting procedure. The procedure must return
99
+ # ANSI codes, suitable for passing to String#ansi method.
100
+ def format=(procedure)
101
+ @format = procedure ? procedure.to_proc : nil
102
+ end
103
+
104
+ # TODO: Should #to_s also take options and formatting block?
105
+ # Maybe instead have hoin take all these and leave #to_s bare.
54
106
 
55
107
  # Return string in column layout. The number of columns is determined
56
108
  # by the `columns` property or overriden by +cols+ argument.
57
- #--
58
- # TODO: Allow #to_s to take options and formating block?
59
- #++
60
109
  def to_s(cols=nil)
61
110
  to_s_columns(cols || columns)
62
111
  end
63
112
 
64
- private
113
+ #
114
+ def join(cols=nil)
115
+ to_s_columns(cols || columns)
116
+ end
117
+
118
+ private
65
119
 
66
120
  # Layout string lines into columns.
67
121
  #
68
- # TODO: put in empty strings for blank cells
122
+ # @todo Put in empty strings for blank cells.
123
+ # @todo Centering look like it's off by one to the right.
124
+ #
69
125
  def to_s_columns(columns=nil)
70
126
  lines = list.to_a
71
127
  count = lines.size
72
128
  max = lines.map{ |l| l.size }.max
129
+
73
130
  if columns.nil?
74
131
  width = Terminal.terminal_width
75
- columns = (width / (max + padding)).to_i
132
+ columns = (width / (max + padding.size)).to_i
76
133
  end
77
134
 
78
135
  rows = []
@@ -83,12 +140,12 @@ module ANSI
83
140
  (rows[index % mod] ||=[]) << line.strip
84
141
  end
85
142
 
86
- pad = " " * padding
143
+ pad = padding
87
144
  tmp = template(max, pad)
88
145
  str = ""
89
146
  rows.each_with_index do |row, ri|
90
147
  row.each_with_index do |cell, ci|
91
- ansi_codes = ansi_formating(cell, ci, ri)
148
+ ansi_codes = ansi_formatting(cell, ci, ri)
92
149
  if ansi_codes.empty?
93
150
  str << (tmp % cell)
94
151
  else
@@ -102,10 +159,11 @@ module ANSI
102
159
  end
103
160
 
104
161
  # Aligns the cell left or right.
105
- #
106
- # TODO: Handle centered alignment.
107
162
  def template(max, pad)
108
163
  case align
164
+ when :center, 'center'
165
+ offset = " " * (max / 2)
166
+ "#{offset}%#{max}s#{offset}#{pad}"
109
167
  when :right, 'right'
110
168
  "%#{max}s#{pad}"
111
169
  else
@@ -113,8 +171,8 @@ module ANSI
113
171
  end
114
172
  end
115
173
 
116
- # Used to apply ANSI formating to each cell.
117
- def ansi_formating(cell, col, row)
174
+ # Used to apply ANSI formatting to each cell.
175
+ def ansi_formatting(cell, col, row)
118
176
  if @format
119
177
  case @format.arity
120
178
  when 0
@@ -1,10 +1,17 @@
1
1
  module ANSI
2
2
 
3
+ require 'ansi/chart'
4
+
3
5
  # Converts {CHART} and {SPECIAL_CHART} entries into constants.
6
+ # So for example, the CHART entry for :red becomes:
7
+ #
8
+ # ANSI::Constants::RED #=> "\e[31m"
9
+ #
10
+ # The ANSI Constants are include into ANSI::Code and can be included
11
+ # any where will they would be of use.
12
+ #
4
13
  module Constants
5
14
 
6
- require 'ansi/chart'
7
-
8
15
  CHART.each do |name, code|
9
16
  const_set(name.to_s.upcase, "\e[#{code}m")
10
17
  end
@@ -1,9 +1,15 @@
1
1
  require 'ansi/code'
2
+ require 'ansi/chain'
2
3
 
3
4
  class ::String
5
+
4
6
  #
5
7
  def ansi(*codes)
6
- ANSI::Code.ansi(self, *codes)
8
+ if codes.empty?
9
+ ANSI::Chain.new(self)
10
+ else
11
+ ANSI::Code.ansi(self, *codes)
12
+ end
7
13
  end
8
14
 
9
15
  #
@@ -2,9 +2,33 @@ require 'ansi/code'
2
2
 
3
3
  module ANSI
4
4
 
5
- # Diff can produced a colorized difference of two string or objects.
5
+ # Diff produces colorized differences of two string or objects.
6
+ #
6
7
  class Diff
7
8
 
9
+ # Highlights the differnce between two strings.
10
+ #
11
+ # This class method is equivalent to calling:
12
+ #
13
+ # ANSI::Diff.new(object1, object2).to_a
14
+ #
15
+ def self.diff(object1, object2, options={})
16
+ new(object1, object2, options={}).to_a
17
+ end
18
+
19
+ # Setup new Diff object. If the objects given are not Strings
20
+ # and do not have `#to_str` defined to coerce them to such, then
21
+ # their `#inspect` methods are used to convert them to strings
22
+ # for comparison.
23
+ #
24
+ # @param [Object] object1
25
+ # First object to compare.
26
+ #
27
+ # @param [Object] object2
28
+ # Second object to compare.
29
+ #
30
+ # @param [Hash] options
31
+ # Options for contoller the way difference is shown. (Not yet used.)
8
32
  #
9
33
  def initialize(object1, object2, options={})
10
34
  @object1 = convert(object1)
@@ -13,25 +37,56 @@ module ANSI
13
37
  @diff1, @diff2 = diff_string(@object1, @object2)
14
38
  end
15
39
 
16
- #
40
+ # Returns the first object's difference string.
17
41
  def diff1
18
42
  @diff1
19
43
  end
20
44
 
21
- #
45
+ # Returns the second object's difference string.
22
46
  def diff2
23
47
  @diff2
24
48
  end
25
49
 
50
+ # Returns both first and second difference strings separated by a
51
+ # new line character.
26
52
  #
53
+ # @todo Should we use `$/` record separator instead?
54
+ #
55
+ # @return [String] Joined difference strings.
27
56
  def to_s
28
57
  "#{@diff1}\n#{@diff2}"
29
58
  end
30
59
 
31
- private
60
+ # Returns both first and second difference strings separated by a
61
+ # the given `separator`. The default is `$/`, the record separator.
62
+ #
63
+ # @param [String] separator
64
+ # The string to use as the separtor between the difference strings.
65
+ #
66
+ # @return [String] Joined difference strings.
67
+ def join(separator=$/)
68
+ "#{@diff1}#{separator}#{@diff2}"
69
+ end
70
+
71
+ # Returns the first and second difference strings in an array.
72
+ #
73
+ # @return [Array] Both difference strings.
74
+ def to_a
75
+ [diff1, diff2]
76
+ end
77
+
78
+ private
32
79
 
33
80
  # Take two plain strings and produce colorized
34
81
  # versions of each highlighting their differences.
82
+ #
83
+ # @param [String] string1
84
+ # First string to compare.
85
+ #
86
+ # @param [String] string2
87
+ # Second string to compare.
88
+ #
89
+ # @return [Array<String>] The two difference strings.
35
90
  def diff_string(string1, string2)
36
91
  compare(string1, string2)
37
92
  end
@@ -52,7 +107,16 @@ module ANSI
52
107
  # Rotation of colors for diff output.
53
108
  COLORS = [:red, :yellow, :magenta]
54
109
 
110
+ # Take two plain strings and produce colorized
111
+ # versions of each highlighting their differences.
55
112
  #
113
+ # @param [String] string1
114
+ # First string to compare.
115
+ #
116
+ # @param [String] string2
117
+ # Second string to compare.
118
+ #
119
+ # @return [Array<String>] The two difference strings.
56
120
  def compare(x, y)
57
121
  c = common(x, y)
58
122
  a = x.dup
@@ -70,7 +134,8 @@ module ANSI
70
134
  return a, b
71
135
  end
72
136
 
73
- #
137
+ # Oh, I should have documented this will I knew what the
138
+ # hell it was doing ;)
74
139
  def common(x,y)
75
140
  c = lcs(x, y)
76
141
 
@@ -99,24 +164,7 @@ module ANSI
99
164
  [l, c, r].flatten.reject{ |s| s.empty? }
100
165
  end
101
166
 
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
- #
167
+ # Least common string.
120
168
  def lcs(s1, s2)
121
169
  res=""
122
170
  num=Array.new(s1.size){Array.new(s2.size)}
@@ -145,6 +193,23 @@ module ANSI
145
193
  res
146
194
  end
147
195
 
196
+ # Hmm... is this even useful?
197
+ def lcs_size(s1, s2)
198
+ num=Array.new(s1.size){Array.new(s2.size)}
199
+ len,ans=0,0
200
+ s1.scan(/./).each_with_index do |l1,i |
201
+ s2.scan(/./).each_with_index do |l2,j |
202
+ unless l1==l2
203
+ num[i][j]=0
204
+ else
205
+ (i==0 || j==0)? num[i][j]=1 : num[i][j]=1 + num[i-1][j-1]
206
+ len = ans = num[i][j] if num[i][j] > len
207
+ end
208
+ end
209
+ end
210
+ ans
211
+ end
212
+
148
213
  end
149
214
 
150
215
  end