= ANSI::Code

Require the library.

  require 'ansi/code'

ANSI::Code can be used as a functions module.

  str = ANSI::Code.red + "Hello" + ANSI::Code.blue + "World"
  str.assert == "\e[31mHello\e[34mWorld"

If a block is supplied to each method then yielded value will
be wrapped in the ANSI code and clear code. 

  str = ANSI::Code.red{ "Hello" } + ANSI::Code.blue{ "World" }
  str.assert == "\e[31mHello\e[0m\e[34mWorld\e[0m"

More conveniently the ANSI::Code module extends ANSI itself.

  str = ANSI.red + "Hello" + ANSI.blue + "World"
  str.assert == "\e[31mHello\e[34mWorld"

  str = ANSI.red{ "Hello" } + ANSI.blue{ "World" }
  str.assert == "\e[31mHello\e[0m\e[34mWorld\e[0m"

In the appropriate context the ANSI::Code module can also be
included, making its methods directly accessible.

  include ANSI::Code

  str = red + "Hello" + blue + "World"
  str.assert == "\e[31mHello\e[34mWorld"

  str = red{ "Hello" } + blue{ "World" }
  str.assert == "\e[31mHello\e[0m\e[34mWorld\e[0m"

Along with the single font colors, the library include background colors.

  str = on_red + "Hello"
  str.assert == "\e[41mHello"

As well as combined color methods.

  str = white_on_red + "Hello"
  str.assert == "\e[37m\e[41mHello"

The ANSI::Code module supports most standard ANSI codes, though
not all platforms support every code, so YMMV.


= String Extensions

In addition the library offers an extension to String class
called #ansi, which allows some of the ANSI::Code methods
to be called in a more object-oriented fashion.

  require 'ansi/core'

  str = "Hello".ansi(:red) + "World".ansi(:blue)
  str.assert == "\e[31mHello\e[0m\e[34mWorld\e[0m"


= ANSI::Logger

Require the ANSI::Logger library.

  require 'ansi/logger'

Create a new ANSI::Logger

  log = ANSI::Logger.new(STDOUT)

Info logging appears normal.

  log.info{"Info logs are green.\n"}

Warn logging appears yellow.

  log.warn{"Warn logs are yellow.\n"}

Debug logging appears cyan.

  log.debug{"Debug logs are cyan.\n"}

Error logging appears red.

  log.error{"Error logs are red.\n"}

Fatal logging appears bright red.

  log.fatal{"Fatal logs are bold red!\n"}

QED.

= ANSI::Progressbar

Pretty progress bars are easy to construct.

  require 'ansi/progressbar'

  pbar = ANSI::Progressbar.new("Test Bar", 100)

Running the bar simply requires calling the #inc method during
a loop and calling #finish when done.

  100.times do |i|
    sleep 0.01
    pbar.inc
  end
  pbar.finish

We will use this same rountine in all the examples below, so lets
make a quick macro for it. Notice we have to use #reset first
before reusing the same progress bar.

  def run(pbar)
    pbar.reset
    100.times do |i|
      sleep 0.01
      pbar.inc
    end
    pbar.finish
    puts
  end

The progress bar can be stylized in almost any way.
The #format setter provides control over the parts
that appear on the line. For example, by default the
format is:

  pbar.format("%-14s %3d%% %s %s", :title, :percentage, :bar, :stat)

So lets vary it up to demonstrate the case.

  pbar.format("%-14s %3d%% %s %s", :title, :percentage, :stat, :bar)
  run(pbar)

The progress bar has an extra build in format intended for use with
file downloads called #transer_mode.

  pbar.transfer_mode
  run(pbar)

Calling this methods is the same as calling:

  pbar.format("%-14s %3d%% %s %s",:title, :percentage, :bar, :stat_for_file_transfer)
  run(pbar)

The #style setter allows each part of the line be modified with ANSI codes. And the
#bar_mark writer can be used to change the character used to make the bar.

  pbar.standard_mode
  pbar.style(:title => [:red], :bar=>[:blue])
  pbar.bar_mark = "="
  run(pbar)

QED.

= ANSI::Mixin

The ANSI::Mixin module is design for including into
String-like classes. It will support any class that defines
a #to_s method.

  require 'ansi/mixin'

In this demonstration we will simply include it in the
core String class.

  class ::String
    include ANSI::Mixin
  end

Now all strings will have access to ANSI's style and color
codes via simple method calls.

  "roses".red.assert == "\e[31mroses\e[0m"

  "violets".blue.assert == "\e[34mviolets\e[0m"

  "sugar".italic.assert == "\e[3msugar\e[0m"

The method can be combined, of course.

  "you".italic.bold.assert == "\e[1m\e[3myou\e[0m\e[0m"

The mixin also supports background methods.

  "envy".on_green.assert == "\e[42menvy\e[0m"

And it also supports the combined foreground-on-background 
methods.

  "b&w".white_on_black.assert == "\e[37m\e[40mb&w\e[0m"


= ANSI::String

The ANSI::String class is a very sophisticated implementation
of Ruby's standard String class, but one that can handle
ANSI codes seamlessly.

  require 'ansi/string'

  flower1 = ANSI::String.new("Roses")
  flower2 = ANSI::String.new("Violets")

Like any other string.

  flower1.to_s.assert == "Roses"
  flower2.to_s.assert == "Violets"

Bet now we can add color.

  flower1.red!
  flower2.blue!

  flower1.to_s.assert == "\e[31mRoses\e[0m"
  flower2.to_s.assert == "\e[34mViolets\e[0m"

Despite that the string representation now contains ANSI codes,
we can still manipulate the string in much the same way that
we manipulate an ordinary string.

  flower1.size.assert == 5
  flower2.size.assert == 7

Like ordinary strings we can concatenate the two strings

  flowers = flower1 + ' ' + flower2
  flowers.to_s.assert == "\e[31mRoses\e[0m \e[34mViolets\e[0m"

  flowers.size.assert == 13

Standard case conversion such as #upcase and #downcase work.

  flower1.upcase.to_s.assert == "\e[31mROSES\e[0m"
  flower1.downcase.to_s.assert == "\e[31mroses\e[0m"

Some of the most difficult methods to re-implement were the 
substitution methods such as #sub and #gsub. They are still
somewhat more limited than the original string methods, but
their primary functionality should work.

  flower1.gsub('s', 'z').to_s.assert == "\e[31mRozez\e[0m"

There are still a number of methods that need implementation.
ANSI::String is currently a very partial implementation. But
as you can see from the methods it does currently support,
is it already useful.



= ANSI::Columns

The +Columns+ class makes it easy to create nice looking text columns,
sorted from top to bottom, right to left (as opposed to the other way
around).

  require 'ansi/columns'

  list = %w{a b c d e f g h i j k l}

  columns = ANSI::Columns.new(list)

  columns.to_s(4)

The output will be:

  a d g j
  b e h k
  c f i l

Besides an array of elements, Columns.new can take a string in which
the elements are divided by newlines characters. The default column
size can also be given to the initializer.

  list = "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl"

  columns = ANSI::Columns.new(list, :columns=>6)

  columns.to_s

The output will be:

  a c e g i k
  b d f h j l

If the column count is +nil+, then the number of columns will be calculated
as a best fit for the current terminal window.

== Padding

Columns can adjust the padding between cells.

  list = %w{a b c d e f g h i j k l}

  columns = ANSI::Columns.new(list, :padding=>2)

  columns.to_s(4)

The output will be:

  a  d  g  j
  b  e  h  k
  c  f  i  l

== Alignment

Columns can also be aligned either left or right.

  list = %w{xx xx xx yy y yy z zz z}

  columns = ANSI::Columns.new(list, :align=>:right)

  columns.to_s(3)

The output will be:

  xx yy  z
  xx  y zz
  xx yy  z

== Format

Lastly, columns can be augmented with ANSI codes. This is done through
a formatting block. The block can take up to three parameters, the cell
content, the column and row numbers, or the cell and the column and row
numbers.

  list = %w{a b c d e f g h i j k l}

  columns = ANSI::Columns.new(list){ |c,r| r % 2 == 0 ? :red : :blue }

  out = columns.to_s(4)

  out.assert == (
    "\e[31ma \e[0m\e[31md \e[0m\e[31mg \e[0m\e[31mj \e[0m\n" +
    "\e[34mb \e[0m\e[34me \e[0m\e[34mh \e[0m\e[34mk \e[0m\n" +
    "\e[31mc \e[0m\e[31mf \e[0m\e[31mi \e[0m\e[31ml \e[0m\n"
  )

QED.

= ANSI::Table

The ANSI::Table class can be used to output tabular data with nicely
formated ASCII cell borders.

  require 'ansi/table'

The constructor takes an 2-dimensional array.

  data = [
    [ 10, 20, 30 ],
    [ 20, 10, 20 ],
    [ 50, 40, 20 ]
  ]

  table = ANSI::Table.new(data)

  table.to_s

The output will be:

  +----+----+----+
  | 10 | 20 | 30 |
  | 20 | 10 | 20 |
  | 50 | 40 | 20 |
  +----+----+----+



= ANSI::Diff

  require 'ansi/diff'

  a = 'abcYefg'
  b = 'abcXefg'

  diff = ANSI::Diff.new(a,b)

  diff.to_s.assert == "\e[31mabc\e[0m\e[33mYefg\e[0m\n\e[31mabc\e[0mXefg"

Try another.

  a = 'abc'
  b = 'abcdef'

  diff = ANSI::Diff.new(a,b)

  diff.to_s.assert == "\e[31mabc\e[0m\n\e[31mabc\e[0mdef"

And another.

  a = 'abcXXXghi'
  b = 'abcdefghi'

  diff = ANSI::Diff.new(a,b)

  diff.to_s.assert == "\e[31mabc\e[0m\e[33mXXXghi\e[0m\n\e[31mabc\e[0mdefghi"

And another.

  a = 'abcXXXdefghi'
  b = 'abcdefghi'

  diff = ANSI::Diff.new(a,b)

  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"

Comparison that is mostly different.

  a = 'abcpppz123'
  b = 'abcxyzzz43'

  diff = ANSI::Diff.new(a,b)

  diff.to_s.assert == "\e[31mabc\e[0m\e[33mpppz123\e[0m\n\e[31mabc\e[0mxyzzz43"


= ANSI::BBCode

The BBCode module provides methods for converting between
BBCodes, basic HTML and ANSI codes.

  require 'ansi/bbcode'

BBCodes are color and style codes in square brackets, quite
popular with on line forums.

  bbcode = "this is [COLOR=red]red[/COLOR], this is [B]bold[/B]"

We can convert this to ANSI code simply enough:

  ansi = ANSI::BBCode.bbcode_to_ansi(bbcode)

  ansi.assert == "this is \e[0;31mred\e[0m, this is \e[1mbold\e[0m\n"

In addition the BBCode module supports conversion to simple HTML.

  html = ANSI::BBCode.bbcode_to_html(bbcode)

  html.assert == "this is <font color=\"red\">red</font>, this is <strong>bold</strong><br />\n"


= ANSI::Terminal

We should be ables to get the terminal width via the `terminal_width` method.

  width = ANSI::Terminal.terminal_width

  Fixnum.assert === width


