192 lines
6.2 KiB
Python
192 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
This module is just a collection of simple helper functions.
|
|
"""
|
|
from __future__ import division
|
|
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
from __future__ import unicode_literals
|
|
from builtins import str
|
|
from datetime import date, datetime
|
|
from logging import getLogger
|
|
|
|
from asciimatics.constants import SINGLE_LINE, DOUBLE_LINE
|
|
|
|
|
|
# Diagnostic logging
|
|
logger = getLogger(__name__)
|
|
|
|
|
|
def readable_mem(mem):
|
|
"""
|
|
:param mem: An integer number of bytes to convert to human-readable form.
|
|
:return: A human-readable string representation of the number.
|
|
"""
|
|
for suffix in ["", "K", "M", "G", "T"]:
|
|
if mem < 10000:
|
|
return "{}{}".format(int(mem), suffix)
|
|
mem /= 1024
|
|
return "{}P".format(int(mem))
|
|
|
|
|
|
def readable_timestamp(stamp):
|
|
"""
|
|
:param stamp: A floating point number representing the POSIX file timestamp.
|
|
:return: A short human-readable string representation of the timestamp.
|
|
"""
|
|
if date.fromtimestamp(stamp) == date.today():
|
|
return str(datetime.fromtimestamp(stamp).strftime("%I:%M:%S%p"))
|
|
else:
|
|
return str(date.fromtimestamp(stamp))
|
|
|
|
|
|
class _DotDict(dict):
|
|
"""
|
|
Modified dictionary to allow dot notation access.
|
|
|
|
This can be used for quick and easy structures. See https://stackoverflow.com/q/2352181/4994021
|
|
"""
|
|
|
|
__getattr__ = dict.get
|
|
__setattr__ = dict.__setitem__
|
|
__delattr__ = dict.__delitem__
|
|
|
|
|
|
class BoxTool(object):
|
|
"""
|
|
Tool for building boxes out of characters.
|
|
|
|
Supports a variety of line styles from `asciimatics.constants`:
|
|
|
|
* ``ASCII_LINE`` -- ASCII safe characters (0)
|
|
* ``SINGLE_LINE`` -- Unicode based single lined box (1)
|
|
* ``DOUBLE_LINE`` -- Unicode based double lined box (2)
|
|
|
|
Individual characters of a box can be accessed directly through attributes. Most attribute
|
|
names are based on the Extended-ASCII characters used for the UNICODE version of the shape.
|
|
The names describe the directions the piece point in (not the part of the box). For example,
|
|
"up_left" is a corner piece that has a part that points up and a part that points left -- the
|
|
character usually used for the bottom right hand corner of a box.
|
|
|
|
Attribute values are:
|
|
|
|
* ``up_left`` -- corner piece facing up and left
|
|
* ``up_right`` -- corner piece facing up and right
|
|
* ``down_left`` -- corner piece facing down and left
|
|
* ``down_right`` -- corner piece facing down and right
|
|
* ``h`` -- horizontal line
|
|
* ``v`` -- vertical line
|
|
* ``v_inside`` -- vertical line used inside the grid
|
|
* ``v_left`` -- vertical line with mid joiner facing to the left
|
|
* ``v_right`` -- vertical line with mid joiner facing to the right
|
|
* ``h_up`` -- horizontal line with a mid joiner facing up
|
|
* ``h_down`` -- horizontal line with a mid joiner facing down
|
|
* ``cross`` -- intersection between vertical and horizontal
|
|
"""
|
|
|
|
def __init__(self, unicode_aware, style=SINGLE_LINE):
|
|
"""
|
|
:param unicode_aware: boolean indicating if the terminal is Unicode
|
|
aware. If False, will force the use of the ASCII style
|
|
:param style: line style specifier. Supports ``ASCII_LINE``,
|
|
``SINGLE_LINE``, and ``DOUBLE_LINE``. Defaults to ``SINGLE_LINE``.
|
|
"""
|
|
self.unicode_aware = unicode_aware
|
|
|
|
# Call property to get side-effect of setting values
|
|
self.style = style
|
|
|
|
@property
|
|
def style(self):
|
|
"""
|
|
The line drawing style used to draw boxes. Possible styles are set
|
|
in :mod:`asciimatics.constants`.
|
|
|
|
:param style: One of ``ASCII_LINE``, ``SINGLE_LINE``, or ``DOUBLE_LINE``
|
|
"""
|
|
return self._style
|
|
|
|
@style.setter
|
|
def style(self, style):
|
|
self._style = style
|
|
|
|
if style == SINGLE_LINE and self.unicode_aware:
|
|
self.down_right = u"┌"
|
|
self.down_left = u"┐"
|
|
self.up_right = u"└"
|
|
self.up_left = u"┘"
|
|
self.h = u"─"
|
|
self.h_inside = u"─"
|
|
self.v = u"│"
|
|
self.v_inside = u"│"
|
|
self.v_left = u"┤"
|
|
self.v_right = u"├"
|
|
self.h_up = u"┴"
|
|
self.h_down = u"┬"
|
|
self.cross = u"┼"
|
|
elif style == DOUBLE_LINE and self.unicode_aware:
|
|
self.down_right = u"╔"
|
|
self.down_left = u"╗"
|
|
self.up_right = u"╚"
|
|
self.up_left = u"╝"
|
|
self.h = u"═"
|
|
self.h_inside = u"═"
|
|
self.v = u"║"
|
|
self.v_inside = u"║"
|
|
self.v_left = u"╣"
|
|
self.v_right = u"╠"
|
|
self.h_up = u"╩"
|
|
self.h_down = u"╦"
|
|
self.cross = u"╬"
|
|
else:
|
|
self.down_left = "+"
|
|
self.down_right = "+"
|
|
self.up_right = "+"
|
|
self.up_left = "+"
|
|
self.h = "-"
|
|
self.h_inside = "-"
|
|
self.v = "|"
|
|
self.v_inside = ":"
|
|
self.v_left = "+"
|
|
self.v_right = "+"
|
|
self.h_up = "+"
|
|
self.h_down = "+"
|
|
self.cross = "+"
|
|
|
|
# --- Empty box methods
|
|
def box_top(self, width):
|
|
"""
|
|
Returns a string containing the top border of a box
|
|
|
|
:param width: width of box, including corners
|
|
"""
|
|
return self.down_right + (width - 2) * self.h + self.down_left
|
|
|
|
def box_bottom(self, width):
|
|
"""
|
|
Returns a string containing the bottom border of a box
|
|
|
|
:param width: width of box, including corners
|
|
"""
|
|
return self.up_right + (width - 2) * self.h + self.up_left
|
|
|
|
def box_line(self, width):
|
|
"""
|
|
Returns a string with a vertical bar on each end, padded with
|
|
spaces in between for the given width.
|
|
|
|
:param width: width of box including sides
|
|
"""
|
|
return self.v + (width - 2) * ' ' + self.v
|
|
|
|
def box(self, width, height):
|
|
"""
|
|
Returns a string containing a box with the given width and height.
|
|
"""
|
|
lines = [self.box_top(width)]
|
|
for _ in range(height - 2):
|
|
lines.append(self.box_line(width))
|
|
|
|
lines.append(self.box_bottom(width))
|
|
return '\n'.join(lines) + '\n'
|