Skip to content

Instantly share code, notes, and snippets.

@sazeygit
Last active December 29, 2022 15:13
Show Gist options
  • Save sazeygit/7078800da160e926882ecf2da624587f to your computer and use it in GitHub Desktop.
Save sazeygit/7078800da160e926882ecf2da624587f to your computer and use it in GitHub Desktop.
Display strings using a typing and a ticker effect. Typing effect can also be used to capture input.
import typer as t
def main(stdscr):
string = "Hello World!"
# Simple typing of a string
t.label(string)
# String on same line (default)
# Delay (ms) can be adjusted to your liking (default is 40ms)
t.label(string, delay=20, nl=0)
t.label(string, delay=60, nl=0)
# String on new line
t.label(string, on_nl=1)
t.endwin()
string = t.prompt("Enter string here: ", delay=50)
# label and ticker can be made to pause
t.ticker(string, delay=40, pause=0)
# iters governs the number of characters that are skipped over in the string
# Useful for very long strings
t.ticker(string, pause=1, iters=3)
t.endwin()
t.wrapper(main)
# A longer string - 1234567890
# Change log
# v1.1.1 - clean up for publication | 29/12
# v1.1 - added ticker() | 23/12
# v1 - where the dream began | 19-23/12
from curses import curs_set, newwin, endwin, getsyx, setsyx, raw, noraw, napms, echo, wrapper
# Set delay in ms, default is 40
delay = 40
# Type output onto terminal in a typewriter fashion
# Basically complete, is_prompt functionality missing
# delay: delay in ms, pause
def label(my_string=str, pause = 1, nl = 1, on_nl=0, delay=40):
# Set cursor invisible
curs_set(0)
raw()
# Basic error catching
try:
from curses import getsyx
except ModuleNotFoundError:
print("curses not installed. Use command `pip install curses` to install.")
return(1)
if my_string == '':
raise ValueError("[0x01] - String emtpy.")
if pause < 0 or pause > 1:
raise ValueError("[0x02] - 'pause' parameter bad value.")
if nl < 0 or nl > 1:
raise ValueError("[0x03] - 'nl' parameter bad value.")
if on_nl < 0 or on_nl > 1:
raise ValueError("[0x04] - 'on_nl' parameter bad value.")
# Initialise variables
i, y, x, b_y, b_x = 0, 0, 0, 0, 0
# Get current y and x positions
b_y = getsyx()[0]
b_x = getsyx()[1]
# Add new line at start of line if on_nl is set to 1
if on_nl == 1:
b_y += 1
b_x = 0
# Initialise text box
text_window = newwin(y, x, b_y, b_x)
# <output>
while i < len(my_string):
text_window.addch(my_string[i])
i += 1
napms(delay)
text_window.refresh()
# </output>
# Add a pause
if pause == 1:
text_window.getkey()
# Add new line at the end of output if flag nl is 1
if nl == 1:
setsyx(b_y + 1, 0)
# Reset screen
curs_set(1)
noraw()
# Function marquees input text, captures input as string and returns string
def prompt(my_string=str, delay=40, on_nl=0):
# Clear screen, set cursor invisible, set echo to true
# curs_set(0)
echo(True)
noraw()
# Initialise variables
i, y = 0, 0
input_string = ""
input_char = ''
# Initialise text box, on new line if needed
if on_nl == 1:
y = getsyx()[0]
text_window = newwin(0, 0, y, 0)
# Replicating label function, as textboxes are function level objects and are destroyed afterwards
try:
while i < len(my_string):
text_window.addch(my_string[i])
i += 1
napms(delay)
text_window.refresh()
except:
my_string = None
# Keep adding characters to string until Enter is pressed
while True:
input_char = text_window.get_wch()
if input_char == '\n':
break
input_string += str(input_char)
y, x = text_window.getyx()
text_window.addstr(y, x, '')
text_window.refresh()
setsyx(getsyx()[0], 0)
# Return input_string
return(input_string)
# Reset screen
curs_set(1)
echo(False)
def ticker(my_string=str, pause=1, delay=20, iters=1, nl=1):
# Initialisation as per usual
curs_set(0)
x = 0
text_window = newwin(0, 0, getsyx()[0], 0)
# Kludge to fix a bug I can't nail. If pause=0 and iters>1, the last
# character of my_string not print correctly.
if pause == 0:
iters = 1
# This loop iterates over each character in string in place, then repeats the same for each character in string
while x < len(my_string):
for r in range(len(my_string)):
# iters governs how many character are skipped over during iteration
text_window.addch(0, x, my_string[r//iters])
napms(delay)
text_window.refresh()
# This exact placement ensures the printed character is the right one
text_window.addch(0, x, my_string[x])
# Continue while loop
x += 1
# Standard stuff
if pause == 1:
text_window.getch()
if nl == 1:
setsyx(getsyx()[0] + 1, 0)
elif nl == 0:
setsyx(getsyx()[0], len(my_string))
curs_set(1)
@sazeygit
Copy link
Author

1_edit.mp4

@sazeygit
Copy link
Author

sazeygit commented Dec 29, 2022

TYPER.py

  • Display string using a typing effect | .label(pause, nl, on_nl, delay)

    • Can also return str output | .prompt(delay, on_nl)
  • Can also utilise a ticker effect | .ticker(pause, delay, iters, nl)

  • Minimal necessary functions imported from curses

  • All functions have adjustable delay, nl (new line) parameters

See typer-example.py for example

Bug list:

  • Weird bug where the last character is not printed correctly by .ticker(), if pause=0 and iters>1
    Current workaround: force iters=1 when pause=0 (kludgy I know)

Constructive criticism welcome but please remember this is my first project 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment