try running this code I guess:
# adapted from https://codepen.io/soulwire/pen/mErPAK?editors=1111
# formatted with replit format
# https://stackoverflow.com/questions/27674602/hide-traceback-unless-a-debug-flag-is-set
# moved "sys.tracebacklimit=0" to elsewhere
import sys
import random
import curses
from typing import List, TypeVar
from math import floor
from time import sleep
# initialize variables
# random CHARS
CHARS = "`-=~@#$%^&*_{}|[]\\;':/<>"
# Exception class for Curses/MatrixPrint
class LengthOfTextTooLong(Exception):
"""Exception to be raised when text is too long"""
class MatrixPrint:
"""
creates a new instance of MatrixPrint.
the first iteration will be ""
specify the delay of one iteration to the next (pause between update())
clears screen and hides cursor
"""
def __init__(
self,
delay: float = 0.025,
color: str = "\033[38;2;117;117;117m",
base_color: str = "\033[38;2;211;211;211m",
max_limit: int = 150,
) -> None:
self.old = ""
self.frame = 0
self.queue = []
self.delay = delay
self.col = color
self.base = base_color
self.max_limit = max_limit
self.chance = 0.28
print("\033c\033[?25l", end="", flush=True)
def print(self, text: str) -> None:
"""
prints text in animation. The text will go from one text to the next. Default text is "" in the beginning.
It creates a queue which contains before/after and allowed frames for random CHARS.
"""
if len(text) > self.max_limit or text.count("\n") >= 1:
sys.tracebacklimit = 0 # https://stackoverflow.com/questions/27674602/hide-traceback-unless-a-debug-flag-is-set
# added space between decleration
raise LengthOfTextTooLong(
"Text is too long. Consider splitting the message into two message"
)
self.queue = []
for i in range(max(len(text), len(self.old))):
start = floor(random.random() * 40)
end = start + floor(random.random() * 40)
# start and end are the allowed frames
self.queue.append(
[
"" if i >= len(text) else text[i], # after
"" if i >= len(self.old) else self.old[i], # before
start, # start
end, # end
"", # char
]
)
self.frame = 0
self.update()
self.old = text
def rand_char(self) -> str:
"""
random character with color
"""
return f"{self.col}{random.choice(CHARS)}\033[0m"
def update(self) -> None:
"""
prints next permutation of text.
Basically:
* it will print some random CHARS in existing places if within allowed frame
* it will print some new random CHARS if within allowed frame in non-existing places to create a longer string or to make the string smaller
"""
while True:
output = ""
done = 0
for i in range(len(self.queue)):
after, before, start, end, char = self.queue[i]
# num finished++
if self.frame >= end:
done += 1
output += f"{self.base}{after}\033[0m"
elif self.frame >= start: # self.frame (start, end]
if (
char == ""
or random.random() < self.chance
and (char not in "\t\n")
): # char is None (that is, it is not really there yet so you wanna place a rand_char first) or choose to place
self.queue[i][4] = self.rand_char()
output += self.queue[i][4]
else: # else not in frame
output += f"{self.base}{before}\033[0m"
if done == len(self.queue):
return print("\033c", output, end="", flush=True, sep="")
self.frame += 1
print("\033c", output, end="", flush=True, sep="")
sleep(self.delay)
class CursesMatrixPrint:
"""
creates a new instance of CursesMatrixPrint.
the first iteration will be ""
specify the delay of one iteration to the next (pause between update())
clears screen and hides cursor
initializes curses.window
creates color codes 0 -> 256
please specify in curses color code if you would like to specify it
"""
def __init__(
self,
delay: float = 0.025,
color: str = 242,
base_color: str = 0,
max_limit: int = 150,
) -> None:
self.old = ""
self.frame = 0
self.queue = []
self.delay = delay
self.col = color
self.base = base_color
self.chance = 0.28
self.max_limit = max_limit
self.screen = curses.initscr()
print("\033[?25l", end="", flush=True)
# https://stackoverflow.com/questions/18551558/how-to-use-terminal-color-palette-with-curses
# used just some of it
# from main
curses.start_color()
curses.use_default_colors()
for i in range(0, curses.COLORS):
curses.init_pair(i + 1, i, -1)
def print(self, text: str) -> None:
"""
prints text in animation. The text will go from one text to the next. Default text is "" in the beginning.
It creates a queue which contains before/after and allowed frames for random CHARS.
"""
if len(text) > self.max_limit or text.count("\n") >= 1:
sys.tracebacklimit = 0 # https://stackoverflow.com/questions/27674602/hide-traceback-unless-a-debug-flag-is-set
# added space between decleration
raise LengthOfTextTooLong(
"Text is too long. Consider splitting the message into two message"
)
self.queue = []
if self.old != "":
self.screen.clear()
for i in range(max(len(text), len(self.old))):
start = floor(random.random() * 40)
end = start + floor(random.random() * 40)
# start and end are the allowed frames
self.queue.append(
[
"" if i >= len(text) else text[i], # after
"" if i >= len(self.old) else self.old[i], # before
start, # start
end, # end
"", # char
]
)
self.frame = 0
self.update()
self.old = text
def rand_char(self) -> str:
"""
random character
"""
return random.choice(CHARS)
def update(self) -> None:
"""
prints next permutation of text.
Basically:
* it will print some random CHARS in existing places if within allowed frame
* it will print some new random CHARS if within allowed frame in non-existing places to create a longer string or to make the string smaller
"""
while True:
done = 0
for i in range(len(self.queue)):
after, before, start, end, char = self.queue[i]
# num finished++
if self.frame >= end:
done += 1
if after != "":
self.screen.addch(after, curses.color_pair(self.base))
elif self.frame >= start: # self.frame (start, end]
if (
char == ""
or random.random() < self.chance
and (char not in "\t\n")
): # char is None (that is, it is not really there yet so you wanna place a rand_char first) or choose to place
self.queue[i][4] = self.rand_char()
if self.queue[i][4] != "":
self.screen.addch(self.queue[i][4], curses.color_pair(self.col))
elif before != "":
self.screen.addch(before, self.base)
elif after != "":
self.screen.addch(after, self.base)
else: # else not in frame
if before != "":
self.screen.addch(before, curses.color_pair(self.base))
if done == len(self.queue):
return self.screen.refresh()
self.frame += 1
sleep(self.delay)
self.screen.refresh()
self.screen.clear()
matrix = MatrixPrint()
curses_matrix = CursesMatrixPrint()
Matrix = TypeVar("Matrix", MatrixPrint, CursesMatrixPrint)
def print_phrases(
phrases: List[str], matrix: Matrix = curses_matrix, delay: float = 0.8
) -> None:
"""
prints all phrases with a specified delay using MatrixPrint or CursesMatrixPrint. See Curses/MatrixPrint.print
"""
for i in phrases:
matrix.print(i)
sleep(delay)
def print_paragraph(
paragraph: str,
deliminator: str = ".",
matrix: Matrix = curses_matrix,
delay: float = 0.8,
include_deliminator: bool = True,
) -> None:
"""
splits the paragraph by the split and then prints as much as possible. That is, take ['hello', 'world', '...' * 100] it will print 'hello world' then '.' * 150 then '.' * 150
"""
words = paragraph.split(deliminator)
i = 0
while i < len(words):
current = ""
if len(words[i]) < matrix.max_limit:
while (
i < len(words)
and len(current)
+ len(words[i])
+ (len(deliminator) if include_deliminator else 0)
< matrix.max_limit
):
current += words[i]
if include_deliminator:
current += deliminator
i += 1
matrix.print(current)
else: # split current into chunks
# https://pythonexamples.org/python-split-string-into-specific-length-chunks/
# changed from [str[i:i+n] for i in range(0, len(str), n)]
# to [words[i][k: k + matrix.max_limit] for k in range(0, len(words), matrix.max_limit)]
# to fit purposes
for j in [
words[i][k : k + matrix.max_limit]
for k in range(0, len(words[i]), matrix.max_limit)
]:
matrix.print(j)
sleep(delay)
i += 1
sleep(delay)
# hex to rgb converter https://www.colorhexa.com/
# color from https://www.designwizard.com/wp-content/uploads/2019/03/colorCombination_11.jpg
matrix = MatrixPrint(
0.025,
color="\033[38;2;0;99;178m",
base_color="\033[38;2;156;195;213m",
max_limit=100,
)
phrases = [
"I like to think",
"That sometimes,",
"The impossible is possible",
"And that our understanding of the universe can",
"be turned upside down",
]
print_paragraph(
"Made by bigminiboss. Idea from https://codepen.io/soulwire/pen/mErPAK?editors=1111. And was adapted by me into python. Now for the famous sequence :)",
deliminator=".",
matrix=matrix,
delay=2,
include_deliminator=True,
)
while True:
print_phrases(phrases, matrix)