mirror of
https://github.com/not-kennethreitz/click-tools.git
synced 2026-06-05 07:06:13 +00:00
@@ -2,5 +2,6 @@ from . import eng
|
||||
from . import pipes
|
||||
from . import resources
|
||||
from . import utils
|
||||
from . import text
|
||||
|
||||
import crayons
|
||||
@@ -0,0 +1,132 @@
|
||||
# -*- 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
|
||||
|
||||
cols = [list(c) for c in cols]
|
||||
|
||||
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)
|
||||
|
||||
|
||||
|
||||
return '\n'.join(_out)
|
||||
|
||||
|
||||
|
||||
###########################
|
||||
if __name__ == '__main__':
|
||||
a = 'this is text that goes into a small column\n cool?'
|
||||
b = 'this is other text\nothertext\nothertext'
|
||||
|
||||
print(columns((a, 10), (b, 20), (b, None)))
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
clint.textui.formatters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Core TextUI functionality for text formatting.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from crayons 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
|
||||
:param string: string to be formatted
|
||||
:type string: basestring or clint.textui.colored.ColoredString
|
||||
:param cols: max width the text to be formatted
|
||||
:type cols: int
|
||||
:param separator: separator to break rows
|
||||
:type separator: basestring
|
||||
|
||||
>>> formatters.max_width('123 5678', 8)
|
||||
'123 5678'
|
||||
>>> formatters.max_width('123 5678', 7)
|
||||
'123 \n5678'
|
||||
|
||||
"""
|
||||
|
||||
is_color = isinstance(string, ColoredString)
|
||||
|
||||
if is_color:
|
||||
string_copy = string._new('')
|
||||
string = string.s
|
||||
|
||||
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:
|
||||
_row[_row_i] += word
|
||||
_row[_row_i] += ' '
|
||||
|
||||
elif len(word) > cols:
|
||||
|
||||
# ensure empty row
|
||||
if len(_row[_row_i]):
|
||||
_row[_row_i] = _row[_row_i].rstrip()
|
||||
_row.append('')
|
||||
_row_i += 1
|
||||
|
||||
chunks = schunk(word, cols)
|
||||
for i, chunk in enumerate(chunks):
|
||||
if not (i + 1) == len(chunks):
|
||||
_row[_row_i] += chunk
|
||||
_row[_row_i] = _row[_row_i].rstrip()
|
||||
_row.append('')
|
||||
_row_i += 1
|
||||
else:
|
||||
_row[_row_i] += chunk
|
||||
_row[_row_i] += ' '
|
||||
else:
|
||||
_row[_row_i] = _row[_row_i].rstrip()
|
||||
_row.append('')
|
||||
_row_i += 1
|
||||
_row[_row_i] += word
|
||||
_row[_row_i] += ' '
|
||||
else:
|
||||
_row[_row_i] = _row[_row_i].rstrip()
|
||||
|
||||
_row = map(str, _row)
|
||||
_stack.append(separator.join(_row))
|
||||
|
||||
_s = '\n'.join(_stack)
|
||||
if is_color:
|
||||
_s = string_copy._new(_s)
|
||||
return _s
|
||||
+1
-1
@@ -6,7 +6,7 @@ from contextlib import contextmanager
|
||||
|
||||
from .formatters import max_width, min_width
|
||||
from .cols import columns
|
||||
from ..utils import tsplit
|
||||
from .utils import tsplit
|
||||
|
||||
|
||||
__all__ = (
|
||||
|
||||
Reference in New Issue
Block a user