styles =
  #styles
  bold: ['\x1B[1m', '\x1B[22m']
  italic: ['\x1B[3m', '\x1B[23m']
  underline: ['\x1B[4m', '\x1B[24m']
  inverse: ['\x1B[7m', '\x1B[27m']
  strikethrough: ['\x1B[9m', '\x1B[29m']
  #text colors
  #grayscale
  white: ['\x1B[37m', '\x1B[39m']
  grey: ['\x1B[90m', '\x1B[39m']
  black: ['\x1B[30m', '\x1B[39m']
  #colors
  blue: ['\x1B[34m', '\x1B[39m']
  cyan: ['\x1B[36m', '\x1B[39m']
  green: ['\x1B[32m', '\x1B[39m']
  magenta: ['\x1B[35m', '\x1B[39m']
  red: ['\x1B[31m', '\x1B[39m']
  yellow: ['\x1B[33m', '\x1B[39m']
  #background colors
  #grayscale
  whiteBG: ['\x1B[47m', '\x1B[49m']
  greyBG: ['\x1B[49;5;8m', '\x1B[49m']
  blackBG: ['\x1B[40m', '\x1B[49m']
  #colors
  blueBG: ['\x1B[44m', '\x1B[49m']
  cyanBG: ['\x1B[46m', '\x1B[49m']
  greenBG: ['\x1B[42m', '\x1B[49m']
  magentaBG: ['\x1B[45m', '\x1B[49m']
  redBG: ['\x1B[41m', '\x1B[49m']
  yellowBG: ['\x1B[43m', '\x1B[49m']

addProperty = (color, func) ->
  # __defineGetter__ at the least works in more browsers
  # http://robertnyman.com/javascript/javascript-getters-setters.html
  # Object.defineProperty only works in Chrome
  String::__defineGetter__ color, func

stylize = (str, style) ->
  "#{styles[style][0]}#{str}#{styles[style][1]}"

# Iterate through all default styles and colors
['bold', 'underline', 'strikethrough', 'italic', 'inverse', 'grey', 'black', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta', 'greyBG', 'blackBG', 'yellowBG', 'redBG', 'greenBG', 'blueBG', 'whiteBG', 'cyanBG', 'magentaBG'].forEach (style) ->
  addProperty style, -> stylize this, style

addProperty 'stripColors', ->
  ("" + this).replace /\x1B\[\d+m/g, ''
