diff --git a/progress/bar.py b/progress/bar.py index 8819efd..5637196 100644 --- a/progress/bar.py +++ b/progress/bar.py @@ -19,6 +19,7 @@ from __future__ import unicode_literals import sys from . import Progress +from .colors import color class Bar(Progress): @@ -28,13 +29,14 @@ class Bar(Progress): bar_suffix = '| ' empty_fill = ' ' fill = '#' + color = None def update(self): filled_length = int(self.width * self.progress) empty_length = self.width - filled_length message = self.message % self - bar = self.fill * filled_length + bar = color(self.fill * filled_length, fg=self.color) empty = self.empty_fill * empty_length suffix = self.suffix % self line = ''.join([message, self.bar_prefix, bar, empty, self.bar_suffix, @@ -74,7 +76,7 @@ class IncrementalBar(Bar): nempty = self.width - nfull # Number of empty chars message = self.message % self - bar = self.phases[-1] * nfull + bar = color(self.phases[-1] * nfull, fg=self.color) current = self.phases[phase] if phase > 0 else '' empty = self.empty_fill * max(0, nempty - len(current)) suffix = self.suffix % self diff --git a/progress/colors.py b/progress/colors.py new file mode 100644 index 0000000..4e770f8 --- /dev/null +++ b/progress/colors.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2020 Georgios Verigakis +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from functools import partial + + +COLORS = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', + 'white') +STYLES = ('bold', 'faint', 'italic', 'underline', 'blink', 'blink2', + 'negative', 'concealed', 'crossed') + + +def color(s, fg=None, bg=None, style=None): + sgr = [] + + if fg: + if fg in COLORS: + sgr.append(str(30 + COLORS.index(fg))) + elif isinstance(fg, int) and 0 <= fg <= 255: + sgr.append('38;5;%d' % int(fg)) + else: + raise Exception('Invalid color "%s"' % fg) + + if bg: + if bg in COLORS: + sgr.append(str(40 + COLORS.index(bg))) + elif isinstance(bg, int) and 0 <= bg <= 255: + sgr.append('48;5;%d' % bg) + else: + raise Exception('Invalid color "%s"' % bg) + + if style: + for st in style.split('+'): + if st in STYLES: + sgr.append(str(1 + STYLES.index(st))) + else: + raise Exception('Invalid style "%s"' % st) + + if sgr: + prefix = '\x1b[' + ';'.join(sgr) + 'm' + suffix = '\x1b[0m' + return prefix + s + suffix + else: + return s + + +# Foreground shortcuts +black = partial(color, fg='black') +red = partial(color, fg='red') +green = partial(color, fg='green') +yellow = partial(color, fg='yellow') +blue = partial(color, fg='blue') +magenta = partial(color, fg='magenta') +cyan = partial(color, fg='cyan') +white = partial(color, fg='white') + +# Style shortcuts +bold = partial(color, style='bold') +faint = partial(color, style='faint') +italic = partial(color, style='italic') +underline = partial(color, style='underline') +blink = partial(color, style='blink') +blink2 = partial(color, style='blink2') +negative = partial(color, style='negative') +concealed = partial(color, style='concealed') +crossed = partial(color, style='crossed') diff --git a/test_progress.py b/test_progress.py index 4c61bf0..802bd2e 100755 --- a/test_progress.py +++ b/test_progress.py @@ -11,6 +11,7 @@ from progress.bar import (Bar, ChargingBar, FillingSquaresBar, from progress.spinner import (Spinner, PieSpinner, MoonSpinner, LineSpinner, PixelSpinner) from progress.counter import Counter, Countdown, Stack, Pie +from progress.colors import bold def sleep(): @@ -32,6 +33,10 @@ for bar_cls in (IncrementalBar, PixelBar, ShadyBar): bar.next() sleep() +bar = IncrementalBar(bold('Corolored'), color='green') +for i in bar.iter(range(200)): + sleep() + for spin in (Spinner, PieSpinner, MoonSpinner, LineSpinner, PixelSpinner): for i in spin(spin.__name__ + ' %(index)d ').iter(range(100)): sleep()