39 Commits

Author SHA1 Message Date
Wladimir van der Laan 4a06f19e4f fix bug when using normal color syntax 2011-04-10 15:50:51 +02:00
Wladimir J. van der Laan a841043b56 RGB color support 2011-04-10 14:52:22 +02:00
star:Kenneth Reitz f651e71093 Merge branch 'develop' 2011-04-06 13:06:51 -04:00
star:Kenneth Reitz e500773da3 version bump (v0.2.3) 2011-04-06 13:06:14 -04:00
star:Kenneth Reitz 4b9e35c631 configurable progress interator streams 2011-04-06 13:02:40 -04:00
star:Kenneth Reitz e85fffdbb6 puts/puts_err fixes, defaults for string 2011-04-06 13:00:13 -04:00
star:Kenneth Reitz b58f8dccdc no colorama auto-init upon import 2011-04-06 10:08:25 -04:00
star:Kenneth Reitz 3d63ed01f9 whitespace cleanup 2011-04-03 08:11:23 -04:00
star:Kenneth Reitz 81165754a4 allow clint.textui.puts() to accept arbitrary file-like objects (like StringIO for <pre> generation) 2011-04-03 08:11:17 -04:00
star:Kenneth Reitz 6f106e2f12 toxic 2011-04-01 10:05:55 -04:00
star:Kenneth Reitz 8adda14a27 Merge branch 'feature/multiversion-testing' of https://github.com/offbyone/clint into develop 2011-04-01 10:04:28 -04:00
Chris Rose cc072a18f3 Add tox support 2011-04-01 07:58:48 -06:00
star:Kenneth Reitz c226b6b736 progress bar examples 2011-03-31 14:52:44 -04:00
Will Thames 3406ab5329 Added Will Thames to list of authors 2011-03-31 12:24:42 +01:00
Will Thames cf0c0bda70 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
2011-03-31 12:21:57 +01:00
star:Kenneth Reitz a4c2be8865 pre me right 2011-03-31 06:16:09 -04:00
star:Kenneth Reitz fa2bbf9a0d link to examples directory 2011-03-31 01:07:54 -04:00
star:Kenneth Reitz 9736b4cd71 oh yeah, columns. 2011-03-31 01:05:07 -04:00
star:Kenneth Reitz 2e68207d0a updated readme for newcomers 2011-03-31 00:48:02 -04:00
star:Kenneth Reitz 164d68ce37 loggin' 2011-03-30 23:08:33 -04:00
star:Kenneth Reitz aa5008b2e0 namespace fix 2011-03-30 23:03:39 -04:00
star:Kenneth Reitz 8b7161b15b Configurable progress bars :)
Argument changes.
2011-03-30 23:03:34 -04:00
star:Kenneth Reitz 763ca94e7b newline support for textui.puts 2011-03-30 23:03:13 -04:00
star:Kenneth Reitz 2d200e3709 progress.bar(width=), not size. 2011-03-30 22:53:36 -04:00
star:Kenneth Reitz d0f2375a7b No more '>' in progress bar 2011-03-30 22:51:49 -04:00
star:Kenneth Reitz 2369bc387d progressbar => bar 2011-03-30 22:47:33 -04:00
star:Kenneth Reitz f12e47fa7c add dots progress iterator 2011-03-30 22:47:18 -04:00
star:Kenneth Reitz 5d733d123d put progress uis in separate namespace (for now) 2011-03-30 22:46:57 -04:00
star:Kenneth Reitz 9e1ea1ef91 Automatically disable color 2011-03-30 22:41:40 -04:00
star:Kenneth Reitz 6d151a0794 mention examples. 2011-03-24 07:10:40 -04:00
star:Kenneth Reitz 13afb11dea Elaborate on what Clint IS. 2011-03-24 07:08:00 -04:00
star:Kenneth Reitz faeacbbfad Merge branch 'develop' 2011-03-24 05:11:47 -04:00
star:Kenneth Reitz 401344ff1e updated version info 2011-03-24 05:09:09 -04:00
star:Kenneth Reitz 598deda4d9 python 2.5 support! 2011-03-24 05:07:14 -04:00
star:Kenneth Reitz bf7b5d0930 2.5 with_statement support! 2011-03-24 05:06:23 -04:00
star:Kenneth Reitz 6404b0e49c no redundant versions 2011-03-24 03:42:20 -04:00
star:Kenneth Reitz b92f3204c9 version bump 2011-03-24 03:42:11 -04:00
star:Kenneth Reitz 61225d90e6 fix all colors example 2011-03-24 03:40:42 -04:00
star:Kenneth Reitz 3688a2a67b list of available colors 2011-03-24 03:40:37 -04:00
28 changed files with 702 additions and 85 deletions
+4 -1
View File
@@ -1,2 +1,5 @@
.idea
MANIFEST
MANIFEST
*.pyc
.tox
*~
+2 -1
View File
@@ -12,4 +12,5 @@ Patches and Suggestions
- Jeff Forcier
- Morgan Goose
- Travis Swicegood
- Travis Swicegood
- Will Thames
+24
View File
@@ -1,6 +1,30 @@
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
0.2.1 (2011-03-24)
++++++++++++++++++
* Python 2.5 Support
* List of available colors
0.2.0 (2011-03-23)
++++++++++++++++++
+30 -3
View File
@@ -12,16 +12,43 @@ commandline applications.
**T** ools
.
Features:
---------
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 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.
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.
.. _examples: https://github.com/kennethreitz/clint/tree/develop/examples
You'll never want to not use it.
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 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
-------
+2 -2
View File
@@ -19,8 +19,8 @@ from .pipes import piped_in
__title__ = 'clint'
__version__ = '0.2.0'
__build__ = 0x000200
__version__ = '0.2.3'
__build__ = 0x000203
__author__ = 'Kenneth Reitz'
__license__ = 'ISC'
__copyright__ = 'Copyright 2011 Kenneth Reitz'
+36 -24
View File
@@ -2,11 +2,13 @@
This module generates ANSI character codes to printing colors to terminals.
See: http://en.wikipedia.org/wiki/ANSI_escape_code
'''
from . import caps
CSI = '\033['
def code_to_chars(code):
return CSI + str(code) + 'm'
def code_to_chars(codes):
codes = [str(code) for code in codes]
return CSI + (";".join(codes)) + 'm'
class AnsiCodes(object):
def __init__(self, codes):
@@ -14,34 +16,44 @@ class AnsiCodes(object):
if not name.startswith('_'):
value = getattr(codes, name)
setattr(self, name, code_to_chars(value))
self._method = codes._caps_method
def __call__(self, code):
if isinstance(code, basestring):
return getattr(self, code)
else: # extended (pass to capability)
return code_to_chars(getattr(caps.capability, self._method)(code))
class AnsiFore:
BLACK = 30
RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37
RESET = 39
_caps_method = 'fg'
BLACK = (30,)
RED = (31,)
GREEN = (32,)
YELLOW = (33,)
BLUE = (34,)
MAGENTA = (35,)
CYAN = (36,)
WHITE = (37,)
RESET = (39,)
class AnsiBack:
BLACK = 40
RED = 41
GREEN = 42
YELLOW = 43
BLUE = 44
MAGENTA = 45
CYAN = 46
WHITE = 47
RESET = 49
_caps_method = 'bg'
BLACK = (40,)
RED = (41,)
GREEN = (42,)
YELLOW = (43,)
BLUE = (44,)
MAGENTA = (45,)
CYAN = (46,)
WHITE = (47,)
RESET = (49,)
class AnsiStyle:
BRIGHT = 1
DIM = 2
NORMAL = 22
RESET_ALL = 0
_caps_method = 'style'
BRIGHT = (1,)
DIM = (2,)
NORMAL = (22,)
RESET_ALL = (0,)
Fore = AnsiCodes( AnsiFore )
Back = AnsiCodes( AnsiBack )
+59
View File
@@ -0,0 +1,59 @@
from .conv import xterm256
from .conv import ansi
class _Base(object):
"""
Base 16-color ANSI.
All ANSI terminals as well as Windows support this.
"""
def fg(self, rgb):
(colid, bright) = ansi.from_rgb(rgb)
if bright:
return (1, 30 + colid)
else:
return (30 + colid,)
def bg(self, rgb):
(colid, bright) = ansi.from_rgb(rgb)
# Ignore brightness for background?
return (40 + colid)
def __str__():
return "BASE"
class _XTerm256(object):
"""
256-color terminal. Most modern terminal emulators support this.
Putty, Gnome Terminal, and even oldies like (m)rxvt, xterm.
"""
def fg(self, rgb):
return (38, 5, xterm256.from_rgb(rgb))
def bg(self, rgb):
return (48, 5, xterm256.from_rgb(rgb))
def __str__():
return "XTERM256"
class _RGB(object):
"""
Full 24-bit RGB support.
As far as I know, only Konsole can do this.
"""
def fg(self, rgb):
return (38, 2) + rgb
def bg(self, rgb):
return (48, 2) + rgb
def __str__():
return "RGB"
class ColorCapability:
ANSI = _Base() # Base 16-color ANSI support
XTERM256 = _XTerm256() # xterm256 (GNOME terminal / Putty)
RGB = _RGB() # Full RGB (Konsole)
# Current terminal caps, default to ANSI
capability = ColorCapability.ANSI
+69
View File
@@ -0,0 +1,69 @@
"""
ANSI 16-color conversion utilities.
"""
# Wladimir van der Laan, 2011
#
# The original ansi colors are defined as follows
#
# 0 black
# 1 red
# 2 green
# 3 brown (green+red)
# 4 blue
# 5 magenta (blue+red)
# 6 cyan (blue+green)
# 7 white
#
# However, the exact RGB mappings depend on the terminal that
# is used.
# In addition to these colors, nearly all terminals support 8
# colors that are simply brighter versions of the defined colors.
_colors = [
(0,0,0),
(128,0,0),
(0,128,0),
(128,128,0),
(0,0,128),
(128,0,128),
(0,128,128),
(192,192,192),
(128,128,128),
(255,0,0),
(0,255,0),
(255,255,0),
(0,0,255),
(255,0,255),
(0,255,255),
(255,255,255)
]
def to_rgb(color):
"""
Convert ANSI color tuple (color_id, bright) to RGB tuple.
Raise `ValueError` in case of invalid color spec.
"""
color = (color[1]<<3)|color[0]
try:
return _colors[color]
except IndexError:
raise ValueError("Color %i out of range" % color)
def from_rgb(rgb):
"""
Convert RGB tuple to ANSI color tuple (color_id, bright).
Raise `ValueError` in case of invalid color spec.
"""
min_d = 1000000
closest = None
for idx,col in enumerate(_colors):
dr = rgb[0]-col[0]
dg = rgb[1]-col[1]
db = rgb[2]-col[2]
d = dr*dr + dg*dg + db*db
if d < min_d:
min_d = d
closest = idx
return (closest&7, closest>>3)
+184
View File
@@ -0,0 +1,184 @@
"""
HTML color conversion utilities.
"""
# Wladimir van der Laan, 2011
colors = {
'aliceblue': '#F0F8FF',
'antiquewhite': '#FAEBD7',
'aqua': '#00FFFF',
'aquamarine': '#7FFFD4',
'azure': '#F0FFFF',
'beige': '#F5F5DC',
'bisque': '#FFE4C4',
'black': '#000000',
'blanchedalmond': '#FFEBCD',
'blue': '#0000FF',
'blueviolet': '#8A2BE2',
'brown': '#A52A2A',
'burlywood': '#DEB887',
'cadetblue': '#5F9EA0',
'chartreuse': '#7FFF00',
'chocolate': '#D2691E',
'coral': '#FF7F50',
'cornflowerblue': '#6495ED',
'cornsilk': '#FFF8DC',
'crimson': '#DC143C',
'cyan': '#00FFFF',
'darkblue': '#00008B',
'darkcyan': '#008B8B',
'darkgoldenrod': '#B8860B',
'darkgray': '#A9A9A9',
'darkgreen': '#006400',
'darkgrey': '#A9A9A9',
'darkkhaki': '#BDB76B',
'darkmagenta': '#8B008B',
'darkolivegreen': '#556B2F',
'darkorange': '#FF8C00',
'darkorchid': '#9932CC',
'darkred': '#8B0000',
'darksalmon': '#E9967A',
'darkseagreen': '#8FBC8F',
'darkslateblue': '#483D8B',
'darkslategray': '#2F4F4F',
'darkslategrey': '#2F4F4F',
'darkturquoise': '#00CED1',
'darkviolet': '#9400D3',
'deeppink': '#FF1493',
'deepskyblue': '#00BFFF',
'dimgray': '#696969',
'dimgrey': '#696969',
'dodgerblue': '#1E90FF',
'firebrick': '#B22222',
'floralwhite': '#FFFAF0',
'forestgreen': '#228B22',
'fuchsia': '#FF00FF',
'gainsboro': '#DCDCDC',
'ghostwhite': '#F8F8FF',
'gold': '#FFD700',
'goldenrod': '#DAA520',
'gray': '#808080',
'green': '#008000',
'greenyellow': '#ADFF2F',
'grey': '#808080',
'honeydew': '#F0FFF0',
'hotpink': '#FF69B4',
'indianred ': '#CD5C5C',
'indigo ': '#4B0082',
'ivory': '#FFFFF0',
'khaki': '#F0E68C',
'lavender': '#E6E6FA',
'lavenderblush': '#FFF0F5',
'lawngreen': '#7CFC00',
'lemonchiffon': '#FFFACD',
'lightblue': '#ADD8E6',
'lightcoral': '#F08080',
'lightcyan': '#E0FFFF',
'lightgoldenrodyellow': '#FAFAD2',
'lightgray': '#D3D3D3',
'lightgreen': '#90EE90',
'lightgrey': '#D3D3D3',
'lightpink': '#FFB6C1',
'lightsalmon': '#FFA07A',
'lightseagreen': '#20B2AA',
'lightskyblue': '#87CEFA',
'lightslategray': '#778899',
'lightslategrey': '#778899',
'lightsteelblue': '#B0C4DE',
'lightyellow': '#FFFFE0',
'lime': '#00FF00',
'limegreen': '#32CD32',
'linen': '#FAF0E6',
'magenta': '#FF00FF',
'maroon': '#800000',
'mediumaquamarine': '#66CDAA',
'mediumblue': '#0000CD',
'mediumorchid': '#BA55D3',
'mediumpurple': '#9370D8',
'mediumseagreen': '#3CB371',
'mediumslateblue': '#7B68EE',
'mediumspringgreen': '#00FA9A',
'mediumturquoise': '#48D1CC',
'mediumvioletred': '#C71585',
'midnightblue': '#191970',
'mintcream': '#F5FFFA',
'mistyrose': '#FFE4E1',
'moccasin': '#FFE4B5',
'navajowhite': '#FFDEAD',
'navy': '#000080',
'oldlace': '#FDF5E6',
'olive': '#808000',
'olivedrab': '#6B8E23',
'orange': '#FFA500',
'orangered': '#FF4500',
'orchid': '#DA70D6',
'palegoldenrod': '#EEE8AA',
'palegreen': '#98FB98',
'paleturquoise': '#AFEEEE',
'palevioletred': '#D87093',
'papayawhip': '#FFEFD5',
'peachpuff': '#FFDAB9',
'peru': '#CD853F',
'pink': '#FFC0CB',
'plum': '#DDA0DD',
'powderblue': '#B0E0E6',
'purple': '#800080',
'red': '#FF0000',
'rosybrown': '#BC8F8F',
'royalblue': '#4169E1',
'saddlebrown': '#8B4513',
'salmon': '#FA8072',
'sandybrown': '#F4A460',
'seagreen': '#2E8B57',
'seashell': '#FFF5EE',
'sienna': '#A0522D',
'silver': '#C0C0C0',
'skyblue': '#87CEEB',
'slateblue': '#6A5ACD',
'slategray': '#708090',
'slategrey': '#708090',
'snow': '#FFFAFA',
'springgreen': '#00FF7F',
'steelblue': '#4682B4',
'tan': '#D2B48C',
'teal': '#008080',
'thistle': '#D8BFD8',
'tomato': '#FF6347',
'turquoise': '#40E0D0',
'violet': '#EE82EE',
'wheat': '#F5DEB3',
'white': '#FFFFFF',
'whitesmoke': '#F5F5F5',
'yellow': '#FFFF00',
'yellowgreen': '#9ACD32'}
def to_rgb(color):
"""
Parse HTML color specification to RGB tuple.
Raise `ValueError` in case of invalid color spec.
"""
if color in colors:
color = colors[color]
if color.startswith("#"):
color = color[1:]
if len(color) == 6: #RRGGBB
rgb = (int(color[0:2],16),
int(color[2:4],16),
int(color[4:6],16))
elif len(color) == 3: #RGB
rgb = (int(color[0],16),
int(color[1],16),
int(color[2],16))
rgb = tuple([(x<<4)|x for x in rgb])
else:
raise ValueError("Invalid color %s" % color)
return rgb
def from_rgb(rgb):
"""
Convert RGB tuple to HTML color specification.
"""
return "#%02x%02x%02x" % rgb
+115
View File
@@ -0,0 +1,115 @@
"""
256-color xterm conversion utilities.
"""
# Wladimir van der Laan, 2011
# whole colortable, filled in later
colortable = None
# the 6 value iterations in the xterm color cube
valuerange = [ 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF ]
# 16 basic ANSI colors + lighter variants
# these can be different depending on the terminal settings,
# so do not use them when converting from RGB.
basic16 = [
[ 0x00, 0x00, 0x00 ], # 0
[ 0xCD, 0x00, 0x00 ], # 1
[ 0x00, 0xCD, 0x00 ], # 2
[ 0xCD, 0xCD, 0x00 ], # 3
[ 0x00, 0x00, 0xEE ], # 4
[ 0xCD, 0x00, 0xCD ], # 5
[ 0x00, 0xCD, 0xCD ], # 6
[ 0xE5, 0xE5, 0xE5 ], # 7
[ 0x7F, 0x7F, 0x7F ], # 8
[ 0xFF, 0x00, 0x00 ], # 9
[ 0x00, 0xFF, 0x00 ], # 10
[ 0xFF, 0xFF, 0x00 ], # 11
[ 0x5C, 0x5C, 0xFF ], # 12
[ 0xFF, 0x00, 0xFF ], # 13
[ 0x00, 0xFF, 0xFF ], # 14
[ 0xFF, 0xFF, 0xFF ] # 15
]
# Closest color on RGB color cube (from valuerange)
closest6 = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
def _color_dist(c, rgb):
"""
Return squared Euclidian distance of rgb to color `c`
in the color table.
"""
d0 = colortable[c][0] - rgb[0]
d1 = colortable[c][1] - rgb[1]
d2 = colortable[c][2] - rgb[2]
return d0*d0 + d1*d1 + d2*d2
def to_rgb(color):
"""
Convert a xterm256 color value (0-255) to 3 unsigned chars RGB
tuple.
"""
rgb = [0,0,0]
if color < 16:
# 16 basic colors
rgb[0] = basic16[color][0]
rgb[1] = basic16[color][1]
rgb[2] = basic16[color][2]
elif color >= 16 and color <= 231:
# color cube color
color -= 16
rgb[0] = valuerange[(color/36)%6]
rgb[1] = valuerange[(color/6)%6]
rgb[2] = valuerange[color%6]
elif color >= 232 and color <= 255:
# gray tone
rgb[0] = rgb[1] = rgb[2] = 8+(color-232)*0x0a
return rgb
def from_rgb(rgb):
"""
Convert RGB tuple to xterm256 color value (0-255).
"""
# Optimized algorithm to find the xterm256 color with Euclidian closest distance to a
# provided RGB value: as the palette consists of an independent 6x6x6 RGB cube
# and a 24 grey tone scale, determine the closest color in both palettes, then
# from these two return the on that's closest to the requested RGB color.
# Compute closest color on 6x6x6 RGB cube
r = [closest6[x] for x in rgb]
b = 16 + r[0]*36 + r[1]*6 + r[2]
# Compute closest point on greyscale line
greyscale = sum(rgb)
r = (greyscale-9) / 30
c = 232 + max(min(r,23),0)
# Return RGB cube or greyscale color depending
# on which is closest.
distb = _color_dist(b, rgb)
distc = _color_dist(c, rgb)
if distb <= distc:
color = b
else:
color = c
return color
colortable = [to_rgb(c) for c in xrange(0, 256)]
+1
View File
@@ -9,6 +9,7 @@ This module contains the helper functions for dealing with unix pipes.
"""
from __future__ import absolute_import
from __future__ import with_statement
import sys
+9 -8
View File
@@ -10,6 +10,7 @@ This module contains all the application resource features of clint.
from __future__ import absolute_import
from __future__ import with_statement
import errno
from os import remove, removedirs
@@ -38,7 +39,7 @@ class AppDir(object):
def __repr__(self):
return '<app-dir: %s>' % (self.path)
def __getattribute__(self, name):
@@ -52,11 +53,11 @@ class AppDir(object):
"""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)
@@ -65,7 +66,7 @@ class AppDir(object):
def open(self, filename, mode='r'):
"""Returns file object from given filename."""
self._raise_if_none()
fn = path_join(self.path, filename)
@@ -120,11 +121,11 @@ class AppDir(object):
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)
@@ -160,11 +161,11 @@ log = AppDir()
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
+3 -3
View File
@@ -8,8 +8,8 @@ This module provides the text output helper system.
"""
from __future__ import absolute_import
from . import colored
from .core import *
from . import progress
from core import *
+35 -15
View File
@@ -15,12 +15,7 @@ import re
import sys
from ..packages import colorama
DISABLE_COLOR = False
if sys.stdout.isatty():
colorama.init(autoreset=True)
from ..packages.colorama.conv import html
__all__ = (
'red', 'green', 'yellow', 'blue',
@@ -28,6 +23,12 @@ __all__ = (
'clean', 'disable'
)
COLORS = __all__[:-2]
DISABLE_COLOR = False
if not sys.stdout.isatty():
DISABLE_COLOR = True
class ColoredString(object):
"""Enhanced string for __len__ operations on Colored output."""
@@ -39,33 +40,34 @@ class ColoredString(object):
@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)
colorama.Fore(self.color), self.s, colorama.Fore.RESET)
else:
return self.s
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))
@@ -77,7 +79,7 @@ def clean(s):
strip = re.compile("([^-_a-zA-Z0-9!@#%&=,/'\";:~`\$\^\*\(\)\+\[\]\.\{\}\|\?\<\>\\]+|[^\s]+)")
txt = strip.sub('', str(s))
strip = re.compile(r'\[\d+m')
strip = re.compile(r'\[[\d;]+m')
txt = strip.sub('', txt)
return txt
@@ -107,6 +109,24 @@ def cyan(string):
def white(string):
return ColoredString('WHITE', string)
def rgb(color, string):
"""
RGB-colored text.
The `color` argument can have the following formats:
- #3f3f3f
- 3f3f3f
- ('3f', '3f', '3f')
- (100, 24, 244)
"""
if isinstance(color, basestring):
color = html.to_rgb(color)
else:
if isinstance(color[0], basestring):
color = (int(color[0],16), int(color[1],16), int(color[2],16))
return ColoredString(color, string)
def disable():
"""Disables colors."""
global DISABLE_COLOR
+1
View File
@@ -94,6 +94,7 @@ def columns(*cols, **kwargs):
cols[_big_col][1] = (cwidth - _total_cols) - len(cols)
cols[_big_col][0] = max_width(cols[_big_col][0], cols[_big_col][1]).split('\n')
height = len(max([c[0] for c in cols], key=len))
for i, (strings, width) in enumerate(cols):
+8 -9
View File
@@ -13,13 +13,12 @@ from __future__ import absolute_import
import sys
from .progress import progressbar
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', 'columns', 'max_width', 'min_width')
STDOUT = sys.stdout.write
@@ -63,14 +62,14 @@ class Writer(object):
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),
@@ -79,14 +78,14 @@ class Writer(object):
stream(_str)
def puts(s, newline=True):
def puts(s='', newline=True, stream=STDOUT):
"""Prints given string to stdout via Writer interface."""
Writer()(s, stream=STDOUT)
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=''):
+46 -10
View File
@@ -12,21 +12,57 @@ from __future__ import absolute_import
import sys
STREAM = sys.stderr
def progressbar(it, prefix='', size=32, hide=False):
BAR_TEMPLATE = '%s[%s%s] %i/%i\r'
BAR_EMPTY_CHAR = '-'
BAR_FILLED_CHAR = '='
DOTS_CHAR = '.'
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(size*_i/count)
if not hide:
sys.stdout.write("%s[%s>%s] %i/%i\r" % (prefix, "="*x, "-"*(size-x), _i, count))
sys.stdout.flush()
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:
_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 = 0
if not hide:
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()
+2 -1
View File
@@ -9,6 +9,7 @@ Various Python helpers used within clint.
"""
from __future__ import absolute_import
from __future__ import with_statement
import sys
import errno
@@ -28,7 +29,7 @@ def mkdir_p(path):
"""Emulates `mkdir -p` behavior."""
try:
makedirs(path)
except OSError as exc: # Python >2.5
except OSError, exc: # Python >2.5
if exc.errno == errno.EEXIST:
pass
else:
+1 -1
View File
@@ -12,5 +12,5 @@ text = 'THIS TEXT IS COLORED %s!'
if __name__ == '__main__':
for color in colored.__all__:
for color in colored.COLORS:
print getattr(colored, color)(text % color.upper())
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
sys.path.insert(0, os.path.abspath('..'))
from clint.textui import colored
from clint.packages.colorama.conv import html
from clint.packages.colorama import caps
from clint.textui import columns
# Force capability to XTERM256 for now, otherwise it's boring
# I'm not sure a reliable detection mechanism even exists...
caps.capability = caps.ColorCapability.XTERM256
def colorizer(colors):
for color in colors:
yield colored.rgb(color, color)
if __name__ == '__main__':
i = iter(colorizer(html.colors))
while True:
try:
a = i.next()
except StopIteration:
break
try:
b = i.next()
except StopIteration:
b = ""
try:
c = i.next()
except StopIteration:
c = ""
print columns([a,30],[b,30],[c,30])
+3
View File
@@ -1,6 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
import sys
import os
+2
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
import sys
import os
+2
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
import sys
import os
+3 -1
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
import sys
import os
@@ -21,4 +23,4 @@ if __name__ == '__main__':
with indent(5, quote=colored.red(' |')):
puts(in_data)
else:
puts(colored.red('Warning: ') + 'No data was piped in.')
puts(colored.red('Warning: ') + 'No data was piped in.')
+4 -3
View File
@@ -8,12 +8,13 @@ sys.path.insert(0, os.path.abspath('..'))
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)
+5 -3
View File
@@ -6,6 +6,9 @@ import sys
from distutils.core import setup
import clint
def publish():
"""Publish to PyPi"""
@@ -19,7 +22,7 @@ required = []
setup(
name='clint',
version='0.2.0',
version=clint.__version__,
description='Python Command-line Application Tools',
long_description=open('README.rst').read() + '\n\n' +
open('HISTORY.rst').read(),
@@ -29,7 +32,6 @@ setup(
packages= [
'clint',
'clint.textui',
'clint.packages', 'clint.packages.colorama'
],
install_requires=required,
@@ -40,7 +42,7 @@ setup(
'Natural Language :: English',
'License :: OSI Approved :: ISC License (ISCL)',
'Programming Language :: Python',
# 'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
# 'Programming Language :: Python :: 3.0',
+12
View File
@@ -0,0 +1,12 @@
[tox]
envlist = py25,py26,py27,py3
[testenv]
commands=py.test --junitxml=junit-{envname}.xml
deps = pytest
[testenv:pypy]
basepython=/usr/bin/pypy-c
[testenv:py3]
basepython=/usr/bin/python3