From 9e1ea1ef91bfda7f213db845904885de11f7c9c0 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 22:41:40 -0400 Subject: [PATCH 01/84] Automatically disable color --- clint/textui/colored.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clint/textui/colored.py b/clint/textui/colored.py index dcee9616..d4721030 100644 --- a/clint/textui/colored.py +++ b/clint/textui/colored.py @@ -27,6 +27,8 @@ if sys.stdout.isatty(): colorama.init(autoreset=True) +else: + DISABLE_COLOR = True class ColoredString(object): From 5d733d123d86ba244cc6a23c5acf788d6f7ababc Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 22:46:57 -0400 Subject: [PATCH 02/84] put progress uis in separate namespace (for now) --- clint/textui/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clint/textui/core.py b/clint/textui/core.py index d782cd0a..45350326 100644 --- a/clint/textui/core.py +++ b/clint/textui/core.py @@ -13,13 +13,13 @@ import sys -from .progress import progressbar +from . import progress from .formatters import max_width, min_width from .cols import columns from ..utils import tsplit -__all__ = ('puts', 'puts_err', 'indent', 'progressbar', 'columns', 'max_width', 'min_width') +__all__ = ('puts', 'puts_err', 'indent', 'progress', 'columns', 'max_width', 'min_width') STDOUT = sys.stdout.write From f12e47fa7c96f54440c15daf682948c8000c8d96 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 22:47:18 -0400 Subject: [PATCH 03/84] add dots progress iterator --- clint/textui/progress.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/clint/textui/progress.py b/clint/textui/progress.py index a61aba03..4b18bbab 100644 --- a/clint/textui/progress.py +++ b/clint/textui/progress.py @@ -30,3 +30,18 @@ def _show(_i): if not hide: sys.stdout.write("\n") sys.stdout.flush() + + +def dots(it, prefix='', hide=False): + """Progress iterator. Prints a dot for each item being iterated""" + count = len(it) + if count: + def _show(_i): + sys.stdout.write('.') + + _show(0) + for i, item in enumerate(it): + yield item + _show(i+1) + if not hide: + sys.stdout.write("\n") From 2369bc387d3c72a566e5995a5ce1379cf26c7c7a Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 22:47:33 -0400 Subject: [PATCH 04/84] progressbar => bar --- clint/textui/progress.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clint/textui/progress.py b/clint/textui/progress.py index 4b18bbab..45a70058 100644 --- a/clint/textui/progress.py +++ b/clint/textui/progress.py @@ -13,7 +13,7 @@ import sys -def progressbar(it, prefix='', size=32, hide=False): +def bar(it, prefix='', size=32, hide=False): """Progress iterator. Wrap your iterables with it.""" count = len(it) if count: From d0f2375a7bbbd126d2462116fc35e0e378d3ce5f Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 22:51:49 -0400 Subject: [PATCH 05/84] No more '>' in progress bar --- clint/textui/progress.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clint/textui/progress.py b/clint/textui/progress.py index 45a70058..f7038424 100644 --- a/clint/textui/progress.py +++ b/clint/textui/progress.py @@ -20,7 +20,7 @@ def bar(it, prefix='', size=32, hide=False): def _show(_i): x = int(size*_i/count) if not hide: - sys.stdout.write("%s[%s>%s] %i/%i\r" % (prefix, "="*x, "-"*(size-x), _i, count)) + sys.stdout.write("%s[%s%s] %i/%i\r" % (prefix, "="*x, "-"*(size-x), _i, count)) sys.stdout.flush() _show(0) From 2d200e3709ef05d2fe2d664992e79933b8807aaa Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 22:53:15 -0400 Subject: [PATCH 06/84] progress.bar(width=), not size. --- clint/textui/progress.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clint/textui/progress.py b/clint/textui/progress.py index f7038424..4058c570 100644 --- a/clint/textui/progress.py +++ b/clint/textui/progress.py @@ -13,14 +13,14 @@ import sys -def bar(it, prefix='', size=32, hide=False): +def bar(it, prefix='', width=32, hide=False): """Progress iterator. Wrap your iterables with it.""" count = len(it) if count: def _show(_i): - x = int(size*_i/count) + x = int(width*_i/count) if not hide: - sys.stdout.write("%s[%s%s] %i/%i\r" % (prefix, "="*x, "-"*(size-x), _i, count)) + sys.stdout.write("%s[%s%s] %i/%i\r" % (prefix, "="*x, "-"*(width-x), _i, count)) sys.stdout.flush() _show(0) From 763ca94e7ba325df0b9f5bba1f03da63292101d7 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 23:03:13 -0400 Subject: [PATCH 07/84] newline support for textui.puts --- clint/textui/core.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clint/textui/core.py b/clint/textui/core.py index 45350326..3418cc18 100644 --- a/clint/textui/core.py +++ b/clint/textui/core.py @@ -13,13 +13,12 @@ import sys -from . import progress from .formatters import max_width, min_width from .cols import columns from ..utils import tsplit -__all__ = ('puts', 'puts_err', 'indent', 'progress', 'columns', 'max_width', 'min_width') +__all__ = ('puts', 'puts_err', 'indent', 'columns', 'max_width', 'min_width') STDOUT = sys.stdout.write @@ -81,7 +80,7 @@ def __call__(self, s, newline=True, stream=STDOUT): def puts(s, newline=True): """Prints given string to stdout via Writer interface.""" - Writer()(s, stream=STDOUT) + Writer()(s, newline, stream=STDOUT) def puts_err(s, newline=True): From 8b7161b15b789c97c3b4b8c77c3c36d9848ec561 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 23:03:34 -0400 Subject: [PATCH 08/84] Configurable progress bars :) Argument changes. --- clint/textui/progress.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/clint/textui/progress.py b/clint/textui/progress.py index 4058c570..11bf1741 100644 --- a/clint/textui/progress.py +++ b/clint/textui/progress.py @@ -10,17 +10,26 @@ from __future__ import absolute_import +from .core import puts + import sys +BAR_TEMPLATE = '%s[%s%s] %i/%i\r' +BAR_EMPTY_CHAR = '-' +BAR_FILLED_CHAR = '=' + +DOTS_CHAR = '.' + -def bar(it, prefix='', width=32, hide=False): +def bar(it, label='', width=32, hide=False): """Progress iterator. Wrap your iterables with it.""" count = len(it) if count: def _show(_i): x = int(width*_i/count) if not hide: - sys.stdout.write("%s[%s%s] %i/%i\r" % (prefix, "="*x, "-"*(width-x), _i, count)) + puts(BAR_TEMPLATE % ( + label, BAR_FILLED_CHAR*x, BAR_EMPTY_CHAR*(width-x), _i, count), newline=False) sys.stdout.flush() _show(0) @@ -32,12 +41,15 @@ def _show(_i): sys.stdout.flush() -def dots(it, prefix='', hide=False): +def dots(it, label='', hide=False): """Progress iterator. Prints a dot for each item being iterated""" count = len(it) + + puts(label, newline=False) if count: def _show(_i): - sys.stdout.write('.') + # sys.stdout.write('.') + puts(DOTS_CHAR, newline=False) _show(0) for i, item in enumerate(it): From aa5008b2e051a2f7badaf86d8f348e30c8660736 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 23:03:39 -0400 Subject: [PATCH 09/84] namespace fix --- clint/textui/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clint/textui/__init__.py b/clint/textui/__init__.py index aa3a36a7..39681c68 100644 --- a/clint/textui/__init__.py +++ b/clint/textui/__init__.py @@ -10,4 +10,6 @@ from . import colored +from . import progress + from core import * From 164d68ce37cb21116ee0f5c81fce94175c7483f2 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Wed, 30 Mar 2011 23:08:33 -0400 Subject: [PATCH 10/84] loggin' --- HISTORY.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index 4af4b7ff..2e1cb547 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,6 +1,15 @@ History ------- +0.2.2 ++++++ + +Auto Color Disabling +Progress Namespace Change +New Progress Bars +textui.puts newline fix + + 0.2.1 (2011-03-24) ++++++++++++++++++ From 2e68207d0a519b5b065b5721e206f9efd26cbb35 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Thu, 31 Mar 2011 00:48:02 -0400 Subject: [PATCH 11/84] updated readme for newcomers --- README.rst | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 05fd4dbd..af8b20bf 100644 --- a/README.rst +++ b/README.rst @@ -15,7 +15,7 @@ commandline applications. Clint is awesome. Crazy awesome. It supports colors, but detects if the session is a TTY, so doesn't render the colors if you're piping stuff around. Automagically. -Awesome nestable indentation context manager. Example: (``with indent(4): puts('indented text')``). It supports custom email-style quotes. Of course, it supports color too, if and when needed. +Awesome nest-able indentation context manager. Example: (``with indent(4): puts('indented text')``). It supports custom email-style quotes. Of course, it supports color too, if and when needed. It has an awesome Column printer with optional auto-expanding columns. It detects how wide your current console is and adjusts accordingly. It wraps your words properly to fit the column size. With or without colors mixed in. All with a single function call. @@ -29,16 +29,24 @@ You'll never want to not use it. - -Features: ---------- +Current Features: +----------------- - Little Documentation (bear with me for now) - CLI Colors and Indents - Iterator-based Progress Bar - Implicit Argument Handling -- Simple Support for Unix Pipes +- Simple Support for Incoming Unix Pipes - Application Directory management + +Future Features: +---------------- +- Documentation! +- Simple choice system `Are you sure? [Yn]` +- Default query system `Installation Path [/usr/local/bin/]` +- Suggestions welcome. + + Example ------- From 9736b4cd71e298f262505a676f54769ef96be2f5 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Thu, 31 Mar 2011 01:05:07 -0400 Subject: [PATCH 12/84] oh yeah, columns. --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index af8b20bf..500f39d5 100644 --- a/README.rst +++ b/README.rst @@ -33,6 +33,7 @@ Current Features: ----------------- - Little Documentation (bear with me for now) - CLI Colors and Indents +- Extremely Simple + Powerful Column Printer - Iterator-based Progress Bar - Implicit Argument Handling - Simple Support for Incoming Unix Pipes From fa2bbf9a0dcd4b80afef98a112dad1b034d224c0 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Thu, 31 Mar 2011 01:07:54 -0400 Subject: [PATCH 13/84] link to examples directory --- README.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 500f39d5..1f0d5f18 100644 --- a/README.rst +++ b/README.rst @@ -22,8 +22,9 @@ It has an awesome Column printer with optional auto-expanding columns. It detect The world's easiest to use implicit argument system w/ chaining methods for filtering. Seriously. -Run the various executables in ``./examples`` to get a good feel for what Clint offers. +Run the various executables in examples_ to get a good feel for what Clint offers. +.. _examples: https://github.com/kennethreitz/clint/tree/develop/examples You'll never want to not use it. From a4c2be8865890f7a9be316e79c344c63071fda5d Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Thu, 31 Mar 2011 06:16:09 -0400 Subject: [PATCH 14/84] pre me right --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 1f0d5f18..a2fa853d 100644 --- a/README.rst +++ b/README.rst @@ -44,8 +44,8 @@ Current Features: Future Features: ---------------- - Documentation! -- Simple choice system `Are you sure? [Yn]` -- Default query system `Installation Path [/usr/local/bin/]` +- Simple choice system ``Are you sure? [Yn]`` +- Default query system ``Installation Path [/usr/local/bin/]`` - Suggestions welcome. From cf0c0bda70f0d9c68b1325037e08686d2e4ce0a6 Mon Sep 17 00:00:00 2001 From: Will Thames Date: Thu, 31 Mar 2011 12:21:57 +0100 Subject: [PATCH 15/84] Moved from __future__ line closer to the top of the file to prevent File "piped.py", line 7 from __future__ import with_statement SyntaxError: from __future__ imports must occur at the beginning of the file --- examples/piped.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/piped.py b/examples/piped.py index 63701d4e..f0a4ebaf 100644 --- a/examples/piped.py +++ b/examples/piped.py @@ -1,11 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +from __future__ import with_statement + import sys import os -from __future__ import with_statement - sys.path.insert(0, os.path.abspath('..')) from clint import piped_in @@ -23,4 +23,4 @@ with indent(5, quote=colored.red(' |')): puts(in_data) else: - puts(colored.red('Warning: ') + 'No data was piped in.') \ No newline at end of file + puts(colored.red('Warning: ') + 'No data was piped in.') From 3406ab5329a006002c0889369b66dbc7e8b37f6c Mon Sep 17 00:00:00 2001 From: Will Thames Date: Thu, 31 Mar 2011 12:24:42 +0100 Subject: [PATCH 16/84] Added Will Thames to list of authors --- AUTHORS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 0e169a1f..caef1ae2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -12,4 +12,5 @@ Patches and Suggestions - Jeff Forcier - Morgan Goose -- Travis Swicegood \ No newline at end of file +- Travis Swicegood +- Will Thames From c226b6b736830f96ffd663391a72fc7d9b1822cc Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Thu, 31 Mar 2011 14:52:44 -0400 Subject: [PATCH 17/84] progress bar examples --- examples/progressbar.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/progressbar.py b/examples/progressbar.py index 30cf4045..7643d524 100755 --- a/examples/progressbar.py +++ b/examples/progressbar.py @@ -8,12 +8,13 @@ from time import sleep from random import random -from clint.textui import progressbar +from clint.textui import progress if __name__ == '__main__': - for i in progressbar(range(100)): + for i in progress.bar(range(100)): sleep(random() * 0.2) - + for i in progress.dots(range(100)): + sleep(random() * 0.2) \ No newline at end of file From cc072a18f3f28b3420054d6430b0beb1fe51746d Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Fri, 1 Apr 2011 07:58:48 -0600 Subject: [PATCH 18/84] Add tox support --- .gitignore | 4 +++- tox.ini | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index 1ff8381a..b49e53e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .idea -MANIFEST \ No newline at end of file +MANIFEST +*.pyc +.tox diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..9fc727c5 --- /dev/null +++ b/tox.ini @@ -0,0 +1,5 @@ +[tox] +envlist = py26, py27 #, py25, py31, py32 + +[testenv] +commands = {envpython} test_clint.py From 6f106e2f1238797c5e474f45435888587528fbaf Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Fri, 1 Apr 2011 10:05:55 -0400 Subject: [PATCH 19/84] toxic --- tox.ini | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 9fc727c5..82becb54 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,12 @@ [tox] -envlist = py26, py27 #, py25, py31, py32 +envlist = py25,py26,py27,py3 [testenv] -commands = {envpython} test_clint.py +commands=py.test --junitxml=junit-{envname}.xml +deps = pytest + +[testenv:pypy] +basepython=/usr/bin/pypy-c + +[testenv:py3] +basepython=/usr/bin/python3 \ No newline at end of file From 81165754a440aa0ab1b92d7a43f698fec2fe8b33 Mon Sep 17 00:00:00 2001 From: "star:Kenneth Reitz" Date: Sun, 3 Apr 2011 08:11:17 -0400 Subject: [PATCH 20/84] allow clint.textui.puts() to accept arbitrary file-like objects (like StringIO for
 generation)

---
 clint/textui/core.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clint/textui/core.py b/clint/textui/core.py
index 3418cc18..90978c67 100644
--- a/clint/textui/core.py
+++ b/clint/textui/core.py
@@ -78,9 +78,9 @@ def __call__(self, s, newline=True, stream=STDOUT):
         stream(_str)
 
 
-def puts(s, newline=True):
+def puts(s, newline=True, stream=STDOUT):
     """Prints given string to stdout via Writer interface."""
-    Writer()(s, newline, stream=STDOUT)
+    Writer()(s, newline, stream=stream)
 
 
 def puts_err(s, newline=True):

From 3d63ed01f92743d41c77da26d8d148a5fcfced7d Mon Sep 17 00:00:00 2001
From: "star:Kenneth Reitz" 
Date: Sun, 3 Apr 2011 08:11:23 -0400
Subject: [PATCH 21/84] whitespace cleanup

---
 clint/resources.py   | 16 ++++++++--------
 clint/textui/core.py |  6 +++---
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/clint/resources.py b/clint/resources.py
index 27ad10a2..b4827502 100644
--- a/clint/resources.py
+++ b/clint/resources.py
@@ -39,7 +39,7 @@ def __init__(self, path=None):
 
     def __repr__(self):
         return '' % (self.path)
-    
+
 
     def __getattribute__(self, name):
 
@@ -53,11 +53,11 @@ def _raise_if_none(self):
         """Raises if operations are carried out on an unconfigured AppDir."""
         if not self.path:
             raise NotConfigured()
-        
+
 
     def _create(self):
         """Creates current AppDir at AppDir.path."""
-        
+
         self._raise_if_none()
         if not self._exists:
             mkdir_p(self.path)
@@ -66,7 +66,7 @@ def _create(self):
 
     def open(self, filename, mode='r'):
         """Returns file object from given filename."""
-        
+
         self._raise_if_none()
         fn = path_join(self.path, filename)
 
@@ -121,11 +121,11 @@ def delete(self, filename=''):
             else:
                 raise why
 
-        
+
     def read(self, filename, binary=False):
         """Returns contents of given file with AppDir.
         If file doesn't exist, returns None."""
-        
+
         self._raise_if_none()
         fn = path_join(self.path, filename)
 
@@ -161,11 +161,11 @@ def sub(self, path):
 def init(vendor, name):
 
     global user, site, cache, log
-    
+
     ad = AppDirs(name, vendor)
 
     user.path = ad.user_data_dir
-    
+
     site.path = ad.site_data_dir
     cache.path = ad.user_cache_dir
     log.path = ad.user_log_dir
diff --git a/clint/textui/core.py b/clint/textui/core.py
index 90978c67..8ef3e310 100644
--- a/clint/textui/core.py
+++ b/clint/textui/core.py
@@ -62,14 +62,14 @@ def __exit__(self, type, value, traceback):
 
 
     def __call__(self, s, newline=True, stream=STDOUT):
-        
+
         if newline:
             s = tsplit(s, NEWLINES)
             s = map(str, s)
             indent = ''.join(self.shared['indent_strings'])
-            
+
             s = (str('\n' + indent)).join(s)
-        
+
         _str = ''.join((
             ''.join(self.shared['indent_strings']),
             str(s),

From b58f8dccdc0cb24dcce2cad4fb2f2fc9b4552394 Mon Sep 17 00:00:00 2001
From: "star:Kenneth Reitz" 
Date: Wed, 6 Apr 2011 10:08:25 -0400
Subject: [PATCH 22/84] no colorama auto-init upon import

---
 clint/textui/colored.py | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index d4721030..1091f0d6 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -25,9 +25,7 @@
 COLORS = __all__[:-2]
 DISABLE_COLOR = False
 
-if sys.stdout.isatty():
-    colorama.init(autoreset=True)
-else:
+if not sys.stdout.isatty():
     DISABLE_COLOR = True
 
 
@@ -41,6 +39,7 @@ def __init__(self, color, s):
     @property
     def color_str(self):
         if sys.stdout.isatty() and not DISABLE_COLOR:
+            colorama.init(autoreset=True)
             return '%s%s%s' % (
                 getattr(colorama.Fore, self.color), self.s, colorama.Fore.RESET)
         else:
@@ -49,25 +48,25 @@ def color_str(self):
 
     def __len__(self):
         return len(self.s)
-        
+
     def __repr__(self):
         return "<%s-string: '%s'>" % (self.color, self.s)
-        
+
     def __str__(self):
         return self.__unicode__().encode('utf8')
-        
+
     def __unicode__(self):
         return self.color_str
-        
+
     def __add__(self, other):
         return str(self.color_str) + str(other)
-        
+
     def __radd__(self, other):
         return str(other) + str(self.color_str)
-        
+
     def __mul__(self, other):
         return (self.color_str * other)
-        
+
     def split(self, x=' '):
         return map(self._new, self.s.split(x))
 

From e85fffdbb6ac7622c36bec7b3a1e879193991220 Mon Sep 17 00:00:00 2001
From: "star:Kenneth Reitz" 
Date: Wed, 6 Apr 2011 13:00:13 -0400
Subject: [PATCH 23/84] puts/puts_err fixes, defaults for string

---
 clint/textui/core.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clint/textui/core.py b/clint/textui/core.py
index 8ef3e310..af9cab2f 100644
--- a/clint/textui/core.py
+++ b/clint/textui/core.py
@@ -78,14 +78,14 @@ def __call__(self, s, newline=True, stream=STDOUT):
         stream(_str)
 
 
-def puts(s, newline=True, stream=STDOUT):
+def puts(s='', newline=True, stream=STDOUT):
     """Prints given string to stdout via Writer interface."""
     Writer()(s, newline, stream=stream)
 
 
-def puts_err(s, newline=True):
+def puts_err(s='', newline=True, stream=STDERR):
     """Prints given string to stderr via Writer interface."""
-    Writer()(s, stream=STDERR)
+    Writer()(s, newline, stream=stream)
 
 
 def indent(indent=4, quote=''):

From 4b9e35c631ca26d3c114a6b9251dc5aacc1506ff Mon Sep 17 00:00:00 2001
From: "star:Kenneth Reitz" 
Date: Wed, 6 Apr 2011 13:02:40 -0400
Subject: [PATCH 24/84] configurable progress interator streams

---
 clint/textui/progress.py | 55 +++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 23 deletions(-)

diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index 11bf1741..960c35b9 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -10,10 +10,10 @@
 
 from __future__ import absolute_import
 
-from .core import puts
-
 import sys
 
+STREAM = sys.stderr
+
 BAR_TEMPLATE = '%s[%s%s] %i/%i\r'
 BAR_EMPTY_CHAR = '-'
 BAR_FILLED_CHAR = '='
@@ -23,37 +23,46 @@
 
 def bar(it, label='', width=32, hide=False):
     """Progress iterator. Wrap your iterables with it."""
+
+    def _show(_i):
+        x = int(width*_i/count)
+        if not hide:
+            STREAM.write(BAR_TEMPLATE % (
+                label, BAR_FILLED_CHAR*x, BAR_EMPTY_CHAR*(width-x), _i, count))
+            STREAM.flush()
+
     count = len(it)
-    if count:
-        def _show(_i):
-            x = int(width*_i/count)
-            if not hide:
-                puts(BAR_TEMPLATE % (
-                    label, BAR_FILLED_CHAR*x, BAR_EMPTY_CHAR*(width-x), _i, count), newline=False)
-                sys.stdout.flush()
 
+    if count:
         _show(0)
+
     for i, item in enumerate(it):
+
         yield item
         _show(i+1)
+
     if not hide:
-        sys.stdout.write("\n")
-        sys.stdout.flush()
+        STREAM.write('\n')
+        STREAM.flush()
 
 
 def dots(it, label='', hide=False):
     """Progress iterator. Prints a dot for each item being iterated"""
-    count = len(it)
-    
-    puts(label, newline=False)
-    if count:
-        def _show(_i):
-            # sys.stdout.write('.')
-            puts(DOTS_CHAR, newline=False)
 
-        _show(0)
-    for i, item in enumerate(it):
-        yield item
-        _show(i+1)
+    count = 0
+
     if not hide:
-        sys.stdout.write("\n")
+        STREAM.write(label)
+
+    for item in it:
+        if not hide:
+            STREAM.write(DOTS_CHAR)
+            sys.stderr.flush()
+
+        count += 1
+
+        yield item
+
+    STREAM.write('\n')
+    STREAM.flush()
+

From e500773da3a84a683a92ee6abe70008f9667ce96 Mon Sep 17 00:00:00 2001
From: "star:Kenneth Reitz" 
Date: Wed, 6 Apr 2011 13:06:14 -0400
Subject: [PATCH 25/84] version bump (v0.2.3)

---
 HISTORY.rst       | 16 ++++++++++++----
 clint/__init__.py |  4 ++--
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/HISTORY.rst b/HISTORY.rst
index 2e1cb547..19486bd5 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -1,13 +1,21 @@
 History
 -------
 
+0.2.3
++++++
+
+* Only init colors if they are used (iPython compatability)
+* New progress module
+* Various bugfixes
+
+
 0.2.2
 +++++
 
-Auto Color Disabling 
-Progress Namespace Change
-New Progress Bars
-textui.puts newline fix
+* Auto Color Disabling
+* Progress Namespace Change
+* New Progress Bars
+* textui.puts newline fix
 
 
 0.2.1 (2011-03-24)
diff --git a/clint/__init__.py b/clint/__init__.py
index 29ec2d21..aeda450a 100644
--- a/clint/__init__.py
+++ b/clint/__init__.py
@@ -19,8 +19,8 @@
 
 
 __title__ = 'clint'
-__version__ = '0.2.1'
-__build__ = 0x000201
+__version__ = '0.2.3'
+__build__ = 0x000203
 __author__ = 'Kenneth Reitz'
 __license__ = 'ISC'
 __copyright__ = 'Copyright 2011 Kenneth Reitz'

From 003411ebcd23b9707bb9f2fe24a4356add4e8060 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Mon, 18 Apr 2011 12:18:31 -0400
Subject: [PATCH 26/84] eng.plural!

---
 clint/eng.py | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 clint/eng.py

diff --git a/clint/eng.py b/clint/eng.py
new file mode 100644
index 00000000..1a4bff22
--- /dev/null
+++ b/clint/eng.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+"""
+clint.eng
+~~~~~~~~~
+
+This module provides English language string helpers.
+
+"""
+
+MORON_MODE = False
+COMMA = ','
+CONJUNCTION = 'and'
+SPACE = ' '
+
+
+def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, seperator=COMMA):
+    """Joins lists of words. Oxford comma and all."""
+
+    collector = []
+    left = len(l)
+    seperator = seperator + SPACE
+    conj = conj + SPACE
+
+    for _l in l[:]:
+
+        left += -1
+
+        collector.append(_l)
+        if left > 1:
+            collector.append(seperator)
+        elif left == 1:
+            if len(l) == 2 or im_a_moron:
+                print
+                collector.append(SPACE)
+            else:
+                collector.append(seperator)
+
+            collector.append(conj)
+        elif left == 0:
+            pass
+
+    return unicode(''.join(collector))

From 25b8d6a10ec612f573905d60bfe5536d14c18e97 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Mon, 18 Apr 2011 12:25:06 -0400
Subject: [PATCH 27/84] oops

---
 clint/eng.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clint/eng.py b/clint/eng.py
index 1a4bff22..c4cdac2b 100644
--- a/clint/eng.py
+++ b/clint/eng.py
@@ -31,7 +31,6 @@ def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, seperator=COMMA):
             collector.append(seperator)
         elif left == 1:
             if len(l) == 2 or im_a_moron:
-                print
                 collector.append(SPACE)
             else:
                 collector.append(seperator)

From 5d7485c1449bd54b535af3fb064c31f16d62fcba Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Mon, 18 Apr 2011 12:38:56 -0400
Subject: [PATCH 28/84] cleaner eng.join

---
 clint/eng.py | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/clint/eng.py b/clint/eng.py
index c4cdac2b..c8e5774f 100644
--- a/clint/eng.py
+++ b/clint/eng.py
@@ -27,16 +27,23 @@ def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, seperator=COMMA):
         left += -1
 
         collector.append(_l)
-        if left > 1:
-            collector.append(seperator)
-        elif left == 1:
+        if left == 1:
             if len(l) == 2 or im_a_moron:
                 collector.append(SPACE)
             else:
                 collector.append(seperator)
 
             collector.append(conj)
-        elif left == 0:
-            pass
 
-    return unicode(''.join(collector))
+        elif left is not 0:
+            collector.append(seperator)
+
+    return unicode(str().join(collector))
+
+if __name__ == '__main__':
+    print join(['blue', 'red', 'yellow'], conj='or', im_a_moron=True)
+    print join(['blue', 'red', 'yellow'], conj='or')
+    print join(['blue', 'red'], conj='or')
+    print join(['blue', 'red'], conj='and')
+    print join(['blue'], conj='and')
+    print join(['blue', 'red', 'yellow', 'green', 'ello'], conj='and')
\ No newline at end of file

From 872c78a5b90e915345f62f20cc44a71e072aee10 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Mon, 18 Apr 2011 12:39:20 -0400
Subject: [PATCH 29/84] no need to init colorama

---
 clint/textui/colored.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index 1091f0d6..291b19ad 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -39,7 +39,6 @@ def __init__(self, color, s):
     @property
     def color_str(self):
         if sys.stdout.isatty() and not DISABLE_COLOR:
-            colorama.init(autoreset=True)
             return '%s%s%s' % (
                 getattr(colorama.Fore, self.color), self.s, colorama.Fore.RESET)
         else:

From 0855525fca15296d8f901f7b9efe0d4f3cb494a4 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Mon, 18 Apr 2011 12:49:37 -0400
Subject: [PATCH 30/84] added eng.join example

---
 examples/eng_join.py | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 examples/eng_join.py

diff --git a/examples/eng_join.py b/examples/eng_join.py
new file mode 100644
index 00000000..c2736b17
--- /dev/null
+++ b/examples/eng_join.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+import os
+
+sys.path.insert(0, os.path.abspath('..'))
+
+from clint.eng import join
+from clint.textui import colored, indent, puts
+
+colors = [
+    colored.blue('blue'),
+    colored.red('red'),
+    colored.yellow('yellow'),
+    colored.green('green'),
+    colored.magenta('magenta')
+]
+
+colors = map(str, colors)
+
+
+puts('Smart:')
+with indent(4):
+    for i in range(len(colors)):
+        puts(join(colors[:i+1]))
+puts('\n')
+puts('Stupid:')
+with indent(4):
+    for i in range(len(colors)):
+        puts(join(colors[:i+1], im_a_moron=True, conj='\'n'))

From a07602fdeb55d8aa3825df834c5b0afee46be9b2 Mon Sep 17 00:00:00 2001
From: Greg Haskins 
Date: Wed, 15 Jun 2011 12:24:52 -0400
Subject: [PATCH 31/84] call colorama.init(..) at import time to ensure
 stdout/stderr get wrapped

---
 clint/textui/colored.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index 291b19ad..e7c0754f 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -27,6 +27,8 @@
 
 if not sys.stdout.isatty():
     DISABLE_COLOR = True
+else:
+    colorama.init(autoreset=True)
 
 
 class ColoredString(object):

From 1a9e15dbba7b9e15ecc44f9067598d50522e4ddc Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Wed, 15 Jun 2011 12:39:34 -0400
Subject: [PATCH 32/84] added Greg Haskins to AUTHORS

---
 AUTHORS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/AUTHORS b/AUTHORS
index caef1ae2..54abbb6f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -14,3 +14,4 @@ Patches and Suggestions
 - Morgan Goose
 - Travis Swicegood
 - Will Thames
+- Greg Haskins
\ No newline at end of file

From 23689f8b0afb5d62de7fcb3cc340d0e0713ce5c5 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Wed, 15 Jun 2011 12:40:14 -0400
Subject: [PATCH 33/84] updated history

---
 HISTORY.rst | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/HISTORY.rst b/HISTORY.rst
index 19486bd5..1787da7a 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -1,6 +1,13 @@
 History
 -------
 
+?
++
+
+* Win32 Bugfix
+
+
+
 0.2.3
 +++++
 

From 96827698df3369ef5eab88278faff8cc302deead Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Tue, 21 Jun 2011 18:44:46 -0400
Subject: [PATCH 34/84] Update colorama to v0.2.3

---
 clint/packages/colorama/__init__.py    |  4 +-
 clint/packages/colorama/ansitowin32.py | 10 ++++-
 clint/packages/colorama/initialise.py  | 23 ++++++++--
 clint/packages/colorama/win32.py       | 60 +++++++++++++++++++-------
 clint/packages/colorama/winterm.py     | 37 +++++++++++++++-
 5 files changed, 109 insertions(+), 25 deletions(-)

diff --git a/clint/packages/colorama/__init__.py b/clint/packages/colorama/__init__.py
index 331174e5..147a3e03 100644
--- a/clint/packages/colorama/__init__.py
+++ b/clint/packages/colorama/__init__.py
@@ -1,6 +1,6 @@
-from .initialise import init
+from .initialise import init, deinit, reinit
 from .ansi import Fore, Back, Style
 from .ansitowin32 import AnsiToWin32
 
-VERSION = '0.1.18'
+VERSION = '0.2.3'
 
diff --git a/clint/packages/colorama/ansitowin32.py b/clint/packages/colorama/ansitowin32.py
index 363061d3..489a9175 100644
--- a/clint/packages/colorama/ansitowin32.py
+++ b/clint/packages/colorama/ansitowin32.py
@@ -118,12 +118,12 @@ def write(self, text):
             self.wrapped.flush()
         if self.autoreset:
             self.reset_all()
-        
+
 
     def reset_all(self):
         if self.convert:
             self.call_win32('m', (0,))
-        else:
+        elif is_a_tty(self.wrapped):
             self.wrapped.write(Style.RESET_ALL)
 
 
@@ -173,4 +173,10 @@ def call_win32(self, command, params):
                     args = func_args[1:]
                     kwargs = dict(on_stderr=self.on_stderr)
                     func(*args, **kwargs)
+        elif command in ('H', 'f'): # set cursor position
+            func = winterm.set_cursor_position
+            func(params, on_stderr=self.on_stderr)
+        elif command in ('J'):
+            func = winterm.erase_data
+            func(params, on_stderr=self.on_stderr)
 
diff --git a/clint/packages/colorama/initialise.py b/clint/packages/colorama/initialise.py
index 4df5c3e3..51aaa34b 100644
--- a/clint/packages/colorama/initialise.py
+++ b/clint/packages/colorama/initialise.py
@@ -7,6 +7,9 @@
 orig_stdout = sys.stdout
 orig_stderr = sys.stderr
 
+wrapped_stdout = sys.stdout
+wrapped_stderr = sys.stderr
+
 atexit_done = False
 
 
@@ -16,11 +19,14 @@ def reset_all():
 
 def init(autoreset=False, convert=None, strip=None, wrap=True):
 
-    if wrap==False and (autoreset==True or convert==True or strip==True):
+    if not wrap and any([autoreset, convert, strip]):
         raise ValueError('wrap=False conflicts with any other arg=True')
 
-    sys.stdout = wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
-    sys.stderr = wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
+    global wrapped_stdout, wrapped_stderr
+    sys.stdout = wrapped_stdout = \
+        wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
+    sys.stderr = wrapped_stderr = \
+        wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
 
     global atexit_done
     if not atexit_done:
@@ -28,6 +34,16 @@ def init(autoreset=False, convert=None, strip=None, wrap=True):
         atexit_done = True
 
 
+def deinit():
+    sys.stdout = orig_stdout
+    sys.stderr = orig_stderr
+
+
+def reinit():
+    sys.stdout = wrapped_stdout
+    sys.stderr = wrapped_stdout
+
+
 def wrap_stream(stream, convert, strip, autoreset, wrap):
     if wrap:
         wrapper = AnsiToWin32(stream,
@@ -36,3 +52,4 @@ def wrap_stream(stream, convert, strip, autoreset, wrap):
             stream = wrapper.stream
     return stream
 
+
diff --git a/clint/packages/colorama/win32.py b/clint/packages/colorama/win32.py
index 2a6fc949..ed4d613e 100644
--- a/clint/packages/colorama/win32.py
+++ b/clint/packages/colorama/win32.py
@@ -48,8 +48,16 @@ class CONSOLE_SCREEN_BUFFER_INFO(Structure):
             ("srWindow", SMALL_RECT),
             ("dwMaximumWindowSize", COORD),
         ]
+        def __str__(self):
+            return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
+                self.dwSize.Y, self.dwSize.X
+                , self.dwCursorPosition.Y, self.dwCursorPosition.X
+                , self.wAttributes
+                , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right
+                , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X
+            )
 
-    def GetConsoleScreenBufferInfo(stream_id):
+    def GetConsoleScreenBufferInfo(stream_id=STDOUT):
         handle = handles[stream_id]
         csbi = CONSOLE_SCREEN_BUFFER_INFO()
         success = windll.kernel32.GetConsoleScreenBufferInfo(
@@ -62,34 +70,54 @@ def GetConsoleScreenBufferInfo(stream_id):
 
     def SetConsoleTextAttribute(stream_id, attrs):
         handle = handles[stream_id]
-        success = windll.kernel32.SetConsoleTextAttribute(handle, attrs)
-        assert success
+        return windll.kernel32.SetConsoleTextAttribute(handle, attrs)
 
     def SetConsoleCursorPosition(stream_id, position):
-        handle = handles[stream_id]
         position = COORD(*position)
-        success = windll.kernel32.SetConsoleCursorPosition(handle, position)
-        assert success
+        # If the position is out of range, do nothing.
+        if position.Y <= 0 or position.X <= 0: 
+            return
+        # Adjust for Windows' SetConsoleCursorPosition:
+        #    1. being 0-based, while ANSI is 1-based.
+        #    2. expecting (x,y), while ANSI uses (y,x).
+        adjusted_position = COORD(position.Y - 1, position.X - 1)
+        # Adjust for viewport's scroll position
+        sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
+        adjusted_position.Y += sr.Top
+        adjusted_position.X += sr.Left
+        # Resume normal processing
+        handle = handles[stream_id]
+        success = windll.kernel32.SetConsoleCursorPosition(handle, adjusted_position)
+        return success
 
     def FillConsoleOutputCharacter(stream_id, char, length, start):
         handle = handles[stream_id]
         char = TCHAR(char)
         length = DWORD(length)
-        start = COORD(*start)
         num_written = DWORD(0)
-        # AttributeError: function 'FillConsoleOutputCharacter' not found
-        # could it just be that my types are wrong?
-        success = windll.kernel32.FillConsoleOutputCharacter(
+        # Note that this is hard-coded for ANSI (vs wide) bytes.
+        success = windll.kernel32.FillConsoleOutputCharacterA(
             handle, char, length, start, byref(num_written))
-        assert success
         return num_written.value
 
+    def FillConsoleOutputAttribute(stream_id, attr, length, start):
+        ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )'''
+        handle = handles[stream_id]
+        attribute = WORD(attr)
+        length = DWORD(length)
+        num_written = DWORD(0)
+        # Note that this is hard-coded for ANSI (vs wide) bytes.
+        success = windll.kernel32.FillConsoleOutputAttribute(
+            handle, attribute, length, start, byref(num_written))
+        return success
+
 
 if __name__=='__main__':
     x = GetConsoleScreenBufferInfo(STDOUT)
-    print(x.dwSize)
-    print(x.dwCursorPosition)
-    print(x.wAttributes)
-    print(x.srWindow)
-    print(x.dwMaximumWindowSize)
+    print(x)
+    print('dwSize(height,width)                    = (%d,%d)' % (x.dwSize.Y, x.dwSize.X))
+    print('dwCursorPosition(y,x)                   = (%d,%d)' % (x.dwCursorPosition.Y, x.dwCursorPosition.X))
+    print('wAttributes(color)                      =  %d = 0x%02x' % (x.wAttributes, x.wAttributes))
+    print('srWindow(Top,Left)-(Bottom,Right)       = (%d,%d)-(%d,%d)' % (x.srWindow.Top, x.srWindow.Left, x.srWindow.Bottom, x.srWindow.Right))
+    print('dwMaximumWindowSize(maxHeight,maxWidth) = (%d,%d)' % (x.dwMaximumWindowSize.Y, x.dwMaximumWindowSize.X))
 
diff --git a/clint/packages/colorama/winterm.py b/clint/packages/colorama/winterm.py
index 4326c21b..95585f3f 100644
--- a/clint/packages/colorama/winterm.py
+++ b/clint/packages/colorama/winterm.py
@@ -22,8 +22,7 @@ class WinStyle(object):
 class WinTerm(object):
 
     def __init__(self):
-        self._default = \
-            win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
+        self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
         self.set_attrs(self._default)
         self._default_fore = self._fore
         self._default_back = self._back
@@ -67,3 +66,37 @@ def set_console(self, attrs=None, on_stderr=False):
             handle = win32.STDERR
         win32.SetConsoleTextAttribute(handle, attrs)
 
+    def set_cursor_position(self, position=None, on_stderr=False):
+        if position is None:
+            #I'm not currently tracking the position, so there is no default.
+            #position = self.get_position()
+            return
+        handle = win32.STDOUT
+        if on_stderr:
+            handle = win32.STDERR
+        win32.SetConsoleCursorPosition(handle, position)
+
+    def erase_data(self, mode=0, on_stderr=False):
+        # 0 (or None) should clear from the cursor to the end of the screen.
+        # 1 should clear from the cursor to the beginning of the screen.
+        # 2 should clear the entire screen. (And maybe move cursor to (1,1)?)
+        #
+        # At the moment, I only support mode 2. From looking at the API, it 
+        #    should be possible to calculate a different number of bytes to clear, 
+        #    and to do so relative to the cursor position.
+        if mode[0] not in (2,):
+            return
+        handle = win32.STDOUT
+        if on_stderr:
+            handle = win32.STDERR
+        # here's where we'll home the cursor
+        coord_screen = win32.COORD(0,0) 
+        csbi = win32.GetConsoleScreenBufferInfo(handle)
+        # get the number of character cells in the current buffer
+        dw_con_size = csbi.dwSize.X * csbi.dwSize.Y
+        # fill the entire screen with blanks
+        win32.FillConsoleOutputCharacter(handle, ord(' '), dw_con_size, coord_screen)
+        # now set the buffer's attributes accordingly
+        win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen );
+        # put the cursor at (0, 0)
+        win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y))

From 7900853dbcc3442be8c0b1e27851989a4ecfe1a3 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Sat, 25 Jun 2011 12:27:44 -0400
Subject: [PATCH 35/84] v0.2.4

---
 HISTORY.rst       | 6 +++---
 clint/__init__.py | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/HISTORY.rst b/HISTORY.rst
index 1787da7a..5ece8fcc 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -1,13 +1,13 @@
 History
 -------
 
-?
-+
+0.2.4
++++++
 
+* New eng module
 * Win32 Bugfix
 
 
-
 0.2.3
 +++++
 
diff --git a/clint/__init__.py b/clint/__init__.py
index aeda450a..4ec78cdb 100644
--- a/clint/__init__.py
+++ b/clint/__init__.py
@@ -19,8 +19,8 @@
 
 
 __title__ = 'clint'
-__version__ = '0.2.3'
-__build__ = 0x000203
+__version__ = '0.2.4'
+__build__ = 0x000204
 __author__ = 'Kenneth Reitz'
 __license__ = 'ISC'
 __copyright__ = 'Copyright 2011 Kenneth Reitz'

From 705cda44434a69df9764fe7f85e1ebd869569e5c Mon Sep 17 00:00:00 2001
From: Miguel Araujo Perez 
Date: Thu, 11 Aug 2011 16:19:48 +0200
Subject: [PATCH 36/84] Adding kwargs to progress bar, so that `bar_empty_char`
 and `bar_filled_char` can be easily customized.

---
 AUTHORS                  | 3 ++-
 clint/textui/progress.py | 6 ++----
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 54abbb6f..f172f244 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -14,4 +14,5 @@ Patches and Suggestions
 - Morgan Goose
 - Travis Swicegood
 - Will Thames
-- Greg Haskins
\ No newline at end of file
+- Greg Haskins
+- Miguel Araujo 
diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index 960c35b9..40f813f0 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -15,20 +15,18 @@
 STREAM = sys.stderr
 
 BAR_TEMPLATE = '%s[%s%s] %i/%i\r'
-BAR_EMPTY_CHAR = '-'
-BAR_FILLED_CHAR = '='
 
 DOTS_CHAR = '.'
 
 
-def bar(it, label='', width=32, hide=False):
+def bar(it, label='', width=32, hide=False, bar_empty_char='-', bar_filled_char='='):
     """Progress iterator. Wrap your iterables with it."""
 
     def _show(_i):
         x = int(width*_i/count)
         if not hide:
             STREAM.write(BAR_TEMPLATE % (
-                label, BAR_FILLED_CHAR*x, BAR_EMPTY_CHAR*(width-x), _i, count))
+                label, bar_filled_char*x, bar_empty_char*(width-x), _i, count))
             STREAM.flush()
 
     count = len(it)

From 3be47add4a2bcafe35900779bf7d7c509aed8fe9 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Fri, 12 Aug 2011 09:48:24 -0400
Subject: [PATCH 37/84] rename arguments for bar

---
 clint/textui/progress.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index 40f813f0..4ca2b0f7 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -19,7 +19,7 @@
 DOTS_CHAR = '.'
 
 
-def bar(it, label='', width=32, hide=False, bar_empty_char='-', bar_filled_char='='):
+def bar(it, label='', width=32, hide=False, empty_char='-', filled_char='='):
     """Progress iterator. Wrap your iterables with it."""
 
     def _show(_i):

From 98edec43e9cc77ff13c7f66987c176264656d56d Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Sat, 24 Sep 2011 14:32:47 -0400
Subject: [PATCH 38/84] move expand_path to utils

---
 clint/arguments.py | 56 +++++++++++++++-------------------------------
 1 file changed, 18 insertions(+), 38 deletions(-)

diff --git a/clint/arguments.py b/clint/arguments.py
index 579a2e0a..4b823b67 100644
--- a/clint/arguments.py
+++ b/clint/arguments.py
@@ -13,33 +13,13 @@
 
 import os
 from sys import argv
-from glob import glob
 
 from .packages.ordereddict import OrderedDict
-from .utils import is_collection
-
-
+from .utils import expand_path, is_collection
 
 __all__ = ('Args', )
 
 
-
-def _expand_path(path):
-    """Expands directories and globs in given path."""
-
-    paths = []
-
-    if os.path.isdir(path):
-
-        for (dir, dirs, files) in os.walk(path):
-            for file in files:
-                paths.append(os.path.join(dir, file))
-    else:
-        paths.extend(glob(path))
-
-    return paths
-
-
 class Args(object):
     """CLI Argument management."""
 
@@ -110,20 +90,20 @@ def pop(self, x):
 
     def any_contain(self, x):
         """Tests if given string is contained in any stored argument."""
-        
+
         return bool(self.first_with(x))
 
 
     def contains(self, x):
-        """Tests if given object is in arguments list. 
+        """Tests if given object is in arguments list.
            Accepts strings and lists of strings."""
-        
+
         return self.__contains__(x)
 
 
     def first(self, x):
         """Returns first found index of given value (or list of values)"""
-        
+
         def _find( x):
             try:
                 return self.all.index(str(x))
@@ -212,7 +192,7 @@ def contains_at(self, x, index):
                         return False
             else:
                 return (x in self.all[index])
-        
+
         except IndexError:
             return False
 
@@ -221,7 +201,7 @@ def has(self, x):
         """Returns true if argument exists at given index.
            Accepts: integer.
         """
-        
+
         try:
             self.all[x]
             return True
@@ -231,15 +211,15 @@ def has(self, x):
 
     def value_after(self, x):
         """Returns value of argument after given found argument (or list thereof)."""
-        
+
         try:
             try:
                 i = self.all.index(x)
             except ValueError:
                 return None
-                
+
             return self.all[i + 1]
-            
+
         except IndexError:
             return None
 
@@ -266,21 +246,21 @@ def grouped(self):
 
         return collection
 
-    
+
     @property
     def last(self):
         """Returns last argument."""
-        
+
         try:
             return self.all[-1]
         except IndexError:
             return None
 
-    
+
     @property
     def all(self):
         """Returns all arguments."""
-        
+
         return self._args
 
 
@@ -288,7 +268,7 @@ def all_with(self, x):
         """Returns all arguments containing given string (or list thereof)"""
 
         _args = []
-        
+
         for arg in self.all:
             if is_collection(x):
                 for _x in x:
@@ -327,7 +307,7 @@ def flags(self):
         return self.start_with('-')
 
 
-    @property    
+    @property
     def not_flags(self):
         """Returns Arg object excluding flagged arguments."""
 
@@ -341,7 +321,7 @@ def files(self, absolute=False):
         _paths = []
 
         for arg in self.all:
-            for path in _expand_path(arg):
+            for path in expand_path(arg):
                 if os.path.exists(path):
                     if absolute:
                         _paths.append(os.path.abspath(path))
@@ -358,7 +338,7 @@ def not_files(self):
         _args = []
 
         for arg in self.all:
-            if not len(_expand_path(arg)):
+            if not len(expand_path(arg)):
                 if not os.path.exists(arg):
                     _args.append(arg)
 

From d19650b93cc8c2d0043d41ca341a60b09d87daa8 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Sat, 24 Sep 2011 14:33:13 -0400
Subject: [PATCH 39/84] add userpath and environ var expansion to expand_path

---
 clint/utils.py | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/clint/utils.py b/clint/utils.py
index 3f499d0b..b215c337 100644
--- a/clint/utils.py
+++ b/clint/utils.py
@@ -11,9 +11,29 @@
 from __future__ import absolute_import
 from __future__ import with_statement
 
-import sys
 import errno
+import os.path
 from os import makedirs
+from glob import glob
+
+
+def expand_path(path):
+    """Expands directories and globs in given path."""
+
+    paths = []
+    path = os.path.expanduser(path)
+    path = os.path.expandvars(path)
+
+    if os.path.isdir(path):
+
+        for (dir, dirs, files) in os.walk(path):
+            for file in files:
+                paths.append(os.path.join(dir, file))
+    else:
+        paths.extend(glob(path))
+
+    return paths
+
 
 
 def is_collection(obj):
@@ -37,17 +57,17 @@ def mkdir_p(path):
 
 def tsplit(string, delimiters):
     """Behaves str.split but supports tuples of delimiters."""
-    
+
     delimiters = tuple(delimiters)
     stack = [string,]
-    
+
     for delimiter in delimiters:
         for i, substring in enumerate(stack):
             substack = substring.split(delimiter)
             stack.pop(i)
             for j, _substring in enumerate(substack):
                 stack.insert(i+j, _substring)
-            
+
     return stack
 
 def schunk(string, size):

From 7b6138eda60cad87423e131bce1566ea5a12eb58 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Sat, 24 Sep 2011 14:36:30 -0400
Subject: [PATCH 40/84] v0.2.5

---
 clint/__init__.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clint/__init__.py b/clint/__init__.py
index 4ec78cdb..793226bb 100644
--- a/clint/__init__.py
+++ b/clint/__init__.py
@@ -19,8 +19,8 @@
 
 
 __title__ = 'clint'
-__version__ = '0.2.4'
-__build__ = 0x000204
+__version__ = '0.2.5'
+__build__ = 0x000205
 __author__ = 'Kenneth Reitz'
 __license__ = 'ISC'
 __copyright__ = 'Copyright 2011 Kenneth Reitz'

From 84419f6bfbd2ae1e36f9d533856d05912b360ce4 Mon Sep 17 00:00:00 2001
From: robbles 
Date: Wed, 28 Sep 2011 11:13:26 -0700
Subject: [PATCH 41/84] fix mismatch with argument names for progress.bar

---
 clint/textui/progress.py | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index 4ca2b0f7..3a94d1bb 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -17,16 +17,17 @@
 BAR_TEMPLATE = '%s[%s%s] %i/%i\r'
 
 DOTS_CHAR = '.'
+BAR_FILLED_CHAR = '#'
+BAR_EMPTY_CHAR = ' '
 
-
-def bar(it, label='', width=32, hide=False, empty_char='-', filled_char='='):
+def bar(it, label='', width=32, hide=False, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR):
     """Progress iterator. Wrap your iterables with it."""
 
     def _show(_i):
         x = int(width*_i/count)
         if not hide:
             STREAM.write(BAR_TEMPLATE % (
-                label, bar_filled_char*x, bar_empty_char*(width-x), _i, count))
+                label, filled_char*x, empty_char*(width-x), _i, count))
             STREAM.flush()
 
     count = len(it)

From 8e6973253f45dc4bbf5aa489531cc70f9e0c209c Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Fri, 28 Oct 2011 13:04:31 -0300
Subject: [PATCH 42/84] Update clint/textui/progress.py

---
 clint/textui/progress.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index 4ca2b0f7..c958e2b5 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -26,7 +26,7 @@ def _show(_i):
         x = int(width*_i/count)
         if not hide:
             STREAM.write(BAR_TEMPLATE % (
-                label, bar_filled_char*x, bar_empty_char*(width-x), _i, count))
+                label, filled_char*x, empty_char*(width-x), _i, count))
             STREAM.flush()
 
     count = len(it)

From 1ea4c5afdc3eb9a14b076b265a8647dd99304fb9 Mon Sep 17 00:00:00 2001
From: Thomas Kluyver 
Date: Thu, 5 Jan 2012 23:24:25 +0000
Subject: [PATCH 43/84] Installable on Python 3.

---
 clint/arguments.py       |  6 +++++-
 clint/eng.py             | 13 +++++++------
 clint/resources.py       |  2 +-
 clint/textui/__init__.py |  2 +-
 clint/utils.py           |  2 +-
 5 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/clint/arguments.py b/clint/arguments.py
index 4b823b67..e4f25a4b 100644
--- a/clint/arguments.py
+++ b/clint/arguments.py
@@ -14,7 +14,11 @@
 import os
 from sys import argv
 
-from .packages.ordereddict import OrderedDict
+try:
+    from collections import OrderedDict
+except ImportError:
+    from .packages.ordereddict import OrderedDict
+
 from .utils import expand_path, is_collection
 
 __all__ = ('Args', )
diff --git a/clint/eng.py b/clint/eng.py
index c8e5774f..8d9f6082 100644
--- a/clint/eng.py
+++ b/clint/eng.py
@@ -7,6 +7,7 @@
 This module provides English language string helpers.
 
 """
+from __future__ import print_function
 
 MORON_MODE = False
 COMMA = ','
@@ -41,9 +42,9 @@ def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, seperator=COMMA):
     return unicode(str().join(collector))
 
 if __name__ == '__main__':
-    print join(['blue', 'red', 'yellow'], conj='or', im_a_moron=True)
-    print join(['blue', 'red', 'yellow'], conj='or')
-    print join(['blue', 'red'], conj='or')
-    print join(['blue', 'red'], conj='and')
-    print join(['blue'], conj='and')
-    print join(['blue', 'red', 'yellow', 'green', 'ello'], conj='and')
\ No newline at end of file
+    print(join(['blue', 'red', 'yellow'], conj='or', im_a_moron=True))
+    print(join(['blue', 'red', 'yellow'], conj='or'))
+    print(join(['blue', 'red'], conj='or'))
+    print(join(['blue', 'red'], conj='and'))
+    print(join(['blue'], conj='and'))
+    print(join(['blue', 'red', 'yellow', 'green', 'ello'], conj='and'))
diff --git a/clint/resources.py b/clint/resources.py
index b4827502..b499a0fe 100644
--- a/clint/resources.py
+++ b/clint/resources.py
@@ -115,7 +115,7 @@ def delete(self, filename=''):
                 remove(fn)
             else:
                 removedirs(fn)
-        except OSError, why:
+        except OSError as why:
             if why.errno == errno.ENOENT:
                 pass
             else:
diff --git a/clint/textui/__init__.py b/clint/textui/__init__.py
index 39681c68..3b8c92a5 100644
--- a/clint/textui/__init__.py
+++ b/clint/textui/__init__.py
@@ -12,4 +12,4 @@
 from . import colored
 from . import progress
 
-from core import *
+from .core import *
diff --git a/clint/utils.py b/clint/utils.py
index b215c337..fb41ff1f 100644
--- a/clint/utils.py
+++ b/clint/utils.py
@@ -49,7 +49,7 @@ def mkdir_p(path):
     """Emulates `mkdir -p` behavior."""
     try:
         makedirs(path)
-    except OSError, exc: # Python >2.5
+    except OSError as exc: # Python >2.5
         if exc.errno == errno.EEXIST:
             pass
         else:

From b16b2ce7237159c3764c5cc2a3e7292d31310d25 Mon Sep 17 00:00:00 2001
From: Thomas Kluyver 
Date: Fri, 6 Jan 2012 00:11:51 +0000
Subject: [PATCH 44/84] All examples work on Python 3.

---
 clint/eng.py            |  5 +++++
 clint/textui/colored.py | 18 +++++++++++++-----
 clint/utils.py          |  4 ++++
 examples/colors_all.py  |  4 +++-
 examples/eng_join.py    |  2 +-
 examples/resources.py   | 12 +++++++-----
 examples/text_width.py  |  5 +++--
 7 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/clint/eng.py b/clint/eng.py
index 8d9f6082..e903631b 100644
--- a/clint/eng.py
+++ b/clint/eng.py
@@ -14,6 +14,11 @@
 CONJUNCTION = 'and'
 SPACE = ' '
 
+try:
+    unicode
+except NameError:
+    unicode = str
+
 
 def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, seperator=COMMA):
     """Joins lists of words. Oxford comma and all."""
diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index e7c0754f..63d7593d 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -14,6 +14,8 @@
 import re
 import sys
 
+PY3 = sys.version_info[0] >= 3
+
 from ..packages import colorama
 
 __all__ = (
@@ -53,12 +55,18 @@ def __len__(self):
     def __repr__(self):
         return "<%s-string: '%s'>" % (self.color, self.s)
 
-    def __str__(self):
-        return self.__unicode__().encode('utf8')
-
     def __unicode__(self):
         return self.color_str
 
+    if PY3:
+        __str__ = __unicode__
+    else:
+        def __str__(self):
+            return unicode(self).encode('utf8')
+
+    def __iter__(self):
+        return iter(self.color_str)
+
     def __add__(self, other):
         return str(self.color_str) + str(other)
 
@@ -68,8 +76,8 @@ def __radd__(self, other):
     def __mul__(self, other):
         return (self.color_str * other)
 
-    def split(self, x=' '):
-        return map(self._new, self.s.split(x))
+    def split(self, sep=None):
+        return [self._new(s) for s in self.s.split(sep)]
 
     def _new(self, s):
         return ColoredString(self.color, s)
diff --git a/clint/utils.py b/clint/utils.py
index fb41ff1f..e84e8514 100644
--- a/clint/utils.py
+++ b/clint/utils.py
@@ -16,6 +16,10 @@
 from os import makedirs
 from glob import glob
 
+try:
+    basestring
+except NameError:
+    basestring = str
 
 def expand_path(path):
     """Expands directories and globs in given path."""
diff --git a/examples/colors_all.py b/examples/colors_all.py
index 92dd7799..79d09c59 100755
--- a/examples/colors_all.py
+++ b/examples/colors_all.py
@@ -1,6 +1,8 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+from __future__ import print_function
+
 import sys
 import os
 
@@ -13,4 +15,4 @@
 if __name__ == '__main__':
 
 	for color in colored.COLORS:
-		print getattr(colored, color)(text % color.upper())
\ No newline at end of file
+		print(getattr(colored, color)(text % color.upper()))
diff --git a/examples/eng_join.py b/examples/eng_join.py
index c2736b17..12d3deea 100644
--- a/examples/eng_join.py
+++ b/examples/eng_join.py
@@ -17,7 +17,7 @@
     colored.magenta('magenta')
 ]
 
-colors = map(str, colors)
+colors = [str(cs) for cs in colors]
 
 
 puts('Smart:')
diff --git a/examples/resources.py b/examples/resources.py
index 7380c098..0ec65d0e 100755
--- a/examples/resources.py
+++ b/examples/resources.py
@@ -1,6 +1,8 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+from __future__ import print_function
+
 import sys
 import os
 
@@ -13,16 +15,16 @@
 lorem = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
 
 
-print '%s created.' % resources.user.path
+print('%s created.' % resources.user.path)
 
 resources.user.write('lorem.txt', lorem)
-print 'lorem.txt created'
+print('lorem.txt created')
 
 assert resources.user.read('lorem.txt') == lorem
-print 'lorem.txt has correct contents'
+print('lorem.txt has correct contents')
 
 resources.user.delete('lorem.txt')
-print 'lorem.txt deleted'
+print('lorem.txt deleted')
 
 assert resources.user.read('lorem.txt') == None
-print 'lorem.txt deletion confirmed'
\ No newline at end of file
+print('lorem.txt deletion confirmed')
diff --git a/examples/text_width.py b/examples/text_width.py
index bfbfe153..ed377163 100755
--- a/examples/text_width.py
+++ b/examples/text_width.py
@@ -19,5 +19,6 @@
     
     col = 60
     
-    puts(columns([(colored.red('Column 1')), col], [(colored.green('Column Two')), None], [(colored.magenta('Column III')), col]))
-    puts(columns(['hi there my name is kenneth and this is a columns', col], [lorem, None], ['kenneths', col]))
\ No newline at end of file
+    puts(columns([(colored.red('Column 1')), col], [(colored.green('Column Two')), None],
+                    [(colored.magenta('Column III')), col]))
+    puts(columns(['hi there my name is kenneth and this is a columns', col], [lorem, None], ['kenneths', col]))

From 9a4705f090dda6a345e9ac5900fddf936d3edb08 Mon Sep 17 00:00:00 2001
From: Thomas Kluyver 
Date: Fri, 6 Jan 2012 00:16:14 +0000
Subject: [PATCH 45/84] Update trove classifiers.

---
 .gitignore | 1 +
 setup.py   | 8 ++++++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index b49e53e4..875204c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
 MANIFEST
 *.pyc
 .tox
+build/
diff --git a/setup.py b/setup.py
index a6f90e78..fd62e297 100644
--- a/setup.py
+++ b/setup.py
@@ -38,14 +38,18 @@ def publish():
     license='ISC',
     classifiers=(
 #       'Development Status :: 5 - Production/Stable',
+        'Environment :: Console',
         'Intended Audience :: Developers',
         'Natural Language :: English',
         'License :: OSI Approved :: ISC License (ISCL)',
         'Programming Language :: Python',
+        'Programming Language :: Python :: 2',
         'Programming Language :: Python :: 2.5',
         'Programming Language :: Python :: 2.6',
         'Programming Language :: Python :: 2.7',
-        # 'Programming Language :: Python :: 3.0',
-        # 'Programming Language :: Python :: 3.1',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.1',
+        'Programming Language :: Python :: 3.2',
+        'Topic :: Terminals :: Terminal Emulators/X Terminals',
     ),
 )

From dbb063840a09511b122683f9d37c5e4f229ca3c1 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz 
Date: Thu, 5 Jan 2012 22:14:33 -0500
Subject: [PATCH 46/84] v0.3.0

---
 AUTHORS           | 1 +
 HISTORY.rst       | 5 +++++
 clint/__init__.py | 6 +++---
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index f172f244..5d258aa0 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -16,3 +16,4 @@ Patches and Suggestions
 - Will Thames
 - Greg Haskins
 - Miguel Araujo 
+- takluyver
\ No newline at end of file
diff --git a/HISTORY.rst b/HISTORY.rst
index 5ece8fcc..d13983ec 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -1,6 +1,11 @@
 History
 -------
 
+0.3.0
++++++
+
+* Python 3 support!
+
 0.2.4
 +++++
 
diff --git a/clint/__init__.py b/clint/__init__.py
index 793226bb..609b9488 100644
--- a/clint/__init__.py
+++ b/clint/__init__.py
@@ -19,11 +19,11 @@
 
 
 __title__ = 'clint'
-__version__ = '0.2.5'
-__build__ = 0x000205
+__version__ = '0.3.0'
+__build__ = 0x000300
 __author__ = 'Kenneth Reitz'
 __license__ = 'ISC'
-__copyright__ = 'Copyright 2011 Kenneth Reitz'
+__copyright__ = 'Copyright 2012 Kenneth Reitz'
 __docformat__ = 'restructuredtext'
 
 

From d6214ababb34f9fe5ae77fabb415ca87f0e3dd72 Mon Sep 17 00:00:00 2001
From: Thomas Hunger 
Date: Fri, 6 Jan 2012 23:40:43 +0000
Subject: [PATCH 47/84] Distribute README.rst and HISTORY.rst when building
 sdist.

---
 setup.py | 4 ++++
 1 file changed, 4 insertions(+)
 mode change 100644 => 100755 setup.py

diff --git a/setup.py b/setup.py
old mode 100644
new mode 100755
index fd62e297..78d9904b
--- a/setup.py
+++ b/setup.py
@@ -29,6 +29,10 @@ def publish():
     author='Kenneth Reitz',
     author_email='me@kennethreitz.com',
     url='https://github.com/kennethreitz/clint',
+    data_files=[
+        'README.rst',
+        'HISTORY.rst',
+    ],
     packages= [
         'clint',
         'clint.textui',

From 526cf84ebb63f1b2f9758a347da76edae5c0d8b1 Mon Sep 17 00:00:00 2001
From: kracekumar 
Date: Sat, 7 Jan 2012 21:45:31 +0530
Subject: [PATCH 48/84] added a method to find current python interpreter is
 ipython, if so color shoudl be disabled

---
 AUTHORS                 |  3 ++-
 HACKING                 |  2 +-
 clint/textui/colored.py | 11 ++++++++++-
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 5d258aa0..8896c964 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -16,4 +16,5 @@ Patches and Suggestions
 - Will Thames
 - Greg Haskins
 - Miguel Araujo 
-- takluyver
\ No newline at end of file
+- takluyver
+- kracekumar 
diff --git a/HACKING b/HACKING
index 018f9b7a..46b9651f 100644
--- a/HACKING
+++ b/HACKING
@@ -11,4 +11,4 @@ All functionality should be available in pure Python. Optional C (via Cython)
 implementations may be written for performance reasons, but should never
 replace the Python implementation.
 
-Lastly, don't take yourself too seriously :)
\ No newline at end of file
+Lastly, don't take yourself too seriously :)
diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index 63d7593d..f93f50ff 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -25,7 +25,16 @@
 )
 
 COLORS = __all__[:-2]
-DISABLE_COLOR = False
+
+if 'get_ipython' in dir():
+"""
+    when ipython is fired lot of variables like _oh, etc are used.
+    There are so many ways to find current python interpreter is ipython.
+    get_ipython is easiest is most appealing for readers to understand.
+"""
+    DISABLE_COLOR = True
+else:
+    DISABLE_COLOR = False
 
 if not sys.stdout.isatty():
     DISABLE_COLOR = True

From 5f2df1218a00df595d660bbea31c7bbc3cf573f7 Mon Sep 17 00:00:00 2001
From: kracekumar 
Date: Sat, 7 Jan 2012 21:47:55 +0530
Subject: [PATCH 49/84] fixed spaces

---
 clint/textui/colored.py | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index f93f50ff..78e43938 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -27,11 +27,11 @@
 COLORS = __all__[:-2]
 
 if 'get_ipython' in dir():
-"""
-    when ipython is fired lot of variables like _oh, etc are used.
-    There are so many ways to find current python interpreter is ipython.
-    get_ipython is easiest is most appealing for readers to understand.
-"""
+   """
+       when ipython is fired lot of variables like _oh, etc are used.
+       There are so many ways to find current python interpreter is ipython.
+       get_ipython is easiest is most appealing for readers to understand.
+    """
     DISABLE_COLOR = True
 else:
     DISABLE_COLOR = False

From c9bf3bac3a75e009dfe05f19555c2831892abf59 Mon Sep 17 00:00:00 2001
From: kracekumar 
Date: Sat, 7 Jan 2012 21:54:17 +0530
Subject: [PATCH 50/84] works perfectly fine with ipython, standard python
 interpreter and unfortuantely clint colors wont work in dreampie :(

---
 clint/textui/colored.py | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index 78e43938..10c89311 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -27,7 +27,7 @@
 COLORS = __all__[:-2]
 
 if 'get_ipython' in dir():
-   """
+    """
        when ipython is fired lot of variables like _oh, etc are used.
        There are so many ways to find current python interpreter is ipython.
        get_ipython is easiest is most appealing for readers to understand.
@@ -36,10 +36,6 @@
 else:
     DISABLE_COLOR = False
 
-if not sys.stdout.isatty():
-    DISABLE_COLOR = True
-else:
-    colorama.init(autoreset=True)
 
 
 class ColoredString(object):

From ec46d65bd273f4cbb0fdecf68fca2facdf24151b Mon Sep 17 00:00:00 2001
From: Collin Watson 
Date: Sat, 14 Jan 2012 00:59:44 -0800
Subject: [PATCH 51/84] Added support for colored unicode

---
 clint/textui/colored.py |  5 ++++-
 examples/unicode.py     | 32 ++++++++++++++++++++++++++++++++
 examples/unicode.sh     |  3 +++
 3 files changed, 39 insertions(+), 1 deletion(-)
 create mode 100644 examples/unicode.py
 create mode 100755 examples/unicode.sh

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index 10c89311..6b409424 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -61,7 +61,10 @@ def __repr__(self):
         return "<%s-string: '%s'>" % (self.color, self.s)
 
     def __unicode__(self):
-        return self.color_str
+        value = self.color_str
+        if isinstance(value, basestring):
+            return ('%s' % value).decode('utf8')
+        return value
 
     if PY3:
         __str__ = __unicode__
diff --git a/examples/unicode.py b/examples/unicode.py
new file mode 100644
index 00000000..3df92fcb
--- /dev/null
+++ b/examples/unicode.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+sys.path.insert(0, os.path.abspath('..'))
+
+from clint import args
+from clint.textui import colored, puts, indent
+
+if __name__ == '__main__':
+
+    puts('Test:')
+    with indent(4):
+        puts('%s Fake test 1.' % colored.green('✔'))
+        puts('%s Fake test 2.' % colored.red('✖'))
+
+    puts('')
+    puts('Greet:')
+    with indent(4):
+        puts(colored.red('Здравствуйте'))
+        puts(colored.green('你好。'))
+        puts(colored.yellow('سلام'))
+        puts(colored.magenta('안녕하세요'))
+        puts(colored.blue('नमस्ते'))
+        puts(colored.cyan('γειά σου'))
+
+    puts('')
+    puts('Arguments:')
+    with indent(4):
+        for arg in args.all:
+            puts('%s' % colored.red(arg))
diff --git a/examples/unicode.sh b/examples/unicode.sh
new file mode 100755
index 00000000..47a95e9d
--- /dev/null
+++ b/examples/unicode.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+
+python unicode.py こんにちは。

From 7e1c7397553a0f8bdbd55ee18613cf5066cef09b Mon Sep 17 00:00:00 2001
From: Collin Watson 
Date: Sat, 14 Jan 2012 01:11:47 -0800
Subject: [PATCH 52/84] Ignore unicode strings as they are already decoded

---
 clint/textui/colored.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index 6b409424..5ff2b43f 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -62,7 +62,7 @@ def __repr__(self):
 
     def __unicode__(self):
         value = self.color_str
-        if isinstance(value, basestring):
+        if isinstance(value, str):
             return ('%s' % value).decode('utf8')
         return value
 

From a95e803268f298a4b7c7f9b64693b4f5507d9763 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20G=C3=B3mez?= 
Date: Sat, 14 Jan 2012 19:01:23 +0100
Subject: [PATCH 53/84] Add a mill progress indicator to `progress.py`

I've created a progress indicator that outputs a "mill" and added it to
the `progress.py` file.

Very simple stuff but its more compact than the other progress bars and
it can be useful when using long labels.
---
 AUTHORS                  |  1 +
 clint/textui/progress.py | 31 +++++++++++++++++++++++++++++++
 examples/progressbar.py  |  4 +++-
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/AUTHORS b/AUTHORS
index 8896c964..cdbc3d18 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -18,3 +18,4 @@ Patches and Suggestions
 - Miguel Araujo 
 - takluyver
 - kracekumar 
+- Alejandro Gómez 
diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index 3a94d1bb..d0f93c77 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -15,10 +15,12 @@
 STREAM = sys.stderr
 
 BAR_TEMPLATE = '%s[%s%s] %i/%i\r'
+MILL_TEMPLATE = '%s %s %i/%i\r'  
 
 DOTS_CHAR = '.'
 BAR_FILLED_CHAR = '#'
 BAR_EMPTY_CHAR = ' '
+MILL_CHARS = ['|', '/', '-', '\\']
 
 def bar(it, label='', width=32, hide=False, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR):
     """Progress iterator. Wrap your iterables with it."""
@@ -65,3 +67,32 @@ def dots(it, label='', hide=False):
     STREAM.write('\n')
     STREAM.flush()
 
+
+def mill(it, label='', hide=False,): 
+    """Progress iterator. Prints a mill while iterating over the items."""
+
+    def _mill_char(_i):
+        if _i == 100:
+            return ' '
+        else:
+            return MILL_CHARS[_i % len(MILL_CHARS)]
+
+    def _show(_i):
+        if not hide:
+            STREAM.write(MILL_TEMPLATE % (
+                label, _mill_char(_i), _i, count))
+            STREAM.flush()
+
+    count = len(it)
+
+    if count:
+        _show(0)
+
+    for i, item in enumerate(it):
+
+        yield item
+        _show(i+1)
+
+    if not hide:
+        STREAM.write('\n')
+        STREAM.flush()
diff --git a/examples/progressbar.py b/examples/progressbar.py
index 7643d524..951552ee 100755
--- a/examples/progressbar.py
+++ b/examples/progressbar.py
@@ -17,4 +17,6 @@
 
     for i in progress.dots(range(100)):
         sleep(random() * 0.2)
-    
\ No newline at end of file
+    
+    for i in progress.mill(range(100)):
+        sleep(random() * 0.2)

From b917e688379f8b7c74bfab40ac23e99dab925828 Mon Sep 17 00:00:00 2001
From: Collin Watson 
Date: Sat, 14 Jan 2012 12:17:29 -0800
Subject: [PATCH 54/84] Removed unnecessary interpolation since it's a known
 string

---
 clint/textui/colored.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index 5ff2b43f..db707297 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -63,7 +63,7 @@ def __repr__(self):
     def __unicode__(self):
         value = self.color_str
         if isinstance(value, str):
-            return ('%s' % value).decode('utf8')
+            return value.decode('utf8')
         return value
 
     if PY3:

From 1d1bb71203fc4a963b8bdaeca97094c95656e62b Mon Sep 17 00:00:00 2001
From: Collin Watson 
Date: Sat, 14 Jan 2012 12:17:46 -0800
Subject: [PATCH 55/84] Added unicode file and input examples

---
 examples/unicode.json |  4 ++++
 examples/unicode.py   | 33 ++++++++++++++++++++++++++++++---
 examples/unicode.sh   |  2 +-
 3 files changed, 35 insertions(+), 4 deletions(-)
 create mode 100644 examples/unicode.json

diff --git a/examples/unicode.json b/examples/unicode.json
new file mode 100644
index 00000000..94f9554c
--- /dev/null
+++ b/examples/unicode.json
@@ -0,0 +1,4 @@
+{
+    "title": "Bashō's 'old pond'",
+    "text": "古池や蛙飛込む水の音"
+}
diff --git a/examples/unicode.py b/examples/unicode.py
index 3df92fcb..8168fde3 100644
--- a/examples/unicode.py
+++ b/examples/unicode.py
@@ -1,11 +1,18 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-
 import os
 import sys
+import codecs
+
 sys.path.insert(0, os.path.abspath('..'))
 
+try:
+    import json
+except:
+    import simplejson as json
+
 from clint import args
+from clint import piped_in
 from clint.textui import colored, puts, indent
 
 if __name__ == '__main__':
@@ -28,5 +35,25 @@
     puts('')
     puts('Arguments:')
     with indent(4):
-        for arg in args.all:
-            puts('%s' % colored.red(arg))
+        puts('%s' % colored.red(args[0]))
+
+    puts('')
+    puts('File:')
+    with indent(4):
+        f = args.files[0]
+        puts(colored.yellow('%s:' % f))
+        with indent(2):
+            fd = codecs.open(f, encoding='utf-8')
+            for line in fd:
+                line = line.strip('\n\r')
+                puts(colored.yellow('  %s' % line))
+            fd.close()
+
+    puts('')
+    puts('Input:')
+    with indent(4):
+        in_data = json.loads(piped_in())
+        title = in_data['title']
+        text = in_data['text']
+        puts(colored.blue('Title: %s' % title))
+        puts(colored.magenta('Text: %s' % text))
diff --git a/examples/unicode.sh b/examples/unicode.sh
index 47a95e9d..fc93c670 100755
--- a/examples/unicode.sh
+++ b/examples/unicode.sh
@@ -1,3 +1,3 @@
 #!/usr/bin/env sh
 
-python unicode.py こんにちは。
+python unicode.py こんにちは。 unicode.json < unicode.json

From 3a40b682f44ae34b93c9097fb0bdda5fff8622b1 Mon Sep 17 00:00:00 2001
From: Collin Watson 
Date: Sat, 14 Jan 2012 17:03:10 -0800
Subject: [PATCH 56/84] Support python 3 by checking if the decode attribute
 exists.

---
 clint/textui/colored.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index db707297..7ff3878c 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -62,7 +62,7 @@ def __repr__(self):
 
     def __unicode__(self):
         value = self.color_str
-        if isinstance(value, str):
+        if isinstance(value, str) and hasattr(value, 'decode'):
             return value.decode('utf8')
         return value
 

From e8f6f7737ad569afd5ebfea0a27a9cfd89c64370 Mon Sep 17 00:00:00 2001
From: Collin Watson 
Date: Tue, 17 Jan 2012 08:07:42 -0800
Subject: [PATCH 57/84] Explicitly chack for instances of bytes to distinguish
 between py2 and py3.

---
 clint/textui/colored.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index 7ff3878c..0906dde3 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -62,7 +62,7 @@ def __repr__(self):
 
     def __unicode__(self):
         value = self.color_str
-        if isinstance(value, str) and hasattr(value, 'decode'):
+        if isinstance(value, bytes):
             return value.decode('utf8')
         return value
 

From 270afcca03c72e0f950c0f4042f31051ebec9892 Mon Sep 17 00:00:00 2001
From: Jason Piper 
Date: Mon, 23 Jan 2012 13:50:45 +0000
Subject: [PATCH 58/84] Added progress bar ETA

Very simplistic, currently updates every iteration (not a performance
issue, but not the prettiest way to do it)
---
 clint/textui/progress.py | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index d0f93c77..369b19a0 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -11,10 +11,11 @@
 from __future__ import absolute_import
 
 import sys
+import time
 
 STREAM = sys.stderr
 
-BAR_TEMPLATE = '%s[%s%s] %i/%i\r'
+BAR_TEMPLATE = '%s[%s%s] %i/%i - %s\r'
 MILL_TEMPLATE = '%s %s %i/%i\r'  
 
 DOTS_CHAR = '.'
@@ -26,14 +27,17 @@ def bar(it, label='', width=32, hide=False, empty_char=BAR_EMPTY_CHAR, filled_ch
     """Progress iterator. Wrap your iterables with it."""
 
     def _show(_i):
+        ETA = -((start-time.time())/(_i+1)) * (count-_i)
+        ETADisp = time.strftime('%H:%M:%S', time.gmtime(ETA))
         x = int(width*_i/count)
         if not hide:
             STREAM.write(BAR_TEMPLATE % (
-                label, filled_char*x, empty_char*(width-x), _i, count))
+            label, filled_char*x, empty_char*(width-x), _i, count, ETADisp))
             STREAM.flush()
 
     count = len(it)
 
+    start = time.time()
     if count:
         _show(0)
 

From a9d1089bbd7dfaf9272e4c4168ed2c981c800d27 Mon Sep 17 00:00:00 2001
From: Jason Piper 
Date: Mon, 23 Jan 2012 14:27:57 +0000
Subject: [PATCH 59/84] Updated averaging method

Calculates a simple moving average based on the number of iterations
done in (1) second intervals over the last (10) seconds
---
 clint/textui/progress.py | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index 369b19a0..bb7b0b83 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -23,21 +23,34 @@
 BAR_EMPTY_CHAR = ' '
 MILL_CHARS = ['|', '/', '-', '\\']
 
+#How long to wait before recalculating the ETA
+ETA_INTERVAL = 1
+#How many intervals (excluding the current one) to calculate the simple moving average
+ETA_SMA_WINDOW = 9
+
 def bar(it, label='', width=32, hide=False, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR):
     """Progress iterator. Wrap your iterables with it."""
 
     def _show(_i):
-        ETA = -((start-time.time())/(_i+1)) * (count-_i)
-        ETADisp = time.strftime('%H:%M:%S', time.gmtime(ETA))
+        if (time.time() - bar.etadelta) > ETA_INTERVAL:
+            bar.etadelta = time.time()
+            bar.ittimes = bar.ittimes[-ETA_SMA_WINDOW:]+[-(bar.start-time.time())/(_i+1)]
+            bar.eta = sum(bar.ittimes)/float(len(bar.ittimes)) * (count-_i)
+            bar.etadisp = time.strftime('%H:%M:%S', time.gmtime(bar.eta))
         x = int(width*_i/count)
         if not hide:
             STREAM.write(BAR_TEMPLATE % (
-            label, filled_char*x, empty_char*(width-x), _i, count, ETADisp))
+            label, filled_char*x, empty_char*(width-x), _i, count, bar.etadisp))
             STREAM.flush()
 
     count = len(it)
 
-    start = time.time()
+    bar.start    = time.time()
+    bar.ittimes  = []
+    bar.eta      = 0
+    bar.etadelta = time.time()
+    bar.etadisp  = time.strftime('%H:%M:%S', time.gmtime(bar.eta))
+
     if count:
         _show(0)
 

From 129fea5e4ffa723d8edab292e3b5511c43de7e10 Mon Sep 17 00:00:00 2001
From: Jason Piper 
Date: Mon, 23 Jan 2012 14:38:39 +0000
Subject: [PATCH 60/84] added myself to AUTHORS

---
 AUTHORS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/AUTHORS b/AUTHORS
index cdbc3d18..18cbb7c5 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -19,3 +19,4 @@ Patches and Suggestions
 - takluyver
 - kracekumar 
 - Alejandro Gómez 
+- Jason Piper 
\ No newline at end of file

From 72b04cf5af6039986ed6b071e6a28df2a3ea5a21 Mon Sep 17 00:00:00 2001
From:  Boris Feld 
Date: Sat, 11 Feb 2012 22:51:20 +0100
Subject: [PATCH 61/84] Add a dedent util function, useful when using indent
 otherwise than as a context.

---
 clint/textui/core.py | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/clint/textui/core.py b/clint/textui/core.py
index af9cab2f..906adb83 100644
--- a/clint/textui/core.py
+++ b/clint/textui/core.py
@@ -58,8 +58,11 @@ def __enter__(self):
 
 
     def __exit__(self, type, value, traceback):
-        self.shared['indent_strings'].pop()
+        self._dedent()
 
+    @classmethod
+    def _dedent(cls):
+        cls.shared['indent_strings'].pop()        
 
     def __call__(self, s, newline=True, stream=STDOUT):
 
@@ -91,3 +94,7 @@ def puts_err(s='', newline=True, stream=STDERR):
 def indent(indent=4, quote=''):
     """Indentation context manager."""
     return Writer(indent=indent, quote=quote)
+    
+def dedent():
+    return Writer._dedent()
+

From 761dce723797a95dc77d03d7f52317ff19e2fb94 Mon Sep 17 00:00:00 2001
From: FELD Boris 
Date: Sun, 12 Feb 2012 17:20:42 +0100
Subject: [PATCH 62/84] Try to reimplement clint.textui.core in a more simpler
 way

---
 clint/textui/core.py | 94 ++++++++++++++++++++------------------------
 1 file changed, 42 insertions(+), 52 deletions(-)

diff --git a/clint/textui/core.py b/clint/textui/core.py
index 906adb83..31054974 100644
--- a/clint/textui/core.py
+++ b/clint/textui/core.py
@@ -13,12 +13,15 @@
 
 import sys
 
+from contextlib import contextmanager
+
 from .formatters import max_width, min_width
 from .cols import columns
 from ..utils import tsplit
 
 
-__all__ = ('puts', 'puts_err', 'indent', 'columns', 'max_width', 'min_width')
+__all__ = ('puts', 'puts_err', 'indent', 'dedent', 'columns', 'max_width',
+    'min_width')
 
 
 STDOUT = sys.stdout.write
@@ -26,75 +29,62 @@
 
 NEWLINES = ('\n', '\r', '\r\n')
 
+INDENT_STRINGS = []
 
+# Private
 
-class Writer(object):
-    """WriterUtilized by context managers."""
-
-    shared = dict(indent_level=0, indent_strings=[])
-
-
-    def __init__(self, indent=0, quote='', indent_char=' '):
-        self.indent = indent
-        self.indent_char = indent_char
-        self.indent_quote = quote
-        if self.indent > 0:
-            self.indent_string = ''.join((
-                str(quote),
-                (self.indent_char * (indent - len(self.indent_quote)))
-            ))
-        else:
-            self.indent_string = ''.join((
-                ('\x08' * (-1 * (indent - len(self.indent_quote)))),
-                str(quote))
-            )
+def _indent(indent=0, quote='', indent_char=' '):
+    """Indent util function, compute new indent_string"""
+    if indent > 0:
+        indent_string = ''.join((
+            str(quote),
+            (indent_char * (indent - len(quote)))
+        ))
+    else:
+        indent_string = ''.join((
+            ('\x08' * (-1 * (indent - len(quote)))),
+            str(quote))
+        )
 
-        if len(self.indent_string):
-            self.shared['indent_strings'].append(self.indent_string)
+    if len(indent_string):
+        INDENT_STRINGS.append(indent_string)
 
+class IndentContext(object):
 
     def __enter__(self):
         return self
 
-
     def __exit__(self, type, value, traceback):
-        self._dedent()
-
-    @classmethod
-    def _dedent(cls):
-        cls.shared['indent_strings'].pop()        
-
-    def __call__(self, s, newline=True, stream=STDOUT):
-
-        if newline:
-            s = tsplit(s, NEWLINES)
-            s = map(str, s)
-            indent = ''.join(self.shared['indent_strings'])
-
-            s = (str('\n' + indent)).join(s)
-
-        _str = ''.join((
-            ''.join(self.shared['indent_strings']),
-            str(s),
-            '\n' if newline else ''
-        ))
-        stream(_str)
+        dedent()
 
+# Public
 
 def puts(s='', newline=True, stream=STDOUT):
     """Prints given string to stdout via Writer interface."""
-    Writer()(s, newline, stream=stream)
+    if newline:
+        s = tsplit(s, NEWLINES)
+        s = map(str, s)
+        indent = ''.join(INDENT_STRINGS)
 
+        s = (str('\n' + indent)).join(s)
+
+    _str = ''.join((
+        ''.join(INDENT_STRINGS),
+        str(s),
+        '\n' if newline else ''
+    ))
+    stream(_str)
 
 def puts_err(s='', newline=True, stream=STDERR):
     """Prints given string to stderr via Writer interface."""
-    Writer()(s, newline, stream=stream)
+    puts(s, newline, stream)
 
+def dedent():
+    """Dedent next strings, use only if you use indent otherwise than as a
+    context."""
+    INDENT_STRINGS.pop()
 
 def indent(indent=4, quote=''):
     """Indentation context manager."""
-    return Writer(indent=indent, quote=quote)
-    
-def dedent():
-    return Writer._dedent()
-
+    _indent(indent, quote)
+    return IndentContext()

From ea9b2186d5b30f653d5651d0787bdfca47c10d71 Mon Sep 17 00:00:00 2001
From: FELD Boris 
Date: Sun, 12 Feb 2012 17:32:59 +0100
Subject: [PATCH 63/84] More simple implementation of indent context

---
 clint/textui/core.py | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/clint/textui/core.py b/clint/textui/core.py
index 31054974..09a678e9 100644
--- a/clint/textui/core.py
+++ b/clint/textui/core.py
@@ -49,14 +49,6 @@ def _indent(indent=0, quote='', indent_char=' '):
     if len(indent_string):
         INDENT_STRINGS.append(indent_string)
 
-class IndentContext(object):
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, type, value, traceback):
-        dedent()
-
 # Public
 
 def puts(s='', newline=True, stream=STDOUT):
@@ -84,7 +76,12 @@ def dedent():
     context."""
     INDENT_STRINGS.pop()
 
+@contextmanager
+def _indent_context():
+    yield
+    dedent()
+
 def indent(indent=4, quote=''):
     """Indentation context manager."""
     _indent(indent, quote)
-    return IndentContext()
+    return _indent_context()

From 7c48045b574f46905a1ce3d999168cdd747fa341 Mon Sep 17 00:00:00 2001
From: FELD Boris 
Date: Sun, 12 Feb 2012 17:46:33 +0100
Subject: [PATCH 64/84] Update clint.textui.core's docstrings

---
 clint/textui/core.py | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clint/textui/core.py b/clint/textui/core.py
index 09a678e9..6ddacc36 100644
--- a/clint/textui/core.py
+++ b/clint/textui/core.py
@@ -52,7 +52,7 @@ def _indent(indent=0, quote='', indent_char=' '):
 # Public
 
 def puts(s='', newline=True, stream=STDOUT):
-    """Prints given string to stdout via Writer interface."""
+    """Prints given string to stdout."""
     if newline:
         s = tsplit(s, NEWLINES)
         s = map(str, s)
@@ -68,7 +68,7 @@ def puts(s='', newline=True, stream=STDOUT):
     stream(_str)
 
 def puts_err(s='', newline=True, stream=STDERR):
-    """Prints given string to stderr via Writer interface."""
+    """Prints given string to stderr."""
     puts(s, newline, stream)
 
 def dedent():
@@ -78,10 +78,11 @@ def dedent():
 
 @contextmanager
 def _indent_context():
+    """Indentation context manager."""
     yield
     dedent()
 
 def indent(indent=4, quote=''):
-    """Indentation context manager."""
+    """Indentation manager, return an indentation context manager."""
     _indent(indent, quote)
     return _indent_context()

From d4cb4e8c01ca5243c26a30e9ae78fc76c58345f7 Mon Sep 17 00:00:00 2001
From: Giorgos Verigakis 
Date: Tue, 14 Feb 2012 23:57:45 +0200
Subject: [PATCH 65/84] Allow multiple occurences of a flag in grouped

---
 clint/arguments.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clint/arguments.py b/clint/arguments.py
index e4f25a4b..d13622a5 100644
--- a/clint/arguments.py
+++ b/clint/arguments.py
@@ -241,7 +241,7 @@ def grouped(self):
         for arg in self.all:
             if arg.startswith('-'):
                 _current_group = arg
-                collection[arg] = Args(no_argv=True)
+                collection.setdefault(arg, Args(no_argv=True))
             else:
                 if _current_group:
                     collection[_current_group]._args.append(arg)

From d479ea3a3c4ff708483b36b6beb557440bbe125e Mon Sep 17 00:00:00 2001
From: Thomas Kluyver 
Date: Tue, 21 Feb 2012 19:11:14 +0000
Subject: [PATCH 66/84] Initialise colorama for textui on Windows.

Closes gh-39
---
 clint/textui/__init__.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/clint/textui/__init__.py b/clint/textui/__init__.py
index 3b8c92a5..c16fff94 100644
--- a/clint/textui/__init__.py
+++ b/clint/textui/__init__.py
@@ -7,7 +7,10 @@
 This module provides the text output helper system.
 
 """
-
+import sys
+if sys.platform.startswith('win'):
+    from ..packages import colorama
+    colorama.init()
 
 from . import colored
 from . import progress

From 86b196811f20abc099aa78a975adbcd28da0b98f Mon Sep 17 00:00:00 2001
From: Michael Simpson 
Date: Thu, 23 Feb 2012 14:26:05 -0500
Subject: [PATCH 67/84] Update README.rst

---
 README.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.rst b/README.rst
index a2fa853d..c3b00f13 100644
--- a/README.rst
+++ b/README.rst
@@ -70,7 +70,7 @@ I want to quote my console text (like email). ::
     >>>     puts('pretty cool, eh?')
     
     not indented text
-     >  indented text
+     >  quoted text
      >  pretty cool, eh?
 
 I want to color my console text. ::

From 48d9c16f0ff5e92bf10b82739230f9fef3f92d53 Mon Sep 17 00:00:00 2001
From: Gianluca Brindisi 
Date: Fri, 6 Apr 2012 15:01:14 +0200
Subject: [PATCH 68/84] Added basic yes/no prompt module

---
 AUTHORS                |  3 ++-
 clint/textui/prompt.py | 49 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 clint/textui/prompt.py

diff --git a/AUTHORS b/AUTHORS
index 18cbb7c5..d1fe5de8 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -19,4 +19,5 @@ Patches and Suggestions
 - takluyver
 - kracekumar 
 - Alejandro Gómez 
-- Jason Piper 
\ No newline at end of file
+- Jason Piper 
+- Gianluca Brindisi 
diff --git a/clint/textui/prompt.py b/clint/textui/prompt.py
new file mode 100644
index 00000000..7c4bbdd1
--- /dev/null
+++ b/clint/textui/prompt.py
@@ -0,0 +1,49 @@
+# -*- coding: utf8 -*-
+
+"""
+clint.textui.prompt
+~~~~~~~~~~~~~~~~~~~
+
+Module for simple interactive prompts handling
+
+"""
+
+from __future__ import absolute_import
+
+from re import match, I
+
+def yn(prompt, default='y', batch=False):
+    # A sanity check against default value
+    # If not y/n then y is assumed 
+    if default not in ['y', 'n']:
+        default = 'y'
+    
+    # Let's build the prompt
+    choicebox = '[Y/n]' if default == 'y' else '[y/N]' 
+    prompt = prompt + ' ' + choicebox + ' ' 
+
+    # If input is not a yes/no variant or empty
+    # keep asking
+    while True:
+        # If batch option is True then auto reply 
+        # with default input
+        if not batch:
+            input = raw_input(prompt).strip()
+        else:
+            print prompt
+            input = ''
+
+        # If input is empty default choice is assumed
+        # so we return True
+        if input == '':
+            return True
+
+        # Given 'yes' as input if default choice is y
+        # then return True, False otherwise 
+        if match('y(?:es)?', input, I):
+            return True if default == 'y' else False
+
+        # Given 'no' as input if default choice is n
+        # then return True, False otherwise
+        elif match('n(?:o)?', input, I):
+            return True if default == 'n' else False

From afd410125d803da8dd69e3311732286d6a09c4e0 Mon Sep 17 00:00:00 2001
From: kracekumar 
Date: Wed, 9 May 2012 01:05:32 +0530
Subject: [PATCH 69/84] added an example get_each_args.py

---
 clint/textui/r.txt        |  1 +
 examples/args.py          |  3 ++-
 examples/get_each_args.py | 13 +++++++++++++
 examples/get_each_args.sh |  4 ++++
 4 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 clint/textui/r.txt
 create mode 100644 examples/get_each_args.py
 create mode 100755 examples/get_each_args.sh

diff --git a/clint/textui/r.txt b/clint/textui/r.txt
new file mode 100644
index 00000000..32f95c0d
--- /dev/null
+++ b/clint/textui/r.txt
@@ -0,0 +1 @@
+hi
\ No newline at end of file
diff --git a/examples/args.py b/examples/args.py
index 09301b3b..777aeda5 100644
--- a/examples/args.py
+++ b/examples/args.py
@@ -16,4 +16,5 @@
     puts(colored.red('NOT Files detected: ') + str(args.not_files))
     puts(colored.red('Grouped Arguments: ') + str(dict(args.grouped)))
     
-print
\ No newline at end of file
+print 
+
diff --git a/examples/get_each_args.py b/examples/get_each_args.py
new file mode 100644
index 00000000..b18c7adf
--- /dev/null
+++ b/examples/get_each_args.py
@@ -0,0 +1,13 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from clint import args
+from clint.textui import puts, colored
+
+all_args = args.grouped
+
+for item in all_args:
+    if item is not '_':
+        puts(colored.red("key:%s"%item))
+        print(all_args[item].all)
+
diff --git a/examples/get_each_args.sh b/examples/get_each_args.sh
new file mode 100755
index 00000000..0e940be0
--- /dev/null
+++ b/examples/get_each_args.sh
@@ -0,0 +1,4 @@
+echo "python get_each_args.py --name kracekumar --email me@kracekumar.com"
+python get_each_args.py --name kracekumar --email me@kracekumar.com
+echo "python get_each_args.py --languages python c html ruby  --email me@kracekumar.com"
+python get_each_args.py --langauges python c html ruby  --email me@kracekumar.com

From 911a84406ea4ece682cf4e2d004a69bc5a17f0ed Mon Sep 17 00:00:00 2001
From: kracekumar 
Date: Wed, 9 May 2012 01:06:03 +0530
Subject: [PATCH 70/84] added an example get_each_args.py

---
 clint/textui/r.txt | 1 -
 1 file changed, 1 deletion(-)
 delete mode 100644 clint/textui/r.txt

diff --git a/clint/textui/r.txt b/clint/textui/r.txt
deleted file mode 100644
index 32f95c0d..00000000
--- a/clint/textui/r.txt
+++ /dev/null
@@ -1 +0,0 @@
-hi
\ No newline at end of file

From 3e03a9ceb9bfad3eec21fcdb0a86e7fe6a826791 Mon Sep 17 00:00:00 2001
From: Johannes 
Date: Mon, 14 May 2012 12:43:19 +0200
Subject: [PATCH 71/84] Make prompt module accessible

---
 clint/textui/__init__.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clint/textui/__init__.py b/clint/textui/__init__.py
index 3b8c92a5..15e062dc 100644
--- a/clint/textui/__init__.py
+++ b/clint/textui/__init__.py
@@ -11,5 +11,6 @@
 
 from . import colored
 from . import progress
+from . import prompt
 
 from .core import *

From a1808173d96296029cef4bc6f1097d0d61a27bca Mon Sep 17 00:00:00 2001
From: Don Spaulding 
Date: Thu, 14 Jun 2012 12:23:05 -0500
Subject: [PATCH 72/84] Added an expected_size parameter to progress.bar and
 progress.mill.

Some objects you might want to show progress on while iterating over
do not support calling len().  In these cases you can now pass
`expected_size` in to the progress.bar and progress.mill functions
to avoid the len() call on the iterable.
---
 AUTHORS                  | 1 +
 clint/textui/progress.py | 8 ++++----
 examples/progressbar.py  | 7 ++++++-
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index d1fe5de8..04c62868 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -21,3 +21,4 @@ Patches and Suggestions
 - Alejandro Gómez 
 - Jason Piper 
 - Gianluca Brindisi 
+- Don Spaulding 
diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index bb7b0b83..b1369386 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -28,7 +28,7 @@
 #How many intervals (excluding the current one) to calculate the simple moving average
 ETA_SMA_WINDOW = 9
 
-def bar(it, label='', width=32, hide=False, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR):
+def bar(it, label='', width=32, hide=False, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR, expected_size=None):
     """Progress iterator. Wrap your iterables with it."""
 
     def _show(_i):
@@ -43,7 +43,7 @@ def _show(_i):
             label, filled_char*x, empty_char*(width-x), _i, count, bar.etadisp))
             STREAM.flush()
 
-    count = len(it)
+    count = len(it) if expected_size is None else expected_size
 
     bar.start    = time.time()
     bar.ittimes  = []
@@ -85,7 +85,7 @@ def dots(it, label='', hide=False):
     STREAM.flush()
 
 
-def mill(it, label='', hide=False,): 
+def mill(it, label='', hide=False, expected_size=None):
     """Progress iterator. Prints a mill while iterating over the items."""
 
     def _mill_char(_i):
@@ -100,7 +100,7 @@ def _show(_i):
                 label, _mill_char(_i), _i, count))
             STREAM.flush()
 
-    count = len(it)
+    count = len(it) if expected_size is None else expected_size
 
     if count:
         _show(0)
diff --git a/examples/progressbar.py b/examples/progressbar.py
index 951552ee..26030e46 100755
--- a/examples/progressbar.py
+++ b/examples/progressbar.py
@@ -17,6 +17,11 @@
 
     for i in progress.dots(range(100)):
         sleep(random() * 0.2)
-    
+
     for i in progress.mill(range(100)):
         sleep(random() * 0.2)
+
+    # Override the expected_size, for iterables that don't support len()
+    D = dict(zip(range(100), range(100)))
+    for k, v in progress.bar(D.iteritems(), expected_size=len(D)):
+        sleep(random() * 0.2)

From e7db8c7e377f3ec5844a43ca1faa383dd4f3e855 Mon Sep 17 00:00:00 2001
From: barberj 
Date: Wed, 1 Aug 2012 08:42:34 -0400
Subject: [PATCH 73/84] Updated to use arguments module.

Removed py25 support and tox testing since try/except statements were >=2.5.
Try setup import from setuptools so python setup.py develop is available.
---
 clint/__init__.py | 12 ++++++++----
 setup.py          |  6 ++++--
 tox.ini           |  3 ++-
 3 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/clint/__init__.py b/clint/__init__.py
index 609b9488..1f9b02d9 100644
--- a/clint/__init__.py
+++ b/clint/__init__.py
@@ -11,7 +11,14 @@
 
 from __future__ import absolute_import
 
-from . import arguments
+try:
+    from collections import OrderedDict
+except ImportError:
+    from .packages.ordereddict import OrderedDict
+    import collections
+    collections.OrderedDict = OrderedDict
+
+from args import *
 from . import textui
 from . import utils
 from .pipes import piped_in
@@ -25,6 +32,3 @@
 __license__ = 'ISC'
 __copyright__ = 'Copyright 2012 Kenneth Reitz'
 __docformat__ = 'restructuredtext'
-
-
-args = arguments.Args()
diff --git a/setup.py b/setup.py
index 78d9904b..ddc07538 100755
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,10 @@
 import os
 import sys
 
-from distutils.core import setup
+try:
+    from setuptools import setup
+except ImportError:
+    from distutils.core import setup
 
 import clint
 
@@ -48,7 +51,6 @@ def publish():
         'License :: OSI Approved :: ISC License (ISCL)',
         'Programming Language :: Python',
         'Programming Language :: Python :: 2',
-        'Programming Language :: Python :: 2.5',
         'Programming Language :: Python :: 2.6',
         'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3',
diff --git a/tox.ini b/tox.ini
index 82becb54..24c96a55 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,9 +1,10 @@
 [tox]
-envlist = py25,py26,py27,py3
+envlist = py26,py27,py3
 
 [testenv]
 commands=py.test --junitxml=junit-{envname}.xml
 deps = pytest
+    args
 
 [testenv:pypy]
 basepython=/usr/bin/pypy-c

From 70c0680b8c2e8c335765814cd2e3abb85c70f9e6 Mon Sep 17 00:00:00 2001
From: barberj 
Date: Wed, 1 Aug 2012 08:47:29 -0400
Subject: [PATCH 74/84] credit

---
 AUTHORS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/AUTHORS b/AUTHORS
index 04c62868..df01ef3d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,3 +22,4 @@ Patches and Suggestions
 - Jason Piper 
 - Gianluca Brindisi 
 - Don Spaulding 
+- Justin Barber 

From b591c3edc2185c5223f390c9a955e40890e0b6b7 Mon Sep 17 00:00:00 2001
From: barberj 
Date: Wed, 1 Aug 2012 08:49:48 -0400
Subject: [PATCH 75/84] forgot to include args dependency

---
 setup.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/setup.py b/setup.py
index ddc07538..5cd00a4f 100755
--- a/setup.py
+++ b/setup.py
@@ -21,7 +21,7 @@ def publish():
     publish()
     sys.exit()
 
-required = []
+required = ['args']
 
 setup(
     name='clint',

From fc841b0a61656804f0eb80f48ae9e3441168c1b0 Mon Sep 17 00:00:00 2001
From: barberj 
Date: Wed, 1 Aug 2012 09:15:58 -0400
Subject: [PATCH 76/84] consistency is key

---
 AUTHORS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/AUTHORS b/AUTHORS
index df01ef3d..b25d7e10 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,4 +22,4 @@ Patches and Suggestions
 - Jason Piper 
 - Gianluca Brindisi 
 - Don Spaulding 
-- Justin Barber 
+- Justin Barber 

From 8103032de8524f80a43376944a4345a197dca030 Mon Sep 17 00:00:00 2001
From: Jack Riches 
Date: Wed, 8 Aug 2012 15:01:06 +0100
Subject: [PATCH 77/84] Only write progress bars to terminal by default

This removes unwanted progress bar output when piping to another command
or file. Progress bars may be explicitly shown in this case with
progess.bar(iterable, hide=False)
---
 clint/textui/progress.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index b1369386..ad977331 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -14,6 +14,8 @@
 import time
 
 STREAM = sys.stderr
+# Only show bar in terminals by default (better for piping, logging etc.)
+HIDE_DEFAULT = False if STREAM.isatty() else True
 
 BAR_TEMPLATE = '%s[%s%s] %i/%i - %s\r'
 MILL_TEMPLATE = '%s %s %i/%i\r'  
@@ -28,7 +30,7 @@
 #How many intervals (excluding the current one) to calculate the simple moving average
 ETA_SMA_WINDOW = 9
 
-def bar(it, label='', width=32, hide=False, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR, expected_size=None):
+def bar(it, label='', width=32, hide=HIDE_DEFAULT, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR, expected_size=None):
     """Progress iterator. Wrap your iterables with it."""
 
     def _show(_i):
@@ -64,7 +66,7 @@ def _show(_i):
         STREAM.flush()
 
 
-def dots(it, label='', hide=False):
+def dots(it, label='', hide=HIDE_DEFAULT):
     """Progress iterator. Prints a dot for each item being iterated"""
 
     count = 0
@@ -85,7 +87,7 @@ def dots(it, label='', hide=False):
     STREAM.flush()
 
 
-def mill(it, label='', hide=False, expected_size=None):
+def mill(it, label='', hide=HIDE_DEFAULT, expected_size=None):
     """Progress iterator. Prints a mill while iterating over the items."""
 
     def _mill_char(_i):

From e1bdaa4d0d99fc6b53841bc0f075286351d60eb8 Mon Sep 17 00:00:00 2001
From: Jack Riches 
Date: Tue, 14 Aug 2012 09:47:34 +0100
Subject: [PATCH 78/84] More robust checking for if output is a tty

---
 clint/textui/progress.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/clint/textui/progress.py b/clint/textui/progress.py
index ad977331..1a110c94 100644
--- a/clint/textui/progress.py
+++ b/clint/textui/progress.py
@@ -15,7 +15,10 @@
 
 STREAM = sys.stderr
 # Only show bar in terminals by default (better for piping, logging etc.)
-HIDE_DEFAULT = False if STREAM.isatty() else True
+try:
+    HIDE_DEFAULT = not STREAM.isatty()
+except AttributeError:  # output does not support isatty()
+    HIDE_DEFAULT = True
 
 BAR_TEMPLATE = '%s[%s%s] %i/%i - %s\r'
 MILL_TEMPLATE = '%s %s %i/%i\r'  

From b69ceb18d2739379b69c52459147341501e45694 Mon Sep 17 00:00:00 2001
From: jczetta 
Date: Sat, 14 Jul 2012 16:26:30 -0400
Subject: [PATCH 79/84] redefined __getattr__ so all str methods work

All str methods work for ColoredStrings with expected functionality, excepting .join(). Retained some other method definitions in order to retain expected functionality. Added tests for ColoredString.
---
 clint/textui/colored.py | 14 +++++++++++---
 test_clint.py           | 26 ++++++++++++++++++++++++++
 2 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/clint/textui/colored.py b/clint/textui/colored.py
index 0906dde3..2c18b759 100644
--- a/clint/textui/colored.py
+++ b/clint/textui/colored.py
@@ -45,6 +45,17 @@ def __init__(self, color, s):
         self.s = s
         self.color = color
 
+    def __getattr__(self, att): 
+             def func_help(*args, **kwargs):
+                 result = getattr(self.s, att)(*args, **kwargs)
+                 if isinstance(result, basestring):
+                     return self._new(result)
+                 elif isinstance(result, list):
+                     return [self._new(x) for x in result]
+                 else:
+                     return result
+             return func_help
+       
     @property
     def color_str(self):
         if sys.stdout.isatty() and not DISABLE_COLOR:
@@ -84,9 +95,6 @@ def __radd__(self, other):
     def __mul__(self, other):
         return (self.color_str * other)
 
-    def split(self, sep=None):
-        return [self._new(s) for s in self.s.split(sep)]
-
     def _new(self, s):
         return ColoredString(self.color, s)
 
diff --git a/test_clint.py b/test_clint.py
index e9e0b9f0..5bdeda28 100755
--- a/test_clint.py
+++ b/test_clint.py
@@ -16,5 +16,31 @@ def setUp(self):
     def tearDown(self):
         pass
 
+class ColoredStringTestCase(unittest.TestCase):
+    
+    def setUp(self):
+        from clint.textui.colored import ColoredString
+    
+    def tearDown(self):
+        pass
+    
+    def test_split(self):
+        from clint.textui.colored import ColoredString
+        new_str = ColoredString('red', "hello world")
+        output = new_str.split()
+        assert output[0].s == "hello"
+    
+    def test_find(self):
+        from clint.textui.colored import ColoredString
+        new_str = ColoredString('blue', "hello world")
+        output = new_str.find('h')
+        self.assertEqual(output, 0)
+        
+    def test_replace(self):
+        from clint.textui.colored import ColoredString
+        new_str = ColoredString('green', "hello world")
+        output = new_str.replace("world", "universe")
+        assert output.s == "hello universe"
+
 if __name__ == '__main__':
     unittest.main()

From 0bd5026d216520712d6e2e7f07c5c3445139cdc3 Mon Sep 17 00:00:00 2001
From: Matthew Brandly 
Date: Sun, 9 Sep 2012 14:54:52 -0400
Subject: [PATCH 80/84] Fix minor spelling mistake

---
 clint/eng.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clint/eng.py b/clint/eng.py
index e903631b..ab49ee91 100644
--- a/clint/eng.py
+++ b/clint/eng.py
@@ -20,12 +20,12 @@
     unicode = str
 
 
-def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, seperator=COMMA):
+def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, separator=COMMA):
     """Joins lists of words. Oxford comma and all."""
 
     collector = []
     left = len(l)
-    seperator = seperator + SPACE
+    separator = separator + SPACE
     conj = conj + SPACE
 
     for _l in l[:]:
@@ -37,12 +37,12 @@ def join(l, conj=CONJUNCTION, im_a_moron=MORON_MODE, seperator=COMMA):
             if len(l) == 2 or im_a_moron:
                 collector.append(SPACE)
             else:
-                collector.append(seperator)
+                collector.append(separator)
 
             collector.append(conj)
 
         elif left is not 0:
-            collector.append(seperator)
+            collector.append(separator)
 
     return unicode(str().join(collector))
 

From 2c8561a492cb5ee9682632f4c5a35280c4635409 Mon Sep 17 00:00:00 2001
From: Adam Glenn 
Date: Mon, 10 Sep 2012 12:52:51 -0400
Subject: [PATCH 81/84] changed import args to import arguments

---
 clint/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clint/__init__.py b/clint/__init__.py
index 1f9b02d9..7e52439c 100644
--- a/clint/__init__.py
+++ b/clint/__init__.py
@@ -18,7 +18,7 @@
     import collections
     collections.OrderedDict = OrderedDict
 
-from args import *
+from arguments import *
 from . import textui
 from . import utils
 from .pipes import piped_in

From 464849e575c9103bbbd1b84431572adc656d7c63 Mon Sep 17 00:00:00 2001
From: Dmitry Medvinsky 
Date: Wed, 23 May 2012 13:52:20 +0400
Subject: [PATCH 82/84] Add textui streams to __all__

So that I could write

    from clint import textui as ui
    ui.puts(ui.colored.red('fatal error'), stream=ui.STDERR)
---
 AUTHORS              | 1 +
 clint/textui/core.py | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/AUTHORS b/AUTHORS
index b25d7e10..8a1b7410 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -23,3 +23,4 @@ Patches and Suggestions
 - Gianluca Brindisi 
 - Don Spaulding 
 - Justin Barber 
+- Dmitry Medvinsky
diff --git a/clint/textui/core.py b/clint/textui/core.py
index 6ddacc36..c435391e 100644
--- a/clint/textui/core.py
+++ b/clint/textui/core.py
@@ -21,7 +21,7 @@
 
 
 __all__ = ('puts', 'puts_err', 'indent', 'dedent', 'columns', 'max_width',
-    'min_width')
+    'min_width', 'STDOUT', 'STDERR')
 
 
 STDOUT = sys.stdout.write

From ab2f37219aa2daede6779417e97e0174f0b3fa70 Mon Sep 17 00:00:00 2001
From: anatoly techtonik 
Date: Wed, 7 Nov 2012 15:06:46 +0300
Subject: [PATCH 83/84] Fix image

---
 README.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.rst b/README.rst
index c3b00f13..b542b442 100644
--- a/README.rst
+++ b/README.rst
@@ -4,7 +4,7 @@ Clint: Python Command-line Application Tools
 **Clint** is a module filled with a set of awesome tools for developing
 commandline applications.
 
-.. image:: https://github.com/kennethreitz/clint/raw/master/misc/clint.jpeg
+.. image:: https://raw.github.com/kennethreitz/clint/develop/misc/clint.jpeg
 
 **C** ommand
 **L** ine

From 7b2130e58287d8d3eeea363226361332945e5e15 Mon Sep 17 00:00:00 2001
From: Steve Hill 
Date: Thu, 24 Jan 2013 19:50:08 -0800
Subject: [PATCH 84/84] Fix 404 to AUTHORS in README

---
 README.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.rst b/README.rst
index b542b442..2badfb9f 100644
--- a/README.rst
+++ b/README.rst
@@ -160,4 +160,4 @@ Roadmap
 
 
 .. _`the repository`: http://github.com/kennethreitz/clint
-.. _AUTHORS: http://github.com/kennethreitz/clint/blob/master/AUTHORS
+.. _AUTHORS: http://github.com/kennethreitz/clint/blob/develop/AUTHORS