diff options
-rw-r--r-- | .gitignore | 11 | ||||
-rw-r--r-- | license.txt | 21 | ||||
-rw-r--r-- | readme.rst | 24 | ||||
-rwxr-xr-x | scripts/fancy-sleep | 219 |
4 files changed, 275 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8b6a7ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# safely ignore these filetypes/extensions +*.pyo +*.pyc +*.log +*.swp +__pycache__ +*.jpg +*.jpeg +*.gif +*.png +*.svg diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..d075b49 --- /dev/null +++ b/license.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright © 2017 vg <vg@devys.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/readme.rst b/readme.rst new file mode 100644 index 0000000..50c61ce --- /dev/null +++ b/readme.rst @@ -0,0 +1,24 @@ +Description +=========== + +This repository contains little scripts not deserving their own repositories. + +License +======= + +Unless specified otherwise, this project is licensed under the terms of the +MIT license. You should have received a copy of the MIT License along with +this program. If not, see <https://opensource.org/licenses/MIT>. + +SPDX-License-Identifier: MIT + +Copyright © 2017 vg <vg@devys.org> + +Contact +======= + +developer + vg + +mail + vg@devys.org 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) |