def countdown(stdscr, alt_format=False, font=DEFAULT_FONT, blink=False, critical=3, quit_after=None, text=None, timespec=None, title=None, voice=None, voice_prefix=None, exec_cmd=None, outfile=None, no_bell=False, no_seconds=False, no_text_magic=True, no_figlet=False, no_figlet_y_offset=-1, no_window_title=False, time=False, time_format=None, **kwargs): try: sync_start, target = parse_timestr(timespec) except ValueError: raise click.BadParameter( "Unable to parse TIME value '{}'".format(timespec)) curses_lock, input_queue, quit_event = setup(stdscr) figlet = Figlet(font=font) if not no_figlet: no_figlet_y_offset = -1 if title and not no_figlet: try: title = figlet.renderText(title) except CharNotPrinted: title = "" voice_cmd = None if voice: for cmd in ("/usr/bin/say", "/usr/bin/espeak"): if os.path.exists(cmd): voice_cmd = cmd break if voice or exec_cmd: voice_prefix = voice_prefix or "" input_thread = Thread( args=(stdscr, input_queue, quit_event, curses_lock), target=input_thread_body, ) input_thread.start() seconds_total = seconds_left = int( ceil((target - datetime.now()).total_seconds())) try: while seconds_left > 0 or blink or text: figlet.width = stdscr.getmaxyx()[1] if time: countdown_text = datetime.now().strftime(time_format) elif alt_format: countdown_text = format_seconds_alt(seconds_left, seconds_total, hide_seconds=no_seconds) else: countdown_text = format_seconds(seconds_left, hide_seconds=no_seconds) if seconds_left > 0: with curses_lock: if not no_window_title: os.write( stdout.fileno(), "\033]2;{0}\007".format(countdown_text).encode()) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format(countdown_text, seconds_left)) stdscr.erase() try: draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=1 if seconds_left <= critical else 0, fallback=title + "\n" + countdown_text if title else countdown_text, title=title, no_figlet_y_offset=no_figlet_y_offset, ) except CharNotPrinted: draw_text(stdscr, "E") annunciation = None if seconds_left <= critical: annunciation = str(seconds_left) elif seconds_left in (5, 10, 20, 30, 60): annunciation = "{} {} seconds".format(voice_prefix, seconds_left) elif seconds_left in (300, 600, 1800): annunciation = "{} {} minutes".format(voice_prefix, int(seconds_left / 60)) elif seconds_left == 3600: annunciation = "{} one hour".format(voice_prefix) if annunciation or exec_cmd: if exec_cmd: Popen( exec_cmd.format(seconds_left, annunciation or ""), stdout=DEVNULL, stderr=STDOUT, shell=True, ) if voice_cmd: Popen( [voice_cmd, "-v", voice, annunciation.strip()], stdout=DEVNULL, stderr=STDOUT, ) # We want to sleep until this point of time has been # reached: sleep_target = sync_start + timedelta(seconds=1) if time: sleep_target = sleep_target.replace(microsecond=0) # If sync_start has microsecond=0, it might happen that we # need to skip one frame (the very first one). This occurs # when the program has been startet at, say, # "2014-05-29 20:27:57.930651". Now suppose rendering the # frame took about 0.2 seconds. The real time now is # "2014-05-29 20:27:58.130000" and sleep_target is # "2014-05-29 20:27:58.000000" which is in the past! We're # already too late. We could either skip that frame # completely or we can draw it right now. I chose to do the # latter: Only sleep if haven't already missed our target. now = datetime.now() if sleep_target > now and seconds_left > 0: try: input_action = input_queue.get(True, (sleep_target - now).total_seconds()) except Empty: input_action = None if input_action == INPUT_PAUSE: pause_start = datetime.now() with curses_lock: stdscr.erase() try: draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=3, fallback=countdown_text, title=title, no_figlet_y_offset=no_figlet_y_offset, ) except CharNotPrinted: draw_text(stdscr, "E") input_action = input_queue.get() if input_action == INPUT_PAUSE: time_paused = datetime.now() - pause_start sync_start += time_paused target += time_paused if input_action == INPUT_EXIT: # no elif here! input_action may have changed break elif input_action == INPUT_RESET: sync_start, target = parse_timestr(timespec) seconds_left = int( ceil((target - datetime.now()).total_seconds())) continue elif input_action == INPUT_PLUS: target += timedelta(seconds=10) elif input_action == INPUT_MINUS: target -= timedelta(seconds=10) elif input_action == INPUT_LAP: continue sync_start = sleep_target seconds_left = int(ceil((target - datetime.now()).total_seconds())) if seconds_left <= 0: # we could write this entire block outside the parent while # but that would leave us unable to reset everything if not no_bell: with curses_lock: curses.beep() if text and not no_text_magic: text = normalize_text(text) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format(text if text else "DONE", 0)) rendered_text = text if text and not no_figlet: try: rendered_text = figlet.renderText(text) except CharNotPrinted: rendered_text = "" if blink or text: base_color = 1 if blink else 0 blink_reset = False flip = True slept = 0 extra_sleep = 0 while True: with curses_lock: os.write( stdout.fileno(), "\033]2;{0}\007".format( "/" if flip else "\\").encode()) if text: draw_text( stdscr, rendered_text, color=base_color if flip else 4, fallback=text, no_figlet_y_offset=no_figlet_y_offset, ) else: draw_text(stdscr, "", color=base_color if flip else 4) if blink: flip = not flip try: sleep_start = datetime.now() input_action = input_queue.get( True, 0.5 + extra_sleep) except Empty: input_action = None finally: extra_sleep = 0 sleep_end = datetime.now() if input_action == INPUT_PAUSE: pause_start = datetime.now() input_action = input_queue.get() extra_sleep = (sleep_end - sleep_start).total_seconds() if input_action == INPUT_EXIT: # no elif here! input_action may have changed return elif input_action == INPUT_RESET: sync_start, target = parse_timestr(timespec) seconds_left = int( ceil( (target - datetime.now()).total_seconds())) blink_reset = True break slept += (sleep_end - sleep_start).total_seconds() if quit_after and slept >= float(quit_after): return if blink_reset: continue finally: with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;\007".encode()) if outfile: os.remove(outfile) quit_event.set() input_thread.join()
def stopwatch(stdscr, alt_format=False, critical=3, exec_cmd=None, font=DEFAULT_FONT, no_figlet=False, no_figlet_y_offset=-1, no_seconds=False, quit_after=None, title=None, outfile=None, no_window_title=False, time=False, time_format=None, voice_prefix=None, **kwargs): curses_lock, input_queue, quit_event = setup(stdscr) figlet = Figlet(font=font) if not no_figlet: no_figlet_y_offset = -1 if title and not no_figlet: try: title = figlet.renderText(title) except CharNotPrinted: title = "" input_thread = Thread( args=(stdscr, input_queue, quit_event, curses_lock), target=input_thread_body, ) input_thread.start() try: sync_start = datetime.now() pause_start = None seconds_elapsed = 0 laps = [] while quit_after is None or seconds_elapsed < int(quit_after): figlet.width = stdscr.getmaxyx()[1] if time: stopwatch_text = datetime.now().strftime(time_format) elif alt_format: stopwatch_text = format_seconds_alt(seconds_elapsed, 0, hide_seconds=no_seconds) else: stopwatch_text = format_seconds(seconds_elapsed, hide_seconds=no_seconds) with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;{0}\007".format(stopwatch_text).encode()) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format(stopwatch_text, seconds_elapsed)) stdscr.erase() try: draw_text( stdscr, stopwatch_text if no_figlet else figlet.renderText(stopwatch_text), fallback=stopwatch_text, title=title, no_figlet_y_offset=no_figlet_y_offset, ) except CharNotPrinted: draw_text(stdscr, "E") if exec_cmd: voice_prefix = voice_prefix or "" annunciation = "" if seconds_elapsed <= critical and seconds_elapsed > 0: annunciation = str(seconds_elapsed) elif seconds_elapsed in (5, 10, 20, 30, 40, 50, 60): annunciation = "{} {} seconds".format( voice_prefix, seconds_elapsed) elif seconds_elapsed in (120, 180, 300, 600, 1800): annunciation = "{} {} minutes".format( voice_prefix, int(seconds_elapsed / 60)) elif seconds_elapsed == 3600: annunciation = "{} one hour".format(voice_prefix) elif seconds_elapsed % 3600 == 0 and seconds_elapsed > 0: annunciation = "{} {} hours".format( voice_prefix, int(seconds_elapsed / 3600)) Popen( exec_cmd.format(seconds_elapsed, annunciation), stdout=DEVNULL, stderr=STDOUT, shell=True, ) sleep_target = sync_start + timedelta(seconds=seconds_elapsed + 1) if time: sleep_target = sleep_target.replace(microsecond=0) now = datetime.now() if sleep_target > now: try: input_action = input_queue.get(True, (sleep_target - now).total_seconds()) except Empty: input_action = None if input_action == INPUT_PAUSE: pause_start = datetime.now() with curses_lock: if not no_window_title: os.write( stdout.fileno(), "\033]2;{0}\007".format( stopwatch_text).encode()) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format( stopwatch_text, seconds_elapsed)) stdscr.erase() try: draw_text( stdscr, stopwatch_text if no_figlet else figlet.renderText(stopwatch_text), color=3, fallback=stopwatch_text, title=title, no_figlet_y_offset=no_figlet_y_offset, ) except CharNotPrinted: draw_text(stdscr, "E") input_action = input_queue.get() if input_action == INPUT_PAUSE: sync_start += (datetime.now() - pause_start) pause_start = None if input_action == INPUT_EXIT: # no elif here! input_action may have changed if pause_start: sync_start += (datetime.now() - pause_start) pause_start = None break elif input_action == INPUT_RESET: sync_start = datetime.now() laps = [] seconds_elapsed = 0 elif input_action == INPUT_PLUS: sync_start -= timedelta(seconds=10) elif input_action == INPUT_MINUS: sync_start += timedelta(seconds=10) elif input_action == INPUT_LAP: if pause_start: sync_start += (datetime.now() - pause_start) pause_start = None laps.append((datetime.now() - sync_start).total_seconds()) sync_start = datetime.now() seconds_elapsed = 0 seconds_elapsed = int( (datetime.now() - sync_start).total_seconds()) finally: with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;\007".encode()) if outfile: os.remove(outfile) quit_event.set() input_thread.join() return (datetime.now() - sync_start).total_seconds(), laps
def countdown(stdscr, alt_format=False, font=DEFAULT_FONT, blink=False, critical=3, quit_after=None, text=None, timespec=None, title=None, voice=None, no_seconds=False, no_text_magic=True, no_figlet=False, no_window_title=False, **kwargs): try: sync_start, target = parse_timestr(timespec) except ValueError: click.echo("Unable to parse TIME value '{}'".format(timespec)) exit(64) curses_lock, input_queue, quit_event = setup(stdscr) figlet = Figlet(font=font) if title and not no_figlet: title = figlet.renderText(title) input_thread = Thread( args=(stdscr, input_queue, quit_event, curses_lock), target=input_thread_body, ) input_thread.start() seconds_total = seconds_left = int( ceil((target - datetime.now()).total_seconds())) try: while seconds_left > 0 or blink or text: figlet.width = stdscr.getmaxyx()[1] if alt_format: countdown_text = format_seconds_alt(seconds_left, seconds_total, hide_seconds=no_seconds) else: countdown_text = format_seconds(seconds_left, hide_seconds=no_seconds) if seconds_left > 0: with curses_lock: if not no_window_title: os.write( stdout.fileno(), "\033]2;{0}\007".format(countdown_text).encode()) stdscr.erase() draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=1 if seconds_left <= critical else 0, fallback=countdown_text, title=title, ) if seconds_left <= 10 and voice: voice_exec = "echo" if os.path.exists("/usr/bin/say"): voice_exec = "/usr/bin/say" elif os.path.exists("/usr/bin/espeak"): voice_exec = "/usr/bin/espeak" Popen([voice_exec, "-v", voice, str(seconds_left)]) # We want to sleep until this point of time has been # reached: sleep_target = sync_start + timedelta(seconds=1) # If sync_start has microsecond=0, it might happen that we # need to skip one frame (the very first one). This occurs # when the program has been startet at, say, # "2014-05-29 20:27:57.930651". Now suppose rendering the # frame took about 0.2 seconds. The real time now is # "2014-05-29 20:27:58.130000" and sleep_target is # "2014-05-29 20:27:58.000000" which is in the past! We're # already too late. We could either skip that frame # completely or we can draw it right now. I chose to do the # latter: Only sleep if haven't already missed our target. now = datetime.now() if sleep_target > now and seconds_left > 0: try: input_action = input_queue.get(True, (sleep_target - now).total_seconds()) except Empty: input_action = None if input_action == INPUT_PAUSE: pause_start = datetime.now() with curses_lock: stdscr.erase() draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=3, fallback=countdown_text, ) input_action = input_queue.get() if input_action == INPUT_PAUSE: sync_start += (datetime.now() - pause_start) target += (datetime.now() - pause_start) if input_action == INPUT_EXIT: # no elif here! input_action may have changed break elif input_action == INPUT_RESET: sync_start, target = parse_timestr(timespec) seconds_left = int( ceil((target - datetime.now()).total_seconds())) continue sync_start = sleep_target seconds_left = int(ceil((target - datetime.now()).total_seconds())) if seconds_left <= 0: # we could write this entire block outside the parent while # but that would leave us unable to reset everything with curses_lock: curses.beep() if text and not no_text_magic: text = normalize_text(text) rendered_text = text if text and not no_figlet: rendered_text = figlet.renderText(text) if blink or text: base_color = 1 if blink else 0 blink_reset = False flip = True slept = 0 extra_sleep = 0 while True: with curses_lock: os.write( stdout.fileno(), "\033]2;{0}\007".format( "/" if flip else "\\").encode()) if text: draw_text( stdscr, rendered_text, color=base_color if flip else 4, fallback=text, ) else: draw_text(stdscr, "", color=base_color if flip else 4) if blink: flip = not flip try: sleep_start = datetime.now() input_action = input_queue.get( True, 0.5 + extra_sleep) except Empty: input_action = None finally: extra_sleep = 0 sleep_end = datetime.now() if input_action == INPUT_PAUSE: pause_start = datetime.now() input_action = input_queue.get() extra_sleep = (sleep_end - sleep_start).total_seconds() if input_action == INPUT_EXIT: # no elif here! input_action may have changed return elif input_action == INPUT_RESET: sync_start, target = parse_timestr(timespec) seconds_left = int( ceil( (target - datetime.now()).total_seconds())) blink_reset = True break slept += (sleep_end - sleep_start).total_seconds() if quit_after and slept >= float(quit_after): return if blink_reset: continue finally: with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;\007".encode()) quit_event.set() input_thread.join()
def stopwatch(stdscr, alt_format=False, font=DEFAULT_FONT, no_figlet=False, no_seconds=False, quit_after=None, title=None, outfile=None, no_window_title=False, **kwargs): curses_lock, input_queue, quit_event = setup(stdscr) figlet = Figlet(font=font) if title and not no_figlet: try: title = figlet.renderText(title) except CharNotPrinted: title = "" input_thread = Thread( args=(stdscr, input_queue, quit_event, curses_lock), target=input_thread_body, ) input_thread.start() try: sync_start = datetime.now() pause_start = None seconds_elapsed = 0 laps = [] while quit_after is None or seconds_elapsed < int(quit_after): figlet.width = stdscr.getmaxyx()[1] if alt_format: countdown_text = format_seconds_alt(seconds_elapsed, 0, hide_seconds=no_seconds) else: countdown_text = format_seconds(seconds_elapsed, hide_seconds=no_seconds) with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;{0}\007".format(countdown_text).encode()) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format(countdown_text, seconds_elapsed)) stdscr.erase() try: draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), fallback=countdown_text, title=title, ) except CharNotPrinted: draw_text(stdscr, "E") sleep_target = sync_start + timedelta(seconds=seconds_elapsed + 1) now = datetime.now() if sleep_target > now: try: input_action = input_queue.get(True, (sleep_target - now).total_seconds()) except Empty: input_action = None if input_action == INPUT_PAUSE: pause_start = datetime.now() with curses_lock: if not no_window_title: os.write( stdout.fileno(), "\033]2;{0}\007".format( countdown_text).encode()) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format( countdown_text, seconds_elapsed)) stdscr.erase() try: draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=3, fallback=countdown_text, title=title, ) except CharNotPrinted: draw_text(stdscr, "E") input_action = input_queue.get() if input_action == INPUT_PAUSE: sync_start += (datetime.now() - pause_start) pause_start = None if input_action == INPUT_EXIT: # no elif here! input_action may have changed if pause_start: sync_start += (datetime.now() - pause_start) pause_start = None break elif input_action == INPUT_RESET: sync_start = datetime.now() laps = [] seconds_elapsed = 0 elif input_action == INPUT_LAP: if pause_start: sync_start += (datetime.now() - pause_start) pause_start = None laps.append((datetime.now() - sync_start).total_seconds()) sync_start = datetime.now() seconds_elapsed = 0 seconds_elapsed = int( (datetime.now() - sync_start).total_seconds()) finally: with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;\007".encode()) if outfile: os.remove(outfile) quit_event.set() input_thread.join() return (datetime.now() - sync_start).total_seconds(), laps
def stopwatch( stdscr, alt_format=False, font=DEFAULT_FONT, no_figlet=False, no_seconds=False, quit_after=None, title=None, outfile=None, no_window_title=False, time=False, time_format=None, **kwargs ): curses_lock, input_queue, quit_event = setup(stdscr) figlet = Figlet(font=font) if title and not no_figlet: try: title = figlet.renderText(title) except CharNotPrinted: title = "" input_thread = Thread( args=(stdscr, input_queue, quit_event, curses_lock), target=input_thread_body, ) input_thread.start() try: sync_start = datetime.now() pause_start = None seconds_elapsed = 0 laps = [] while quit_after is None or seconds_elapsed < int(quit_after): figlet.width = stdscr.getmaxyx()[1] if time: countdown_text = datetime.now().strftime(time_format) elif alt_format: countdown_text = format_seconds_alt(seconds_elapsed, 0, hide_seconds=no_seconds) else: countdown_text = format_seconds(seconds_elapsed, hide_seconds=no_seconds) with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;{0}\007".format(countdown_text).encode()) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format(countdown_text, seconds_elapsed)) stdscr.erase() try: draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), fallback=countdown_text, title=title, ) except CharNotPrinted: draw_text(stdscr, "E") sleep_target = sync_start + timedelta(seconds=seconds_elapsed + 1) if time: sleep_target = sleep_target.replace(microsecond=0) now = datetime.now() if sleep_target > now: try: input_action = input_queue.get(True, (sleep_target - now).total_seconds()) except Empty: input_action = None if input_action == INPUT_PAUSE: pause_start = datetime.now() with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;{0}\007".format(countdown_text).encode()) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format(countdown_text, seconds_elapsed)) stdscr.erase() try: draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=3, fallback=countdown_text, title=title, ) except CharNotPrinted: draw_text(stdscr, "E") input_action = input_queue.get() if input_action == INPUT_PAUSE: sync_start += (datetime.now() - pause_start) pause_start = None if input_action == INPUT_EXIT: # no elif here! input_action may have changed if pause_start: sync_start += (datetime.now() - pause_start) pause_start = None break elif input_action == INPUT_RESET: sync_start = datetime.now() laps = [] seconds_elapsed = 0 elif input_action == INPUT_LAP: if pause_start: sync_start += (datetime.now() - pause_start) pause_start = None laps.append((datetime.now() - sync_start).total_seconds()) sync_start = datetime.now() seconds_elapsed = 0 seconds_elapsed = int((datetime.now() - sync_start).total_seconds()) finally: with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;\007".encode()) if outfile: os.remove(outfile) quit_event.set() input_thread.join() return (datetime.now() - sync_start).total_seconds(), laps
def countdown( stdscr, alt_format=False, font=DEFAULT_FONT, blink=False, critical=3, quit_after=None, text=None, timespec=None, title=None, voice=None, voice_prefix=None, outfile=None, no_bell=False, no_seconds=False, no_text_magic=True, no_figlet=False, no_window_title=False, time=False, time_format=None, **kwargs ): try: sync_start, target = parse_timestr(timespec) except ValueError: raise click.BadParameter("Unable to parse TIME value '{}'".format(timespec)) curses_lock, input_queue, quit_event = setup(stdscr) figlet = Figlet(font=font) if title and not no_figlet: try: title = figlet.renderText(title) except CharNotPrinted: title = "" voice_cmd = None if voice: for cmd in ("/usr/bin/say", "/usr/bin/espeak"): if os.path.exists(cmd): voice_cmd = cmd break voice_prefix = voice_prefix or "" input_thread = Thread( args=(stdscr, input_queue, quit_event, curses_lock), target=input_thread_body, ) input_thread.start() seconds_total = seconds_left = int(ceil((target - datetime.now()).total_seconds())) try: while seconds_left > 0 or blink or text: figlet.width = stdscr.getmaxyx()[1] if time: countdown_text = datetime.now().strftime(time_format) elif alt_format: countdown_text = format_seconds_alt( seconds_left, seconds_total, hide_seconds=no_seconds) else: countdown_text = format_seconds(seconds_left, hide_seconds=no_seconds) if seconds_left > 0: with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;{0}\007".format(countdown_text).encode()) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format(countdown_text, seconds_left)) stdscr.erase() try: draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=1 if seconds_left <= critical else 0, fallback=title + "\n" + countdown_text if title else countdown_text, title=title, ) except CharNotPrinted: draw_text(stdscr, "E") if voice_cmd: announciation = None if seconds_left <= critical: announciation = str(seconds_left) elif seconds_left in (5, 10, 20, 30, 60): announciation = "{} {} seconds".format(voice_prefix, seconds_left) elif seconds_left in (300, 600, 1800): announciation = "{} {} minutes".format(voice_prefix, int(seconds_left / 60)) elif seconds_left == 3600: announciation = "{} one hour".format(voice_prefix) if announciation: Popen( [voice_cmd, "-v", voice, announciation.strip()], stdout=DEVNULL, stderr=STDOUT, ) # We want to sleep until this point of time has been # reached: sleep_target = sync_start + timedelta(seconds=1) if time: sleep_target = sleep_target.replace(microsecond=0) # If sync_start has microsecond=0, it might happen that we # need to skip one frame (the very first one). This occurs # when the program has been startet at, say, # "2014-05-29 20:27:57.930651". Now suppose rendering the # frame took about 0.2 seconds. The real time now is # "2014-05-29 20:27:58.130000" and sleep_target is # "2014-05-29 20:27:58.000000" which is in the past! We're # already too late. We could either skip that frame # completely or we can draw it right now. I chose to do the # latter: Only sleep if haven't already missed our target. now = datetime.now() if sleep_target > now and seconds_left > 0: try: input_action = input_queue.get(True, (sleep_target - now).total_seconds()) except Empty: input_action = None if input_action == INPUT_PAUSE: pause_start = datetime.now() with curses_lock: stdscr.erase() try: draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=3, fallback=countdown_text, ) except CharNotPrinted: draw_text(stdscr, "E") input_action = input_queue.get() if input_action == INPUT_PAUSE: time_paused = datetime.now() - pause_start sync_start += time_paused target += time_paused if input_action == INPUT_EXIT: # no elif here! input_action may have changed break elif input_action == INPUT_RESET: sync_start, target = parse_timestr(timespec) seconds_left = int(ceil((target - datetime.now()).total_seconds())) continue elif input_action == INPUT_LAP: continue sync_start = sleep_target seconds_left = int(ceil((target - datetime.now()).total_seconds())) if seconds_left <= 0: # we could write this entire block outside the parent while # but that would leave us unable to reset everything if not no_bell: with curses_lock: curses.beep() if text and not no_text_magic: text = normalize_text(text) if outfile: with open(outfile, 'w') as f: f.write("{}\n{}\n".format(text if text else "DONE", 0)) rendered_text = text if text and not no_figlet: try: rendered_text = figlet.renderText(text) except CharNotPrinted: rendered_text = "" if blink or text: base_color = 1 if blink else 0 blink_reset = False flip = True slept = 0 extra_sleep = 0 while True: with curses_lock: os.write(stdout.fileno(), "\033]2;{0}\007".format("/" if flip else "\\").encode()) if text: draw_text( stdscr, rendered_text, color=base_color if flip else 4, fallback=text, ) else: draw_text(stdscr, "", color=base_color if flip else 4) if blink: flip = not flip try: sleep_start = datetime.now() input_action = input_queue.get(True, 0.5 + extra_sleep) except Empty: input_action = None finally: extra_sleep = 0 sleep_end = datetime.now() if input_action == INPUT_PAUSE: pause_start = datetime.now() input_action = input_queue.get() extra_sleep = (sleep_end - sleep_start).total_seconds() if input_action == INPUT_EXIT: # no elif here! input_action may have changed return elif input_action == INPUT_RESET: sync_start, target = parse_timestr(timespec) seconds_left = int(ceil((target - datetime.now()).total_seconds())) blink_reset = True break slept += (sleep_end - sleep_start).total_seconds() if quit_after and slept >= float(quit_after): return if blink_reset: continue finally: with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;\007".encode()) if outfile: os.remove(outfile) quit_event.set() input_thread.join()
def countdown( stdscr, alt_format=False, font=DEFAULT_FONT, blink=False, critical=3, quit_after=None, text=None, timespec=None, title=None, voice=None, no_seconds=False, no_text_magic=True, no_figlet=False, no_window_title=False, **kwargs ): try: sync_start, target = parse_timestr(timespec) except ValueError: click.echo("Unable to parse TIME value '{}'".format(timespec)) exit(64) curses_lock, input_queue, quit_event = setup(stdscr) figlet = Figlet(font=font) if title and not no_figlet: title = figlet.renderText(title) input_thread = Thread( args=(stdscr, input_queue, quit_event, curses_lock), target=input_thread_body, ) input_thread.start() seconds_total = seconds_left = int(ceil((target - datetime.now()).total_seconds())) try: while seconds_left > 0 or blink or text: figlet.width = stdscr.getmaxyx()[1] if alt_format: countdown_text = format_seconds_alt( seconds_left, seconds_total, hide_seconds=no_seconds) else: countdown_text = format_seconds(seconds_left, hide_seconds=no_seconds) if seconds_left > 0: with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;{0}\007".format(countdown_text).encode()) stdscr.erase() draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=1 if seconds_left <= critical else 0, fallback=countdown_text, title=title, ) if seconds_left <= 10 and voice: voice_exec = "echo" if os.path.exists("/usr/bin/say"): voice_exec = "/usr/bin/say" elif os.path.exists("/usr/bin/espeak"): voice_exec = "/usr/bin/espeak" Popen([voice_exec, "-v", voice, str(seconds_left)]) # We want to sleep until this point of time has been # reached: sleep_target = sync_start + timedelta(seconds=1) # If sync_start has microsecond=0, it might happen that we # need to skip one frame (the very first one). This occurs # when the program has been startet at, say, # "2014-05-29 20:27:57.930651". Now suppose rendering the # frame took about 0.2 seconds. The real time now is # "2014-05-29 20:27:58.130000" and sleep_target is # "2014-05-29 20:27:58.000000" which is in the past! We're # already too late. We could either skip that frame # completely or we can draw it right now. I chose to do the # latter: Only sleep if haven't already missed our target. now = datetime.now() if sleep_target > now and seconds_left > 0: try: input_action = input_queue.get(True, (sleep_target - now).total_seconds()) except Empty: input_action = None if input_action == INPUT_PAUSE: pause_start = datetime.now() with curses_lock: stdscr.erase() draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=3, fallback=countdown_text, ) input_action = input_queue.get() if input_action == INPUT_PAUSE: sync_start += (datetime.now() - pause_start) target += (datetime.now() - pause_start) if input_action == INPUT_EXIT: # no elif here! input_action may have changed break elif input_action == INPUT_RESET: sync_start, target = parse_timestr(timespec) seconds_left = int(ceil((target - datetime.now()).total_seconds())) continue elif input_action == INPUT_LAP: continue sync_start = sleep_target seconds_left = int(ceil((target - datetime.now()).total_seconds())) if seconds_left <= 0: # we could write this entire block outside the parent while # but that would leave us unable to reset everything with curses_lock: curses.beep() if text and not no_text_magic: text = normalize_text(text) rendered_text = text if text and not no_figlet: rendered_text = figlet.renderText(text) if blink or text: base_color = 1 if blink else 0 blink_reset = False flip = True slept = 0 extra_sleep = 0 while True: with curses_lock: os.write(stdout.fileno(), "\033]2;{0}\007".format("/" if flip else "\\").encode()) if text: draw_text( stdscr, rendered_text, color=base_color if flip else 4, fallback=text, ) else: draw_text(stdscr, "", color=base_color if flip else 4) if blink: flip = not flip try: sleep_start = datetime.now() input_action = input_queue.get(True, 0.5 + extra_sleep) except Empty: input_action = None finally: extra_sleep = 0 sleep_end = datetime.now() if input_action == INPUT_PAUSE: pause_start = datetime.now() input_action = input_queue.get() extra_sleep = (sleep_end - sleep_start).total_seconds() if input_action == INPUT_EXIT: # no elif here! input_action may have changed return elif input_action == INPUT_RESET: sync_start, target = parse_timestr(timespec) seconds_left = int(ceil((target - datetime.now()).total_seconds())) blink_reset = True break slept += (sleep_end - sleep_start).total_seconds() if quit_after and slept >= float(quit_after): return if blink_reset: continue finally: with curses_lock: if not no_window_title: os.write(stdout.fileno(), "\033]2;\007".encode()) quit_event.set() input_thread.join()
def stopwatch( stdscr, alt_format=False, font=DEFAULT_FONT, no_figlet=False, no_seconds=False, quit_after=None, title=None, no_window_title=False, **kwargs ): curses_lock, input_queue, quit_event = setup(stdscr) figlet = Figlet(font=font) if title and not no_figlet: title = figlet.renderText(title) input_thread = Thread( args=(stdscr, input_queue, quit_event, curses_lock), target=input_thread_body, ) input_thread.start() try: sync_start = datetime.now() seconds_elapsed = 0 while quit_after is None or seconds_elapsed < int(quit_after): figlet.width = stdscr.getmaxyx()[1] if alt_format: countdown_text = format_seconds_alt(seconds_elapsed, 0, hide_seconds=no_seconds) else: countdown_text = format_seconds(seconds_elapsed, hide_seconds=no_seconds) with curses_lock: if not no_window_title: curses.putp("\033]2;{0}\007".format(countdown_text).encode()) stdscr.erase() draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), fallback=countdown_text, title=title, ) sleep_target = sync_start + timedelta(seconds=seconds_elapsed + 1) now = datetime.now() if sleep_target > now: try: input_action = input_queue.get(True, (sleep_target - now).total_seconds()) except Empty: input_action = None if input_action == INPUT_PAUSE: pause_start = datetime.now() with curses_lock: if not no_window_title: curses.putp("\033]2;{0}\007".format(countdown_text).encode()) stdscr.erase() draw_text( stdscr, countdown_text if no_figlet else figlet.renderText(countdown_text), color=3, fallback=countdown_text, title=title, ) input_action = input_queue.get() if input_action == INPUT_PAUSE: sync_start += (datetime.now() - pause_start) if input_action == INPUT_EXIT: # no elif here! input_action may have changed break elif input_action == INPUT_RESET: sync_start = datetime.now() seconds_elapsed = 0 seconds_elapsed = int((datetime.now() - sync_start).total_seconds()) finally: with curses_lock: if not no_window_title: curses.putp("\033]2;\007".encode()) quit_event.set() input_thread.join() raise CursesReturnValue((datetime.now() - sync_start).total_seconds())
def handle404(req, resp): f = Figlet(font='colossal') f.width = 125 resp.status = falcon.HTTP_404 resp.content_type = falcon.MEDIA_TEXT resp.body = f.renderText('C o i n p a y s').encode('utf-8')