Skip to content

Commit

Permalink
Examples of using that keystroke reader thing.
Browse files Browse the repository at this point in the history
  • Loading branch information
scottgasch committed Sep 7, 2024
1 parent 0dfdcc1 commit 0f35017
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 0 deletions.
79 changes: 79 additions & 0 deletions examples/stopwatch/stopwatch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python3

"""
A (unix terminal) stopwatch utility.
"""

import logging
import sys
import time

from pyutils import bootstrap, config, input_utils

logger = logging.getLogger(__name__)
args = config.add_commandline_args(f'({__file__})', f'Args related to {__file__}')
args.add_argument("--start", action="store_true", help="Start as soon as possible.")


class Stopwatch:
def __init__(self):
self.running = False
self.start_time = 0.0
self.elapsed_time = 0.0

def start(self):
if not self.running:
self.start_time = time.time()
self.running = True

def pause(self):
if self.running:
self.elapsed_time += time.time() - self.start_time
self.running = False

def reset(self):
self.running = False
self.start_time = 0
self.elapsed_time = 0

def get_elapsed_time(self) -> float:
if self.running:
return self.elapsed_time + time.time() - self.start_time
else:
return self.elapsed_time


@bootstrap.initialize
def main():
print("Stopwatch... [space]=stop/start, [l]ap, [r]eset, [q]uit (or ^C)")
stopwatch = Stopwatch()
if config.config["start"]:
stopwatch.start()

with input_utils.KeystrokeReader() as get_keystroke:
while True:
# Check / parse any keys.
key = get_keystroke(timeout_seconds=0.01)
if key:
if key == ' ':
if not stopwatch.running:
stopwatch.start()
else:
stopwatch.pause()
elif key == 'r':
print(" " * 50, end='\r')
stopwatch.reset()
elif key == 'l':
print(f"Lap: {stopwatch.get_elapsed_time():.5f}", end="\r\n")
elif key == 'q' or key == chr(3):
print()
return

# Update display.
print(f"Elapsed time: {stopwatch.get_elapsed_time():0.4f}", end="\r")
sys.stdout.flush()
return None


if __name__ == "__main__":
main()
125 changes: 125 additions & 0 deletions examples/timer/timer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/usr/bin/env python3

"""
A (unix terminal) countdown timer utility.
"""

import logging
import sys
import time
from typing import Optional

from pyutils import argparse_utils, bootstrap, config, input_utils

logger = logging.getLogger(__name__)
args = config.add_commandline_args(f'({__file__})', f'Args related to {__file__}')
args.add_argument(
"time_limit",
type=argparse_utils.valid_duration,
help="The time limit of the countdown timer.",
)
args.add_argument(
"--infinite",
action="store_true",
help="After the timer expires, reset and start again forever.",
)
args.add_argument(
"--pause_between",
action="store_true",
help="Should we pause between adjacent timer runs.",
)


class Timer:
def __init__(self, duration: float):
self.running = True
self.start = time.time()
self.original_duration = duration
self.duration = duration
self.run_number = 1
self.elapsed_before_pause = 0.0

def get_remaining_time(self) -> float:
return self.original_duration - self.get_elapsed_time()

def get_elapsed_time(self) -> float:
if self.running:
now = time.time()
return now - self.start + self.elapsed_before_pause
else:
return self.elapsed_before_pause

def is_expired(self):
elapsed = self.get_elapsed_time()
return elapsed >= self.original_duration

def reset(self):
self.run_number += 1
self.start = time.time()
self.duration = self.original_duration
self.elapsed_before_pause = 0
self.running = True

def reset_and_pause(self):
self.run_number += 1
self.start = time.time()
self.duration = self.original_duration
self.elapsed_before_pause = 0
self.running = False

def pause(self):
self.elapsed_before_pause = self.get_elapsed_time()
self.running = False

def unpause(self):
self.start = time.time()
self.duration = self.original_duration - self.elapsed_before_pause
self.running = True


@bootstrap.initialize
def main() -> Optional[int]:
duration = config.config["time_limit"]
timer = Timer(duration.seconds)
print("Countdown timer... [space]=pause/unpause, [r]eset, [q]uit (or ^C).")

with input_utils.KeystrokeReader() as get_keystroke:
while True:

# Check for input / parse any.
key = get_keystroke(timeout_seconds=0.01)
if key:
if key == ' ':
if timer.running:
timer.pause()
else:
timer.unpause()
elif key == 'r':
print(end="\r\n")
timer.reset()
elif key == 'q' or key == chr(3):
sys.exit(0)

# Display remaining countdown.
remaining = timer.get_remaining_time()
print(f"{remaining:0.2f} ", end='\r')

# Done?
if timer.is_expired():
if not config.config["infinite"]:
print("Beep, beep, beep!", end="\r\n")
sys.exit(0)

print(
f"Run number {timer.run_number} expired... Beep, beep, beep!",
end="\r\n",
)
if config.config["pause_between"]:
timer.reset_and_pause()
else:
timer.reset()
return None


if __name__ == '__main__':
main()

0 comments on commit 0f35017

Please sign in to comment.