aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/fancy-sleep
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/fancy-sleep')
-rwxr-xr-xscripts/fancy-sleep219
1 files changed, 219 insertions, 0 deletions
diff --git a/scripts/fancy-sleep b/scripts/fancy-sleep
new file mode 100755
index 0000000..76cb04c
--- /dev/null
+++ b/scripts/fancy-sleep
@@ -0,0 +1,219 @@
+#!/usr/bin/env python3
+# Copyright 2017 vg@devys.org
+# SPDX-License-Identifier: MIT
+
+'''
+Simple and fancy sleep for console.
+
+Time can be precised as XX[h|m|s] [YY[m|s]] [ZZ[s]] or XX:YY[:ZZ].
+
+Usage: fancy-sleep [options] TIME...
+ fancy-sleep -h|--help
+
+Options:
+ -h, --help Display this help message
+'''
+
+
+import contextlib
+import datetime
+import sys
+import time
+import re
+
+import docopt
+
+
+_determine_delta_pattern = None
+
+
+# to avoid accidental trailing spaces removal, use another character and
+# replace.
+numbers = [i.replace('.', ' ') for i in (
+"""\
+ ██████
+ ██ ██
+ ██ ██
+ ██ ██
+ ██████
+""",
+"""\
+ ██
+ ██
+ ██
+ ██
+ ██
+""",
+"""\
+ ██████
+ ██
+ ██████
+ ██....
+ ██████
+""",
+"""\
+ ██████
+ ██
+ ██████
+ ██
+ ██████
+""",
+"""\
+ ██ ██
+ ██ ██
+ ██████
+ ██
+ ██
+""",
+"""\
+ ██████
+ ██....
+ ██████
+ ██
+ ██████
+""",
+"""\
+ ██████
+ ██....
+ ██████
+ ██ ██
+ ██████
+""",
+"""\
+ ██████
+ ██
+ ██
+ ██
+ ██
+""",
+"""\
+ ██████
+ ██ ██
+ ██████
+ ██ ██
+ ██████
+""",
+"""\
+ ██████
+ ██ ██
+ ██████
+ ██
+ ██████
+""",
+"""\
+ .
+ ██.
+ .
+ ██.
+ .
+""",
+)]
+
+
+def print_translated(string):
+ translated = []
+ for character in string:
+ index = 0
+ if '0' <= character and character <= '9':
+ index = ord(character) - ord('0')
+ elif character == ':':
+ index = 10
+ translated.append(numbers[index])
+ display_lines = ['', '', '', '', '', '']
+ for index in range(5):
+ for number in translated:
+ display_lines[index] += number.splitlines()[index]
+ print('\n'.join(display_lines), end='')
+
+
+def determine_delta(elements,
+ time_pattern=re.compile(r'^(\d+)([dhms]?)$')):
+ default = datetime.datetime.strptime('0', '%S')
+ timedelta = datetime.timedelta()
+ for element in elements:
+ groups = time_pattern.match(element)
+ if groups:
+ if groups.group(2) == 'd':
+ timedelta += datetime.timedelta(days=float(groups.group(1)))
+ elif groups.group(2) == 'h':
+ timedelta += datetime.timedelta(hours=float(groups.group(1)))
+ elif groups.group(2) == 'm':
+ timedelta += datetime.timedelta(minutes=float(groups.group(1)))
+ elif groups.group(2) == 's' or groups.group(2) == '':
+ timedelta += datetime.timedelta(seconds=float(groups.group(1)))
+
+
+ #with contextlib.suppress(ValueError):
+ # timedelta += datetime.datetime.strptime(element, '%dd') - default
+ #with contextlib.suppress(ValueError):
+ # timedelta += datetime.datetime.strptime(element, '%Hh') - default
+ #with contextlib.suppress(ValueError):
+ # timedelta += datetime.datetime.strptime(element, '%Mm') - default
+ #with contextlib.suppress(ValueError):
+ # timedelta += datetime.datetime.strptime(element, '%Ss') - default
+ #with contextlib.suppress(ValueError):
+ # timedelta += datetime.datetime.strptime(element, '%S') - default
+ else:
+ with contextlib.suppress(ValueError):
+ timedelta += datetime.datetime.strptime(element, '%H:%M') - default
+ with contextlib.suppress(ValueError):
+ timedelta += datetime.datetime.strptime(element, '%H:%M:%S') - default
+ return timedelta
+
+
+def determine_delta_tests():
+ assert(determine_delta('11'.split()) == datetime.timedelta(seconds=11))
+ assert(determine_delta('11s'.split()) == datetime.timedelta(seconds=11))
+ assert(determine_delta('11h 47m'.split()) == datetime.timedelta(hours=11, minutes=47))
+ assert(determine_delta('11h 47'.split()) == datetime.timedelta(hours=11, seconds=47))
+ assert(determine_delta('11h 47m 09'.split()) == datetime.timedelta(hours=11, minutes=47, seconds=9))
+ assert(determine_delta('09:53'.split()) == datetime.timedelta(hours=9, minutes=53))
+ assert(determine_delta('8:2 9'.split()) == datetime.timedelta(hours=8, minutes=2, seconds=9))
+ assert(determine_delta('8d 5:32 6s'.split()) == datetime.timedelta(days=8, hours=5, minutes=32, seconds=6))
+
+
+if __name__ == '__main__':
+ 'run fancy-sleep code: args parsing, display and sleeping logic'
+
+ # FIXME: can be done automatically with nose for example ?
+ determine_delta_tests()
+
+ args = docopt.docopt(__doc__)
+
+ curtime = datetime.datetime.now()
+ timedelta = determine_delta(args['TIME'])
+ target_time = curtime + timedelta
+
+ print('Launched at:', curtime.strftime('%F %T'))
+ print('Run until:', target_time.strftime('%F %T'))
+ sys.stdout.flush()
+
+ if sys.stdout.isatty():
+ print()
+
+ print('\n'*5, '\x1b[5A', sep='', end='')
+ print('\x1b[s', end='') # save cursor
+ try:
+ while True:
+ delta = target_time.timestamp() - time.time()
+ if delta <= 0:
+ break
+ hours = int(delta / 3600)
+ minutes = int(delta / 60) % 60
+ seconds = int(delta) % 60
+
+ print('\x1b[u', end='') # restore cursor
+ time_string = '%02d:%02d:%02d' % (hours, minutes, seconds)
+ #print('\rremainining time: %s' % time_string, end='')
+ print_translated(time_string)
+
+ time.sleep(1)
+ except KeyboardInterrupt:
+ sys.exit(130)
+ finally:
+ print()
+ else:
+ try:
+ time.sleep(target_time.timestamp() - time.time())
+ except KeyboardInterrupt:
+ sys.exit(130)