-
Notifications
You must be signed in to change notification settings - Fork 1
/
ipse
executable file
·53 lines (45 loc) · 3.77 KB
/
ipse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env python3
# This program parses an ipse file, or series of ipse files, and prints one random pearl of wisdom from them. It's a lot like `fortune` on unix except with a different file format: instead of separating with \n%\n, like in fortune files, ipse files are separated by \n\n (a blank line). \ alone on its own line will be reinterpreted as a blank line. (There is no way to represent a \ on its own line.). The ipse file format is rather adhoc and most ipse files in the world end with .txt instead of .ipse. Files are assumed to be utf-8, probably.
# Like all great programs, this one has a curious name. "Ipse", from the latin phrase "ipse dixit", meaning "he himself said it". "Obiter dicta" ("other things said") would have been a better name for this program, perhaps, but ipse dixit has such a pleasing sound.
# Although there is no way to "weight" the documents, there's nothing that stops you from passing in the name of the same file twice if you want it to be twice as likely to be picked.
# This program was generated (and then modified) from chatgpt (4o mini) using this prompt: python script that reads all the files given as command-line arguments, splits them on \n\n, turns \n\\\n into \n, and picks one of the results randomly. Write as tersely as possible. You are John Carmack btw. add shebang and also if 0 arguments are given print a help message explaining what the program does. Oh also input into stdin counts as a file. use python type annotations on this where appropriate.
# The output of the program was impressive, except that I expected it to work because this is a very basic type of script... and also I subsequently had to edit the script to correct logic error lol. Still, cool stuff.
import sys
import os
import random
from typing import TextIO, NoReturn
import argparse
parser = argparse.ArgumentParser(
description=""" Ipse reads files, splits on \\n\\n, replaces backslash-only lines with blank lines, and picks one part randomly.
Stdin counts as a file if the script is used in a pipeline.
If no arguments are given (and the script is being used interactively (not in a pipeline)), ~/.ipse is used implicitly.
If directories are passed in as arguments, all files (and directories) within those dirs will be recursively included.""",
)
#todo: maybe just let the use pass in a [0-9]* as an argument to select a number of output, without a flag?
#todo: maybe let the splitter of the ipse file be determined by the character before an alphabetical character in a file?
parser.add_argument('ipse_files_and_dirs', nargs="*")
parser.add_argument('-n', '--number', type=int, default=1, help="The number of randomly-selected parts to display. The count of said. How many of them.")
parser.add_argument('-f', '--filter', type=str, default="", help="If provided, ipse will only return parts that contain the given string as a substring.")
p_args = parser.parse_args()
def process_file(filelike: TextIO):
return [ part.replace('\n\\\n', '\n\n') for part in filelike.read().split('\n\n') if p_args.filter in part ]
parts: list[str] = []
if not sys.stdin.isatty():
parts.extend(process_file(sys.stdin))
args: list[str] = p_args.ipse_files_and_dirs
if sys.stdin.isatty() and len(args) == 0:
ipse_default_path = os.path.expanduser("~/.ipse")
if os.path.exists(ipse_default_path):
args = [ipse_default_path]
else:
exit(f"Ipse was invoked but there were no arguments and {ipse_default_path}, the default location, does not exist.")
for arg in args:
arg = os.path.expanduser(arg)
if os.path.isdir(arg):
args += [ os.path.join(arg, entry) for entry in os.listdir(arg) ]
else:
with open(arg) as f:
parts.extend(process_file(f))
if len(parts) == 0:
help()
print( ('─'*10).join(['\n'*2]*2).join(random.sample(parts, p_args.number)) )