-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathchoice
More file actions
executable file
·94 lines (68 loc) · 2.08 KB
/
choice
File metadata and controls
executable file
·94 lines (68 loc) · 2.08 KB
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/env python3
"""
choice [OPTIONS...] CHOICES...
Pick a value at random among CHOICES using secure random.
Alternatively, choices may be provided on stdin.
For example:
# pick a random RGB color
choice red green blue
# pick a number between 1 and 10
seq 1 10 | choice
# pick a random file from ./dir/
find ./dir/ -print0 | choice -0
"""
import optparse
import random
import sys
import textwrap
system_random = random.SystemRandom()
def main() -> int:
p = optparse.OptionParser(usage=__doc__.strip())
p.add_option('-0', '--null', help='Choices on stdin are delimited by null',
action='store_true')
opts, args = p.parse_args()
mode = "args"
delimiter = "\n"
if opts.null:
mode = "stdin"
delimiter = "\0"
if mode == "stdin":
if args:
p.error("Cannot pass args with stdin mode")
choices = read_stdin(delimiter=delimiter)
elif mode == "args":
if len(args) > 0:
choices = args
else:
# if no choices in argv, use stdin as long as it isn't a tty
if sys.stdin.isatty():
p.print_help()
# p.error("Must provide choices in argv or stdin")
return 1
mode = "stdin"
choices = read_stdin(delimiter=delimiter)
else:
raise ValueError(f"Invalid mode {mode!r}")
if len(choices) == 0:
if mode == "stdin":
suffix = " (stdin was empty)"
else:
suffix = " (bug?)"
p.error("Must provide at least one choice" + suffix)
print(system_random.choice(choices))
return 0
def read_stdin(delimiter: str) -> list[str]:
"""
Read choices from stdin
"""
data = sys.stdin.read()
# return empty list on empty input, not [""]
if not data:
return []
# if delimiter is newline, strip trailing newline so we don't end up with
# an empty string choice
if delimiter == "\n":
data = data.rstrip("\n")
return data.split(delimiter)
if __name__ == '__main__':
sys.exit(main())