From c45c5134a7270f7d73a7bbae66d95599b8d551bf Mon Sep 17 00:00:00 2001 From: me Date: Wed, 1 Jan 2020 22:22:31 +0200 Subject: [PATCH] add txtbars --- bumblebee/output.py | 115 +++++++++++++++++++++++++++++++++++++++++++ tests/test_output.py | 62 +++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 tests/test_output.py diff --git a/bumblebee/output.py b/bumblebee/output.py index 99d59c5..f7c952f 100644 --- a/bumblebee/output.py +++ b/bumblebee/output.py @@ -10,6 +10,27 @@ import logging import bumblebee.store import bumblebee.util +MAX_PERCENTS = 100. +CHARS = 8 +HBARS = [ + u"\u2581", + u"\u2582", + u"\u2583", + u"\u2584", + u"\u2585", + u"\u2586", + u"\u2587", + u"\u2588"] +VBARS = [ + u"\u258f", + u"\u258e", + u"\u258d", + u"\u258c", + u"\u258b", + u"\u258a", + u"\u2589", + u"\u2588"] + log = logging.getLogger(__name__) def scrollable(func): @@ -54,6 +75,100 @@ def scrollable(func): return text return wrapper + +class Bar(object): + """superclass""" + bars = None + + def __init__(self, value): + """ + Args: + + value (float): value between 0. and 100. meaning percents + """ + self.value = value + + +class HBar(Bar): + """horizontal bar (1 char)""" + bars = HBARS + + def __init__(self, value): + """ + Args: + + value (float): value between 0. and 100. meaning percents + """ + super(HBar, self).__init__(value) + self.step = MAX_PERCENTS / CHARS + + def get_char(self): + """ + Decide which char to draw + + Return: str + """ + for i in range(CHARS): + left = i * self.step + right = (i + 1) * self.step + if left <= self.value < right: + return self.bars[i] + return self.bars[-1] + + +def hbar(value): + """wrapper function""" + return HBar(value).get_char() + + +class VBar(Bar): + """vertical bar (can be more than 1 char)""" + bars = VBARS + + def __init__(self, value, width=1): + """ + Args: + + value (float): value between 0. and 100. meaning percents + + width (int): width + """ + super(VBar, self).__init__(value) + self.step = MAX_PERCENTS / (CHARS * width) + self.width = width + + def get_chars(self): + """ + Decide which char to draw + + Return: str + """ + if self.value == 100: + return self.bars[-1] * self.width + if self.width == 1: + for i in range(CHARS): + left = i * self.step + right = (i + 1) * self.step + if left <= self.value < right: + return self.bars[i] + else: + full_parts = int(self.value // (self.step * CHARS)) + remainder = self.value - full_parts * self.step * CHARS + empty_parts = self.width - full_parts + if remainder >= 0: + empty_parts -= 1 + part_vbar = VBar(remainder * self.width) # scale to width + chars = self.bars[-1] * full_parts + chars += part_vbar.get_chars() + chars += " " * empty_parts + return chars + + +def vbar(value, width): + """wrapper function""" + return VBar(value, width).get_chars() + + class Widget(bumblebee.store.Store): """Represents a single visible block in the status bar""" def __init__(self, full_text="", name=""): diff --git a/tests/test_output.py b/tests/test_output.py new file mode 100644 index 0000000..6d094c9 --- /dev/null +++ b/tests/test_output.py @@ -0,0 +1,62 @@ +import unittest + +import bumblebee.output + + +class TestHBar(unittest.TestCase): + """tests for bumblebee.output.HBar""" + def setUp(self): + self.value = 1 + self.values = [10, 20, 30, 40, 55, 65, 80, 90] + self.hbar = bumblebee.output.HBar(self.value) + + def test___init__(self): + """bumblebee.output.HBar.__init__()""" + self.assertEqual( + self.hbar.step, bumblebee.output.MAX_PERCENTS / bumblebee.output.CHARS) + + def test_get_char(self): + """bumblebee.output.HBar.get_char()""" + for i in range(bumblebee.output.CHARS): + hbar = bumblebee.output.HBar(self.values[i]) + self.assertEqual(hbar.get_char(), bumblebee.output.HBARS[i]) + # edge case for 100% + hbar = bumblebee.output.HBar(100) + self.assertEqual(hbar.get_char(), bumblebee.output.HBARS[-1]) + + +class TestVBar(unittest.TestCase): + """tests for bumblebee.output.VBar""" + def setUp(self): + self.value = 1 + self.values = [10, 20, 30, 40, 55, 65, 80, 90] + self.vbar = bumblebee.output.VBar(self.value) + + def test___init__(self): + """bumblebee.output.VBar.__init__()""" + self.assertEqual( + self.vbar.step, bumblebee.output.MAX_PERCENTS / bumblebee.output.CHARS) + + def test_get_chars(self): + """bumblebee.output.VBar.get_char()""" + for i in range(bumblebee.output.CHARS): + vbar = bumblebee.output.VBar(self.values[i]) + self.assertEqual(vbar.get_chars(), bumblebee.output.VBARS[i]) + # edge case for 100% + vbar = bumblebee.output.VBar(100) + self.assertEqual(vbar.get_chars(), bumblebee.output.VBARS[-1]) + # 0.x chars filled + value = 0.1 + vbar = bumblebee.output.VBar(value, 3) + expected_chars = vbar.bars[0] + " " + self.assertEqual(vbar.get_chars(), expected_chars) + # 1.x chars filled + value = 35 + vbar = bumblebee.output.VBar(value, 3) + expected_chars = vbar.bars[-1] + vbar.bars[0] + " " + self.assertEqual(vbar.get_chars(), expected_chars) + # 2.x chars filled + value = 67 + vbar = bumblebee.output.VBar(value, 3) + expected_chars = vbar.bars[-1] * 2 + vbar.bars[0] + self.assertEqual(vbar.get_chars(), expected_chars)