Compare commits

...

6 Commits

Author SHA1 Message Date
73cdf060b7
Add type hints to function signatures
For better code intelligence
2025-06-01 22:01:45 -04:00
8de77c5c21
Use pathlib in test_user_car 2025-06-01 22:01:45 -04:00
4cc4b2ead4
replace exit() and quit() with sys.exit() 2025-06-01 22:01:45 -04:00
7a74050c5d
Rewrite print_help to a single string 2025-06-01 22:01:45 -04:00
6d4e7c7914
Rewrite car templates as list of strings
This lets us trim all the trailing whitespace in the file automatically.
2025-06-01 22:01:44 -04:00
29a8ffa91e
Update details in file header for the fork.
Also remove trailing whitespace in the header.
2025-06-01 22:01:44 -04:00

View File

@ -1,17 +1,16 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
## _ _ _ _ _ _ ## _ _ _ _ _ _
## | |_(_) |__| |___ | |_ _ _ __ _(_)_ _ ## | |_(_) |__| |___ | |_ _ _ __ _(_)_ _
## | _| | / _` / -_)| _| '_/ _` | | ' \ ## | _| | / _` / -_)| _| '_/ _` | | ' \
## \__|_|_\__,_\___(_)__|_| \__,_|_|_||_| ## \__|_|_\__,_\___(_)__|_| \__,_|_|_||_|
## ##
## tilde.train is an instance of TerminalTrain. It was originally developed ## tilde.train is an instance of TerminalTrain. It was originally developed
## by cmccabe on tilde.town but is now maintained in tildegit with the main ## by cmccabe on tilde.town (https://tildegit.org/cmccabe/TerminalTrain) but is now
## development ocurring on rawtext.club. ## maintained by vilmibm.
## ##
## If you want to contribute to code improvement, or if you have suggestions ## If you want to contribute code improvements, create a pull request here:
## for cmccabe, create a pull request here: https://tildegit.org/cmccabe/TerminalTrain ## https://git.tilde.town/vilmibm/tilde-train
## or email cmccabe at cmccabe@rawtext.club
## ##
## ----------------- ## -----------------
## ##
@ -27,7 +26,7 @@
## * turn main loop into a function, so cmd line arg reader can call it (with -p) and quit. ## * turn main loop into a function, so cmd line arg reader can call it (with -p) and quit.
## * figure out why tilde.train doesn't work in some terminals (sthg sthg unicode...) ## * figure out why tilde.train doesn't work in some terminals (sthg sthg unicode...)
## * BUGFIX-1 - something about inclusion default cars adding extra "links" to the train. ## * BUGFIX-1 - something about inclusion default cars adding extra "links" to the train.
## * the -p (print train) option should print all cars, not limited to the max_cars value. ## * the -p (print train) option should print all cars, not limited to the max_cars value.
## * related to BUGFIX-1, that seems to impact spacers (links) between cars. ## * related to BUGFIX-1, that seems to impact spacers (links) between cars.
## * allow users to create multiple frames so their cars can be animated (difficulty=med+) ## * allow users to create multiple frames so their cars can be animated (difficulty=med+)
## * allow user configurable speed and number of train cars ## * allow user configurable speed and number of train cars
@ -43,6 +42,8 @@ import curses
from signal import signal, SIGINT from signal import signal, SIGINT
import time ## allowing the loop steps of train animation to be slowed import time ## allowing the loop steps of train animation to be slowed
import string ## for input validation import string ## for input validation
from inspect import cleandoc
from pathlib import Path
traincarFN = ".choochoo" traincarFN = ".choochoo"
max_x = 35 ## max length of train car. max_x = 35 ## max length of train car.
@ -53,79 +54,84 @@ print_train = False ## print train to file (instead of the screen scroll)
train = [""]*max_y ## empty train of correct height. train = [""]*max_y ## empty train of correct height.
cars = [] cars = []
engine = r""" ____ engine = [
|____| ------------ r" ____ ",
| | === | ------ | r" |____| ------------",
___| |__| |_____| | O | | r" | | === | ------ |",
| | | |__/V\_| | r" ___| |__| |_____| | O | |",
[[ | | r" | | | |__/V\_| |",
| | ------------ | ~town | r" [[ | |",
|__|______________|__________| r" | | ------------ | ~town |",
//// / _\__/__\__/__\ / \ r" |__|______________|__________|",
//// \__/ \__/ \__/ \__/ """ r" //// / _\__/__\__/__\ / \ ",
engine = engine.split("\n") r"//// \__/ \__/ \__/ \__/ ",
]
caboose = r""" || caboose = [
============= || r" || ",
=========| |========== r" ============= || ",
| ---- ---- | r"=========| |========== ",
| | | | | | r" | ---- ---- | ",
| ---- ---- | r" | | | | | | ",
| tilde.town railways | r" | ---- ---- | ",
==| |== r" | tilde.town railways | ",
== - / \-/ \-----/ \-/ \ - == r"==| |== ",
\__/ \__/ \__/ \__/ """ r"== - / \-/ \-----/ \-/ \ - == ",
caboose = caboose.split("\n") r" \__/ \__/ \__/ \__/ ",
]
default_car = r""" ----------------------------
| |
| YOUR TRAIN CAR HERE! |
| Just create a |
| ~/.choochoo file! |
| __ __ __ __ |
- / \-/ \------/ \-/ \ -
\__/ \__/ \__/ \__/"""
default_car = default_car.split("\n")
default_car = [
r" ---------------------------- ",
r"| |",
r"| YOUR TRAIN CAR HERE! |",
r"| Just create a |",
r"| ~/.choochoo file! |",
r"| __ __ __ __ |",
r" - / \-/ \------/ \-/ \ - ",
r" \__/ \__/ \__/ \__/ ",
]
def print_help(): def print_help():
print("") print(
print("~ ~ Hooray! You've found the tilde.train! ~ ~") cleandoc(
print("") f"""
print("To add your own car to a future train, create") ~ ~ Hooray! You've found the tilde.train! ~ ~
print("a .choochoo file in your home directory and")
print("make sure it is 'other' readable, for example:") To add your own car to a future train, create
print("") a .choochoo file in your home directory and
print(" chmod 644 ~/.choochoo") make sure it is 'other' readable, for example:
print("")
print("The file should contain an ascii drawing of a") chmod 644 ~/.choochoo
print("train car no more than " + str(max_x) + " characters wide")
print("and " + str(max_y) + " characters tall.") The file should contain an ascii drawing of a
print("") train car no more than {max_x} characters wide
print("Only printable ascii characters are accepted for now.") and {max_y} characters tall.
print("Run the command again followed by a -t switch to test")
print("your .choochoo file and report any non accepted chars.") Only printable ascii characters are accepted for now.
print("") Run the command again followed by a -t switch to test
print("Each train contains a random selection of cars") your .choochoo file and report any non accepted chars.
print("from across tilde.town user home directories.")
print("Don't worry, yours will be coming around the") Each train contains a random selection of cars
print("bend soon!") from across tilde.town user home directories.
print("") Don't worry, yours will be coming around the
print("~ ~ ~ ~ ~ ~") bend soon!
print("")
~ ~ ~ ~ ~ ~
"""
)
)
def test_user_car(): def test_user_car():
username = getpass.getuser() fname = Path.home() / traincarFN
fname = "/home/" + username + "/" + traincarFN
try: try:
myfile = open(fname, 'r') choochoo_string = fname.read_text("utf-8")
except: except OSError as err:
print("ERROR: Couldn't open " + fname) raise OSError(
print("Either it doesn't exist, or is not readble by the tilde.train script.") f"Couldn't open {fname}\n"
exit() "Either it doesn't exist, or is not readble by the tilde.train script."
) from err
choochoo_string = myfile.read()
choochoo_list = choochoo_string.split("\n") choochoo_list = choochoo_string.split("\n")
car = "\n".join(choochoo_list) car = "\n".join(choochoo_list)
@ -160,7 +166,7 @@ def test_user_car():
print(string.printable.strip()) print(string.printable.strip())
print("") print("")
print("Yours contained " + bad_chars) print("Yours contained " + bad_chars)
exit() sys.exit(1)
# print("") # print("")
# print("Test results:") # print("Test results:")
@ -171,27 +177,24 @@ def test_user_car():
if train_height > max_y+1: if train_height > max_y+1:
print("FAIL. Your train car is too tall.") print("FAIL. Your train car is too tall.")
print("It should be no taller than " + str(max_y) + " lines in height.") print("It should be no taller than " + str(max_y) + " lines in height.")
myfile.close() sys.exit(1)
exit()
if train_length > max_x: if train_length > max_x:
print("FAIL. Your train car is too long.") print("FAIL. Your train car is too long.")
print("It should be no longer than " + str(max_x) + " characters in length.") print("It should be no longer than " + str(max_x) + " characters in length.")
myfile.close() sys.exit(1)
exit()
print("PASS. Your train car will work on the tilde.town tracks! :)") print("PASS. Your train car will work on the tilde.town tracks! :)")
myfile.close() sys.exit()
exit()
def link_car(car): def link_car(car: list[str]):
for idx,row in enumerate(car): for idx,row in enumerate(car):
car[idx] = " " + row car[idx] = " " + row
car[len(car)-3] = "+" + car[len(car)-3][1:] car[len(car)-3] = "+" + car[len(car)-3][1:]
car[len(car)-2] = "+" + car[len(car)-2][1:] car[len(car)-2] = "+" + car[len(car)-2][1:]
return car return car
def validate_car(car): def validate_car(car: list[str]):
## this function (1) checks that a train car isn't too tall or too long ## this function (1) checks that a train car isn't too tall or too long
## (2) pads it vertically or on the right side if it is too short or if ## (2) pads it vertically or on the right side if it is too short or if
## not all lines are the same length and (3) removes bad characters. ## not all lines are the same length and (3) removes bad characters.
@ -241,20 +244,20 @@ def print_all_cars():
choochoo_list = choochoo_string.split("\n") choochoo_list = choochoo_string.split("\n")
if len(choochoo_list) > max_y+1: if len(choochoo_list) > max_y+1:
continue ## the train car was too tall; skip it. continue ## the train car was too tall; skip it.
car = validate_car(choochoo_list) ## printing is only a DEBUG feature. car = validate_car(choochoo_list) ## printing is only a DEBUG feature.
if car != 0: if car != 0:
print("") print("")
print(fname + ":") print(fname + ":")
print("\n".join(car)) ## print the car to stdout print("\n".join(car)) ## print the car to stdout
## HOW TO CLOSE THE FILE HANDLE? fname.close(), close(fname), ...? ## HOW TO CLOSE THE FILE HANDLE? fname.close(), close(fname), ...?
except: except:
pass; pass;
# print "Cannot open " + fname # for debuggering purposes # print "Cannot open " + fname # for debuggering purposes
def chuggachugga(stdscr): def chuggachugga(stdscr: curses.window):
curses.curs_set(0) curses.curs_set(0)
h, w = stdscr.getmaxyx() h, w = stdscr.getmaxyx()
x_pos = w-1 x_pos = w-1
@ -296,24 +299,24 @@ def chuggachugga(stdscr):
def handler(signal_received, frame): def handler(signal_received, frame):
print("Oops. The train broke. The engineer is looking into it!") print("Oops. The train broke. The engineer is looking into it!")
print("(Note: the train does not work in all terminals yet.)") print("(Note: the train does not work in all terminals yet.)")
exit(0) sys.exit(1)
default_car = validate_car(default_car) default_car = validate_car(default_car)
if len(sys.argv) == 2 and ("-h" in sys.argv[1] or "help" in sys.argv[1]): if len(sys.argv) == 2 and ("-h" in sys.argv[1] or "help" in sys.argv[1]):
print_help() print_help()
quit() sys.exit()
if len(sys.argv) == 2 and ("-t" in sys.argv[1] or "test" in sys.argv[1]): if len(sys.argv) == 2 and ("-t" in sys.argv[1] or "test" in sys.argv[1]):
test_user_car() test_user_car()
quit() sys.exit()
if len(sys.argv) == 2 and ("-p" in sys.argv[1] or "print" in sys.argv[1]): if len(sys.argv) == 2 and ("-p" in sys.argv[1] or "print" in sys.argv[1]):
print_train = True print_train = True
if len(sys.argv) == 2 and ("-a" in sys.argv[1] or "all" in sys.argv[1]): if len(sys.argv) == 2 and ("-a" in sys.argv[1] or "all" in sys.argv[1]):
print_all_cars() print_all_cars()
quit() sys.exit()
## start a loop that collects all .choochoo files and processes on in each loop ## start a loop that collects all .choochoo files and processes on in each loop
@ -362,7 +365,7 @@ if print_train:
print("<pre>") print("<pre>")
print(train_str) print(train_str)
print("</pre>") print("</pre>")
quit() sys.exit()
pad_str = " "*train_len pad_str = " "*train_len
train.insert(0,pad_str) train.insert(0,pad_str)