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.
@@ -1,204 +1,130 @@
1
- require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /win32/
2
-
3
1
  module ANSI
4
2
 
5
- # deprecate
6
- SUPPORTED = true
3
+ require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /(win32|w32)/
4
+
5
+ require 'ansi/constants'
6
+
7
+ # Global variialbe can be used to prevent ANSI codes
8
+ # from being used in ANSI's methods that do so to string.
9
+ #
10
+ # NOTE: This has no effect of methods that return ANSI codes.
11
+ $ansi = true
7
12
 
8
- # = ANSI Codes
13
+ # ANSI Codes
9
14
  #
10
15
  # Ansi::Code module makes it very easy to use ANSI codes.
11
16
  # These are esspecially nice for beautifying shell output.
12
17
  #
13
- # include Ansi::Code
14
- #
15
- # red + "Hello" + blue + "World"
18
+ # Ansi::Code.red + "Hello" + Ansi::Code.blue + "World"
16
19
  # => "\e[31mHello\e[34mWorld"
17
20
  #
18
- # red { "Hello" } + blue { "World" }
21
+ # Ansi::Code.red{ "Hello" } + Ansi::Code.blue{ "World" }
19
22
  # => "\e[31mHello\e[0m\e[34mWorld\e[0m"
20
23
  #
21
- # == Supported ANSI Commands
22
- #
23
- # The following is a list of supported display codes.
24
- #
25
- # save
26
- # restore
27
- # clear_screen
28
- # cls # synonym for :clear_screen
29
- # clear_line
30
- # clr # synonym for :clear_line
31
- # move
32
- # up
33
- # down
34
- # left
35
- # right
36
- #
37
- # The following is a list of supported "style" codes.
38
- #
39
- # clear
40
- # reset # synonym for :clear
41
- # bold
42
- # dark
43
- # italic # not widely implemented
44
- # underline
45
- # underscore # synonym for :underline
46
- # blink
47
- # rapid_blink # not widely implemented
48
- # negative # no reverse because of String#reverse
49
- # concealed
50
- # strikethrough # not widely implemented
51
- #
52
- # The following is a list of supported color codes.
53
- #
54
- # black
55
- # red
56
- # green
57
- # yellow
58
- # blue
59
- # magenta
60
- # cyan
61
- # white
62
- #
63
- # on_black
64
- # on_red
65
- # on_green
66
- # on_yellow
67
- # on_blue
68
- # on_magenta
69
- # on_cyan
70
- # on_white
24
+ # IMPORTANT! Do not mixin Ansi::Code, instead use {ANSI::Mixin}.
71
25
  #
72
- # In addition there are color combinations like +red_on_white+.
73
- #
74
- # == Acknowledgement
75
- #
76
- # This library is a partial adaptation of ANSIColor by Florian Frank.
77
- #
78
- # ANSIColor Copyright (c) 2002 Florian Frank
79
- #
80
- # == Developer's Notes
81
- #
82
- # TODO: Any ANSI codes left to add? Modes?
26
+ # See {ANSI::Code::CHART} for list of all supported codes.
83
27
  #
28
+ #--
84
29
  # TODO: up, down, right, left, etc could have yielding methods too?
30
+ #++
85
31
 
86
32
  module Code
87
33
  extend self
88
34
 
89
- CLEAR = "\e[0m"
90
- RESET = "\e[0m"
91
- BOLD = "\e[1m"
92
- DARK = "\e[2m"
93
- ITALIC = "\e[3m" # not widely implemented
94
- UNDERLINE = "\e[4m"
95
- UNDERSCORE = "\e[4m"
96
- BLINK = "\e[5m"
97
- RAPID = "\e[6m" # not widely implemented
98
- REVERSE = "\e[7m"
99
- NEGATIVE = "\e[7m" # alternate to reverse because of String#reverse
100
- CONCEALED = "\e[8m"
101
- STRIKE = "\e[9m" # not widely implemented
102
-
103
- BLACK = "\e[30m"
104
- RED = "\e[31m"
105
- GREEN = "\e[32m"
106
- YELLOW = "\e[33m"
107
- BLUE = "\e[34m"
108
- MAGENTA = "\e[35m"
109
- CYAN = "\e[36m"
110
- WHITE = "\e[37m"
111
-
112
- ON_BLACK = "\e[40m"
113
- ON_RED = "\e[41m"
114
- ON_GREEN = "\e[42m"
115
- ON_YELLOW = "\e[43m"
116
- ON_BLUE = "\e[44m"
117
- ON_MAGENTA = "\e[45m"
118
- ON_CYAN = "\e[46m"
119
- ON_WHITE = "\e[47m"
120
-
121
- # Save current cursor positon.
122
- SAVE = "\e[s"
123
-
124
- # Restore saved cursor positon.
125
- RESTORE = "\e[u"
126
-
127
- # Clear to the end of the current line.
128
- CLEAR_LINE = "\e[K"
129
-
130
- # Clear to the end of the current line.
131
- CLR = "\e[K"
132
-
133
- # Clear the screen and move cursor to home.
134
- CLEAR_SCREEN = "\e[2J"
135
-
136
- # Clear the screen and move cursor to home.
137
- CLS = "\e[2J"
35
+ # include ANSI Constants
36
+ include Constants
37
+
38
+ # Regexp for matching most ANSI codes.
39
+ PATTERN = /\e\[(\d+)m/
138
40
 
41
+ # ANSI clear code.
42
+ ENDCODE = "\e[0m"
43
+
44
+ # List of primary styles.
139
45
  def self.styles
140
46
  %w{bold dark italic underline underscore blink rapid reverse negative concealed strike}
141
47
  end
142
48
 
49
+ # List of primary colors.
50
+ def self.colors
51
+ %w{black red green yellow blue magenta cyan white}
52
+ end
53
+
54
+ =begin
143
55
  styles.each do |style|
144
56
  module_eval <<-END, __FILE__, __LINE__
145
57
  def #{style}(string=nil)
146
58
  if string
59
+ return string unless $ansi
147
60
  #warn "use ANSI block notation for future versions"
148
- return "\#{#{style.upcase}}\#{string}\#{CLEAR}"
61
+ return "\#{#{style.upcase}}\#{string}\#{ENDCODE}"
149
62
  end
150
63
  if block_given?
151
- return "\#{#{style.upcase}}\#{yield}\#{CLEAR}"
64
+ return yield unless $ansi
65
+ return "\#{#{style.upcase}}\#{yield}\#{ENDCODE}"
152
66
  end
153
67
  #{style.upcase}
154
68
  end
155
69
  END
156
70
  end
71
+ =end
157
72
 
158
- def self.colors
159
- %w{black red green yellow blue magenta cyan white}
160
- end
161
-
73
+ =begin
162
74
  # Dynamically create color methods.
163
75
 
164
76
  colors.each do |color|
165
77
  module_eval <<-END, __FILE__, __LINE__
166
78
  def #{color}(string=nil)
167
79
  if string
80
+ return string unless $ansi
168
81
  #warn "use ANSI block notation for future versions"
169
- return "\#{#{color.upcase}}\#{string}\#{CLEAR}"
82
+ return "\#{#{color.upcase}}\#{string}\#{ENDCODE}"
170
83
  end
171
84
  if block_given?
172
- return "\#{#{color.upcase}}\#{yield}\#{CLEAR}"
85
+ return yield unless $ansi
86
+ return "\#{#{color.upcase}}\#{yield}\#{ENDCODE}"
173
87
  end
174
88
  #{color.upcase}
175
89
  end
176
90
 
177
91
  def on_#{color}(string=nil)
178
92
  if string
93
+ return string unless $ansi
179
94
  #warn "use ANSI block notation for future versions"
180
- return "\#{ON_#{color.upcase}}\#{string}\#{CLEAR}"
95
+ return "\#{ON_#{color.upcase}}\#{string}\#{ENDCODE}"
181
96
  end
182
97
  if block_given?
183
- return "\#{ON_#{color.upcase}}\#{yield}\#{CLEAR}"
98
+ return yield unless $ansi
99
+ return "\#{ON_#{color.upcase}}\#{yield}\#{ENDCODE}"
184
100
  end
185
101
  ON_#{color.upcase}
186
102
  end
187
103
  END
188
104
  end
105
+ =end
189
106
 
190
- # Dynamically create color on color methods.
107
+ # Return ANSI code given a list of symbolic names.
108
+ def [](*codes)
109
+ code(*codes)
110
+ end
191
111
 
112
+ # Dynamically create color on color methods.
113
+ #
114
+ # @deprecated
115
+ #
192
116
  colors.each do |color|
193
117
  colors.each do |on_color|
194
118
  module_eval <<-END, __FILE__, __LINE__
195
119
  def #{color}_on_#{on_color}(string=nil)
196
120
  if string
121
+ return string unless $ansi
197
122
  #warn "use ANSI block notation for future versions"
198
- return #{color.upcase} + ON_#{color.upcase} + string + CLEAR
123
+ return #{color.upcase} + ON_#{color.upcase} + string + ENDCODE
199
124
  end
200
125
  if block_given?
201
- #{color.upcase} + ON_#{on_color.upcase} + yield.to_s + CLEAR
126
+ return yield unless $ansi
127
+ #{color.upcase} + ON_#{on_color.upcase} + yield.to_s + ENDCODE
202
128
  else
203
129
  #{color.upcase} + ON_#{on_color.upcase}
204
130
  end
@@ -207,45 +133,35 @@ module ANSI
207
133
  end
208
134
  end
209
135
 
210
- # Clear code.
211
- def clear
212
- CLEAR
213
- end
214
-
215
- # Reset code.
216
- def reset
217
- RESET
218
- end
219
-
220
- # Save current cursor positon.
221
- def save
222
- SAVE
223
- end
136
+ # Use method missing to dispatch ANSI code methods.
137
+ def method_missing(code, *args, &blk)
138
+ esc = nil
224
139
 
225
- # Restore saved cursor positon.
226
- def restore
227
- RESTORE
228
- end
229
-
230
- # Clear to the end of the current line.
231
- def clear_line
232
- CLEAR_LINE
233
- end
234
-
235
- # Clear to the end of the current line.
236
- def clr
237
- CLR
238
- end
140
+ if CHART.key?(code)
141
+ esc = "\e[#{CHART[code]}m"
142
+ elsif SPECIAL_CHART.key?(code)
143
+ esc = SPECIAL_CHART[code]
144
+ end
239
145
 
240
- # Clear the screen and move cursor to home.
241
- def clear_screen
242
- CLEAR_SCREEN
146
+ if esc
147
+ if string = args.first
148
+ return string unless $ansi
149
+ #warn "use ANSI block notation for future versions"
150
+ return "#{esc}#{string}#{ENDCODE}"
151
+ end
152
+ if block_given?
153
+ return yield unless $ansi
154
+ return "#{esc}#{yield}#{ENDCODE}"
155
+ end
156
+ esc
157
+ else
158
+ super(code, *args, &blk)
159
+ end
243
160
  end
244
161
 
245
- # Clear the screen and move cursor to home.
246
- def cls
247
- CLS
248
- end
162
+ # TODO: How to deal with position codes when $ansi is false?
163
+ # Should we reaise an error or just not push the codes?
164
+ # For now, we will leave this it as is.
249
165
 
250
166
  # Like +move+ but returns to original positon after
251
167
  # yielding the block.
@@ -292,127 +208,140 @@ module ANSI
292
208
  # "\e[#;#R"
293
209
  #end
294
210
 
295
- # Apply ansi codes to block yield.
211
+ # Apply ANSI codes to a first argument or block value.
296
212
  #
297
- # style(:red, :on_white){ "Valentine" }
213
+ # @example
214
+ # ansi("Valentine", :red, :on_white)
298
215
  #
299
- def style(*codes) #:yield:
300
- s = ""
301
- codes.each do |code|
302
- s << "\e[#{TABLE[code]}m"
303
- end
304
- s << yield.to_s
305
- s << CLEAR
306
- end
307
-
308
- # Alternate term for #style.
309
- alias_method :color, :style
310
-
216
+ # @example
217
+ # ansi(:red, :on_white){ "Valentine" }
311
218
  #
312
- def unstyle #:yield:
219
+ # @return [String]
220
+ # String wrapped ANSI code.
221
+ #
222
+ def ansi(*codes) #:yield:
313
223
  if block_given?
314
- yield.gsub(PATTERN, '')
224
+ string = yield.to_s
315
225
  else
316
- ''
226
+ string = codes.shift.to_s
317
227
  end
228
+
229
+ return string unless $ansi
230
+
231
+ code(*codes) + string + ENDCODE
318
232
  end
319
233
 
234
+ # Remove ANSI codes from string or block value.
320
235
  #
321
- alias_method :uncolor, :unstyle
322
-
323
- # DEPRECATE: This old term will be deprecated.
324
- def uncolered(string=nil)
325
- warn "ansi: use #uncolor or #unansi for future version"
236
+ # @param [String]
237
+ # String from which to remove ANSI codes.
238
+ #
239
+ # @return [String]
240
+ # String wrapped ANSI code.
241
+ #
242
+ #--
243
+ # TODO: Allow selective removal using *codes argument?
244
+ #++
245
+ def unansi(string=nil) #:yield:
326
246
  if block_given?
327
- yield.gsub(PATTERN, '')
328
- elsif string
329
- string.gsub(PATTERN, '')
247
+ string = yield.to_s
330
248
  else
331
- ''
249
+ string = string.to_s
332
250
  end
251
+ string.gsub(PATTERN, '')
333
252
  end
334
253
 
335
- # This method is just like #style, except it takes a string
336
- # rather than a block. The primary purpose of this method
337
- # is to speed up the String#ansi call.
254
+ # Alias for #ansi method.
338
255
  #
339
- # ansi("Valentine", :red, :on_white)
256
+ # @deprecated
257
+ # Here for backward scompatibility.
258
+ alias_method :style, :ansi
259
+
260
+ # Alias for #unansi method.
261
+ #
262
+ # @deprecated
263
+ # Here for backwards compatibility.
264
+ alias_method :unstyle, :unansi
265
+
266
+ # Alternate term for #ansi.
267
+ #
268
+ # @deprecated
269
+ # May change in future definition.
270
+ alias_method :color, :ansi
271
+
272
+ # Alias for unansi.
340
273
  #
341
- def ansi(string, *codes)
342
- s = ""
274
+ # @deprecated
275
+ # May change in future definition.
276
+ alias_method :uncolor, :unansi
277
+
278
+ # Look-up code from chart, or if Integer simply pass through.
279
+ # Also resolves :random and :on_random.
280
+ #
281
+ # @param codes [Array<Symbol,Integer]
282
+ # Symbols or integers to covnert to ANSI code.
283
+ #
284
+ # @return [String] ANSI code
285
+ def code(*codes)
286
+ list = []
343
287
  codes.each do |code|
344
- s << "\e[#{TABLE[code]}m"
288
+ list << \
289
+ case code
290
+ when Integer
291
+ code
292
+ when Array
293
+ rgb(*code)
294
+ when :random
295
+ random
296
+ when :on_random
297
+ random(true)
298
+ else
299
+ CHART[code.to_sym]
300
+ end
345
301
  end
346
- s << string
347
- s << CLEAR
302
+ "\e[" + (list * ";") + "m"
348
303
  end
349
304
 
350
- # Remove ansi codes from +string+. This method is like unstyle,
351
- # but takes a string rather than a block.
352
- def unansi(string)
353
- string.gsub(PATTERN, '')
305
+ # Provides a random primary ANSI color.
306
+ #
307
+ # @param background [Boolean]
308
+ # Use `true` for background color, otherwise foreground color.
309
+ #
310
+ # @return [Integer] ANSI color number
311
+ def random(background=false)
312
+ (background ? 40 : 30) + rand(8)
354
313
  end
355
314
 
356
- # Regexp for matching style and color codes.
357
- PATTERN = /\e\[([34][0-7]|[0-9])m/
358
-
359
- # Table of style and color codes.
360
- TABLE = {
361
- :clear => 0,
362
- :reset => 0,
363
- :bold => 1,
364
- :dark => 2,
365
- :italic => 3,
366
- :underline => 4,
367
- :underscore => 4,
368
- :blink => 5,
369
- :rapid => 6,
370
- :reverse => 7,
371
- :negative => 7,
372
- :concealed => 8,
373
- :strike => 9,
374
- :black => 30,
375
- :red => 31,
376
- :green => 32,
377
- :yellow => 33,
378
- :blue => 34,
379
- :magenta => 35,
380
- :cyan => 36,
381
- :white => 37,
382
- :on_black => 40,
383
- :on_red => 41,
384
- :on_green => 42,
385
- :on_yellow => 43,
386
- :on_blue => 44,
387
- :on_magenta => 45,
388
- :on_cyan => 46,
389
- :on_white => 47
390
- }
391
- end
315
+ # Creates an xterm-256 color from rgb value.
316
+ #
317
+ # @param background [Boolean]
318
+ # Use `true` for background color, otherwise foreground color.
319
+ #
320
+ def rgb(red, green, blue, background=false)
321
+ "#{background ? 48 : 38};5;#{rgb_value(red, green, blue)}"
322
+ end
392
323
 
393
- extend Code
394
- end
324
+ # Creates an xterm-256 color from a CSS-style color string.
325
+ def hex(string, background=false)
326
+ string.tr!('#','')
327
+ x = (string.size == 6 ? 2 : 1)
328
+ r, g, b = [0,1,2].map{ |i| string[i*x,2].to_i(16) }
329
+ rgb(r, g, b, background)
330
+ end
395
331
 
396
- #
397
- class String
398
- #
399
- def ansi(*codes)
400
- ANSI::Code.ansi(self, *codes)
401
- end
332
+ private
402
333
 
403
- #
404
- def ansi!(*codes)
405
- replace(ansi(*codes))
406
- end
334
+ # Gets closest xterm-256 color.
335
+ def rgb_256(r, g, b)
336
+ r, g, b = [r, g, b].map{ |c| rgb_valid(c); (6 * (c.to_f / 256.0)).to_i }
337
+ v = (r * 36 + g * 6 + b + 16).abs
338
+ raise ArgumentError, "RGB value outside 0-255 range" if v > 255
339
+ v
340
+ end
407
341
 
408
- #
409
- def unansi
410
- ANSI::Code.unansi(self)
411
342
  end
412
343
 
413
344
  #
414
- def unansi!
415
- replace(unansi)
416
- end
345
+ extend Code
417
346
  end
418
347