Created
December 27, 2023 14:47
-
-
Save qexat/6ba1b359b2bd5e921d316aebb1472cfb to your computer and use it in GitHub Desktop.
terminal slides lol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import abc | |
| import collections.abc | |
| import os | |
| import shutil | |
| import sys | |
| import time | |
| import typing | |
| class RGBColor(typing.NamedTuple): | |
| red: int | |
| green: int | |
| blue: int | |
| def to_printable(self) -> str: | |
| return "\x1b[38;2;%d;%d;%dm{}\x1b[39m" % self | |
| class RGBAColor(typing.NamedTuple): | |
| red: int | |
| green: int | |
| blue: int | |
| alpha: float = 1.0 | |
| def remove_alpha(self) -> RGBColor: | |
| return RGBColor(*self[:-1]) | |
| def flatten_component(fgc: int, bgc: int, opacity: float) -> int: | |
| return int(((fgc - bgc) * opacity) + bgc) | |
| def flatten_foreground( | |
| fg: RGBAColor, | |
| bg: RGBColor, | |
| strategy: collections.abc.Callable[[int, int, float], int] | None = None, | |
| ) -> RGBColor: | |
| _strategy = strategy or flatten_component | |
| return RGBColor( | |
| *(_strategy(c, bg[i], fg.alpha) for i, c in enumerate(fg.remove_alpha())) | |
| ) | |
| T_contra = typing.TypeVar("T_contra", contravariant=True) | |
| class SupportsWrite(typing.Protocol[T_contra]): | |
| @abc.abstractmethod | |
| def write(self, __s: T_contra, /) -> typing.Any: | |
| pass | |
| def set_bg(color: RGBColor, *, file: SupportsWrite[str] | None = None) -> None: | |
| _file = file or sys.stdout | |
| _file.write("\x1b[48;2;%d;%d;%dm" % color) | |
| def reset_bg(*, file: SupportsWrite[str] | None = None) -> None: | |
| _file = file or sys.stdout | |
| _file.write("\x1b[49m") | |
| def init_seq() -> None: | |
| sys.stdout.write("\x1b[?1049h") | |
| sys.stdout.write("\x1b[2J\x1b[H") | |
| sys.stdout.write("\x1b[?25l") | |
| def end_seq() -> None: | |
| print("\x1b[?1049l\x1b[?25h") | |
| def write_string( | |
| message: str, | |
| x: int, | |
| y: int, | |
| *, | |
| delay: float = 0.0, | |
| release: float = 0.0, | |
| ) -> None: | |
| time.sleep(delay) | |
| sys.stdout.write(f"\x1b[{x};{y}H") | |
| sys.stdout.write(message) | |
| sys.stdout.flush() | |
| time.sleep(release) | |
| def write_strings( | |
| messages: collections.abc.Iterable[str], | |
| x: int, | |
| y: int, | |
| *, | |
| delay: float = 0.0, | |
| release: float = 0.0, | |
| postdelay: float = 0.0, | |
| ) -> None: | |
| for message in messages: | |
| write_string(message, x, y, delay=delay, release=release) | |
| time.sleep(postdelay) | |
| def print_seq( | |
| message: str, | |
| message_length: int | None = None, | |
| /, | |
| fg: RGBColor = RGBColor(255, 255, 255), | |
| bg: RGBColor = RGBColor(0, 0, 0), | |
| framerate: int = 25, | |
| sustain: float = 1.0, | |
| release: float = 0.0, | |
| ) -> None: | |
| width, height = shutil.get_terminal_size() | |
| _message_length = len(message) if message_length is None else message_length | |
| top = (height - 1) // 2 | |
| left = (width - _message_length) // 2 | |
| fadein_frames = [ | |
| flatten_foreground(RGBAColor(*fg, (a / framerate)), bg) | |
| for a in range(0, framerate) | |
| ] | |
| fadeout_frames = list(reversed(fadein_frames)) | |
| fadein = list(map(lambda a: a.to_printable().format(message), fadein_frames)) | |
| fadeout = list(map(lambda a: a.to_printable().format(message), fadeout_frames)) | |
| set_bg(bg) | |
| for _ in range(height): | |
| print(" " * width) | |
| write_strings(fadein, top, left, release=1 / framerate, postdelay=sustain) | |
| write_strings(fadeout, top, left, release=1 / framerate, postdelay=release) | |
| def main() -> int: | |
| FRAMERATE = 100 | |
| fg = RGBColor(255, 255, 255) | |
| bg = RGBColor(0, 0, 0) | |
| mom_bg = RGBColor(48, 24, 0) | |
| son_bg = RGBColor(0, 24, 48) | |
| try: | |
| init_seq() | |
| print_seq( | |
| "© 2007 The Pokémon Company Inc.", | |
| fg=fg, | |
| bg=bg, | |
| framerate=FRAMERATE, | |
| release=0.5, | |
| ) | |
| print_seq("Can you come out?", bg=mom_bg, framerate=FRAMERATE) | |
| print_seq("Mom, I am gay.", bg=son_bg, framerate=FRAMERATE) | |
| print_seq( | |
| "I know that, silly. Come out to the car.", bg=mom_bg, framerate=FRAMERATE | |
| ) | |
| print_seq("Car, I am gay.", bg=son_bg, framerate=FRAMERATE) | |
| finally: | |
| end_seq() | |
| return os.EX_OK | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment