30 Commits

Author SHA1 Message Date
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
star:Kenneth Reitz dda561387c RELASE v0.2.0 2011-03-23 08:52:41 -04:00
star:Kenneth Reitz 06af338874 back to regular adding (thanks to clean()) 2011-03-23 08:43:57 -04:00
star:Kenneth Reitz 9b91cf16b5 v0.2.0 2011-03-23 06:45:01 -04:00
star:Kenneth Reitz ec8fe4a0b7 Added appdirs license 2011-03-23 06:44:56 -04:00
star:Kenneth Reitz dc6a9c63ea prepping for 0.2.0 release 2011-03-23 06:40:38 -04:00
star:Kenneth Reitz 82d31e555f Merge branch 'feature/widths' 2011-03-23 06:35:33 -04:00
star:Kenneth Reitz 2f6e9cbfaa added args.starts_with for flag catcher 2011-03-22 14:07:34 -04:00
star:Kenneth Reitz b576ccbaae disable colors, clean available externally. 2011-03-22 13:56:23 -04:00
star:Kenneth Reitz 8e021f95e9 join returns colored string (for now) 2011-03-22 13:33:56 -04:00
star:Kenneth Reitz 83bf2288dd text_width example 2011-03-22 08:44:00 -04:00
star:Kenneth Reitz f2fc21755b COLUMNS! 2011-03-22 08:03:35 -04:00
star:Kenneth Reitz 52488ace36 ColoredString support for width formatters 2011-03-22 08:03:24 -04:00
star:Kenneth Reitz 8b6eb543b9 textui.clean for stripping colored cli output 2011-03-22 08:02:36 -04:00
star:Kenneth Reitz 2cd9bd5263 min/max widths in textui core
configurable newlines
2011-03-22 04:36:06 -04:00
star:Kenneth Reitz 76bee9c4ba max_width in place. 2011-03-22 04:35:38 -04:00
star:Kenneth Reitz 14c4cdf904 Added utils.schunk() for bytes chunking 2011-03-22 04:18:25 -04:00
star:Kenneth Reitz f6a20fc413 test commit 2011-03-22 03:11:18 -04:00
Kenneth Reitz fc3eeca54f :octocat: says: 'the 🍰 is a lie!' 2011-03-22 03:05:04 -04:00
Kenneth Reitz ebdb04848a fix for found arg at pos 0 2011-03-22 01:17:16 -04:00
Kenneth Reitz f0206b21fc fix for found arg at pos 0 2011-03-22 01:02:07 -04:00
Kenneth Reitz 5366c7e5b2 not_files should return Args object. 2011-03-21 23:53:16 -04:00
Kenneth Reitz 35ec821e37 case typo 2011-03-21 22:36:34 -04:00
21 changed files with 434 additions and 46 deletions
+24 -4
View File
@@ -1,10 +1,28 @@
History
-------
0.1.0 (2011-03-20)
0.2.1 (2011-03-24)
++++++++++++++++++
* Initial Release!
* Python 2.5 Support
* List of available colors
0.2.0 (2011-03-23)
++++++++++++++++++
* Column Printing!!!
* (Auto/Manual) Disabling of Colors
* Smarter Colors
* max_width, min_width
* Strip cli colors
* bug fixes
0.1.2 (2011-03-21)
++++++++++++++++++
* Bugfixes
0.1.1 (2011-03-20)
@@ -16,7 +34,9 @@ History
* Lots of Examples
0.1.2 (2011-03-21)
0.1.0 (2011-03-20)
++++++++++++++++++
* Bugfixes
* Initial Release!
+1 -1
View File
@@ -1 +1 @@
include HISTORY.rst README.rst LICENSE AUTHORS NOTICE
include HISTORY.rst README.rst LICENSE AUTHORS NOTICE
+28 -1
View File
@@ -1,4 +1,4 @@
Clint includes some vendorized python libraries: appdirs, colorama, ordereddict.
Clint includes some vendorized python libraries: appdirs, applib, colorama, ordereddict.
AppDirs License
===============
@@ -25,6 +25,33 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
AppLib License (console width detection functions are from this library)
==============
# This is the MIT license
# Copyright (c) 2010 ActiveState Software Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Colorama License
================
+2 -2
View File
@@ -19,8 +19,8 @@ from .pipes import piped_in
__title__ = 'clint'
__version__ = '0.1.2'
__build__ = 0x000102
__version__ = '0.2.1'
__build__ = 0x000201
__author__ = 'Kenneth Reitz'
__license__ = 'ISC'
__copyright__ = 'Copyright 2011 Kenneth Reitz'
+33 -14
View File
@@ -25,19 +25,19 @@ __all__ = ('Args', )
def _expand_path(path):
"""Expands directories and globs in given path."""
"""Expands directories and globs in given path."""
paths = []
paths = []
if os.path.isdir(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))
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
return paths
class Args(object):
@@ -69,7 +69,7 @@ class Args(object):
def __contains__(self, x):
return bool(self.first(x))
return self.first(x) is not None
def get(self, x):
@@ -90,7 +90,7 @@ class Args(object):
def _remove(x):
found = self.first(x)
if found:
if found is not None:
self._args.pop(found)
if is_collection(x):
@@ -133,7 +133,7 @@ class Args(object):
if is_collection(x):
for item in x:
found = _find(item)
if found:
if found is not None:
return found
return None
else:
@@ -181,6 +181,25 @@ class Args(object):
else:
return _find(x)
def start_with(self, x):
"""Returns all arguments beginning with given string (or list thereof)"""
_args = []
for arg in self.all:
if is_collection(x):
for _x in x:
if arg.startswith(x):
_args.append(arg)
break
else:
if arg.startswith(x):
_args.append(arg)
return Args(_args, no_argv=True)
def contains_at(self, x, index):
"""Tests if given [list of] string is at given index."""
@@ -305,7 +324,7 @@ class Args(object):
def flags(self):
"""Returns Arg object including only flagged arguments."""
return self.all_with('-')
return self.start_with('-')
@property
@@ -343,7 +362,7 @@ class Args(object):
if not os.path.exists(arg):
_args.append(arg)
return _args
return Args(_args, no_argv=True)
@property
def copy(self):
+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
+1
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
+1 -3
View File
@@ -8,8 +8,6 @@ This module provides the text output helper system.
"""
from __future__ import absolute_import
from . import colored
from .core import *
from core import *
+40 -10
View File
@@ -11,18 +11,23 @@ This module provides a simple and elegant wrapper for colorama.
from __future__ import absolute_import
import re
import sys
from ..packages import colorama
colorama.init(autoreset=True)
__all__ = (
'red', 'green', 'yellow', 'blue',
'black', 'magenta', 'cyan', 'white'
'black', 'magenta', 'cyan', 'white',
'clean', 'disable'
)
COLORS = __all__[:-2]
DISABLE_COLOR = False
if sys.stdout.isatty():
colorama.init(autoreset=True)
class ColoredString(object):
"""Enhanced string for __len__ operations on Colored output."""
@@ -30,9 +35,16 @@ class ColoredString(object):
super(ColoredString, self).__init__()
self.s = s
self.color = color
self.color_str = '%s%s%s' % (
getattr(colorama.Fore, self.color), self.s, colorama.Fore.RESET)
@property
def color_str(self):
if sys.stdout.isatty() and not DISABLE_COLOR:
return '%s%s%s' % (
getattr(colorama.Fore, self.color), self.s, colorama.Fore.RESET)
else:
return self.s
def __len__(self):
return len(self.s)
@@ -55,8 +67,20 @@ class ColoredString(object):
return (self.color_str * other)
def split(self, x=' '):
return self.color_str.split(x)
return map(self._new, self.s.split(x))
def _new(self, s):
return ColoredString(self.color, s)
def clean(s):
strip = re.compile("([^-_a-zA-Z0-9!@#%&=,/'\";:~`\$\^\*\(\)\+\[\]\.\{\}\|\?\<\>\\]+|[^\s]+)")
txt = strip.sub('', str(s))
strip = re.compile(r'\[\d+m')
txt = strip.sub('', txt)
return txt
def black(string):
@@ -82,3 +106,9 @@ def cyan(string):
def white(string):
return ColoredString('WHITE', string)
def disable():
"""Disables colors."""
global DISABLE_COLOR
DISABLE_COLOR = True
+141
View File
@@ -0,0 +1,141 @@
# -*- coding: utf-8 -*-
"""
clint.textui.columns
~~~~~~~~~~~~~~~~~~~~
Core TextUI functionality for column formatting.
"""
from __future__ import absolute_import
from .formatters import max_width, min_width
from ..utils import tsplit
import sys
NEWLINES = ('\n', '\r', '\r\n')
def _find_unix_console_width():
import termios, fcntl, struct, sys
# fcntl.ioctl will fail if stdout is not a tty
if not sys.stdout.isatty():
return None
s = struct.pack("HHHH", 0, 0, 0, 0)
fd_stdout = sys.stdout.fileno()
size = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s)
height, width = struct.unpack("HHHH", size)[:2]
return width
def _find_windows_console_width():
# http://code.activestate.com/recipes/440694/
from ctypes import windll, create_string_buffer
STDIN, STDOUT, STDERR = -10, -11, -12
h = windll.kernel32.GetStdHandle(STDERR)
csbi = create_string_buffer(22)
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
if res:
import struct
(bufx, bufy, curx, cury, wattr,
left, top, right, bottom,
maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
sizex = right - left + 1
sizey = bottom - top + 1
return sizex
def console_width(kwargs):
""""Determine console_width."""
if sys.platform.startswith('win'):
console_width = _find_windows_console_width()
else:
console_width = _find_unix_console_width()
_width = kwargs.get('width', None)
if _width:
console_width = _width
else:
if not console_width:
console_width = 80
return console_width
def columns(*cols, **kwargs):
columns = list(cols)
cwidth = console_width(kwargs)
_big_col = None
_total_cols = 0
for i, (string, width) in enumerate(cols):
if width is not None:
_total_cols += (width + 1)
cols[i][0] = max_width(string, width).split('\n')
else:
_big_col = i
if _big_col:
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):
for _ in range(height - len(strings)):
cols[i][0].append('')
for j, string in enumerate(strings):
cols[i][0][j] = min_width(string, width)
stack = [c[0] for c in cols]
_out = []
for i in range(height):
_row = ''
for col in stack:
_row += col[i]
_row += ' '
_out.append(_row)
# try:
# pass
# except:
# pass
return '\n'.join(_out)
# string = max_width(string, width)
# string = min_width(string, width)
# pass
# columns.append()
###########################
a = 'this is text that goes into a small column\n cool?'
b = 'this is other text\nothertext\nothertext'
#columns((a, 10), (b, 20), (b, None))
+9 -3
View File
@@ -14,15 +14,20 @@ 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')
__all__ = ('puts', 'puts_err', 'indent', 'progressbar', 'columns', 'max_width', 'min_width')
STDOUT = sys.stdout.write
STDERR = sys.stderr.write
NEWLINES = ('\n', '\r', '\r\n')
class Writer(object):
"""WriterUtilized by context managers."""
@@ -60,10 +65,11 @@ class Writer(object):
def __call__(self, s, newline=True, stream=STDOUT):
if newline:
s = tsplit(s, ('\n', '\r', '\r\n'))
s = tsplit(s, NEWLINES)
s = map(str, s)
indent = ''.join(self.shared['indent_strings'])
s = ('\n' + indent).join(s)
s = (str('\n' + indent)).join(s)
_str = ''.join((
''.join(self.shared['indent_strings']),
+91
View File
@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
"""
clint.textui.formatters
~~~~~~~~~~~~~~~~~~~~~~~
Core TextUI functionality for text formatting.
"""
from __future__ import absolute_import
from .colored import ColoredString, clean
from ..utils import tsplit, schunk
NEWLINES = ('\n', '\r', '\r\n')
def min_width(string, cols, padding=' '):
"""Returns given string with right padding."""
is_color = isinstance(string, ColoredString)
stack = tsplit(str(string), NEWLINES)
for i, substring in enumerate(stack):
_sub = clean(substring).ljust((cols + 0), padding)
if is_color:
_sub = (_sub.replace(clean(substring), substring))
stack[i] = _sub
return '\n'.join(stack)
def max_width(string, cols, separator='\n'):
"""Returns a freshly formatted """
is_color = isinstance(string, ColoredString)
if is_color:
offset = 10
string_copy = string._new('')
else:
offset = 0
stack = tsplit(string, NEWLINES)
for i, substring in enumerate(stack):
stack[i] = substring.split()
_stack = []
for row in stack:
_row = ['',]
_row_i = 0
for word in row:
if (len(_row[_row_i]) + len(word)) < (cols + offset):
_row[_row_i] += word
_row[_row_i] += ' '
elif len(word) > (cols - offset):
# ensure empty row
if len(_row[_row_i]):
_row.append('')
_row_i += 1
chunks = schunk(word, (cols + offset))
for i, chunk in enumerate(chunks):
if not (i + 1) == len(chunks):
_row[_row_i] += chunk
_row.append('')
_row_i += 1
else:
_row[_row_i] += chunk
_row[_row_i] += ' '
else:
_row.append('')
_row_i += 1
_row[_row_i] += word
_row[_row_i] += ' '
_row = map(str, _row)
_stack.append(separator.join(_row))
_s = '\n'.join(_stack)
if is_color:
_s = string_copy._new(_s)
return _s
+23 -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:
@@ -49,3 +50,24 @@ def tsplit(string, delimiters):
return stack
def schunk(string, size):
"""Splits string into n sized chunks."""
stack = []
substack = []
current_count = 0
for char in string:
if not current_count < size:
stack.append(''.join(substack))
substack = []
current_count = 0
substack.append(char)
current_count += 1
if len(substack):
stack.append(''.join(substack))
return stack
+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())
+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
+2
View File
@@ -4,6 +4,8 @@
import sys
import os
from __future__ import with_statement
sys.path.insert(0, os.path.abspath('..'))
from clint import piped_in
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
sys.path.insert(0, os.path.abspath('..'))
from clint.textui import puts, colored
from clint.textui import columns
lorem = 'Lorem ipsum dolor sit amet, consehdfhdfhdfhdfhdfhctetur adi pisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 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.'
if __name__ == '__main__':
# puts(min_width('test\nit', 20) + ' me')
# puts(max_width(lorem, 20) + ' me')
# print max_width(lorem, 45)
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]))
+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.1.2',
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',
+1 -3
View File
@@ -6,7 +6,7 @@
import unittest
class TablibTestCase(unittest.TestCas):
class TablibTestCase(unittest.TestCase):
"""Tablib test cases."""
def setUp(self):
@@ -16,7 +16,5 @@ class TablibTestCase(unittest.TestCas):
def tearDown(self):
pass
if __name__ == '__main__':
unittest.main()