-
Notifications
You must be signed in to change notification settings - Fork 43
/
util.jl
124 lines (101 loc) · 2.99 KB
/
util.jl
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# This file is a part of DataDeps.jl. License is MIT.
"""
splitpath(path)
The opposite of `joinpath`,
splits a path unto each of its directories names / filename (for the last).
"""
function splitpath(path::AbstractString)
ret=String[]
prev_path = path
while(true)
path, lastpart = splitdir(path)
length(lastpart)>0 && pushfirst!(ret, lastpart)
length(path)==0 && break
if prev_path==path
# catch the casewhere path begins with a root
pushfirst!(ret, path)
break
end
prev_path = path
end
return ret
end
########################################
# Environment variable stuff
"""
env_bool(key)
Checks for an environment variable and fuzzy converts it to a bool
"""
env_bool(key, default=false) = haskey(ENV, key) ? lowercase(ENV[key]) ∉ ["0","","false", "no"] : default
"""
env_list(key)
Checks for an environment variable and converts it to a list of strings, sperated with a colon
"""
env_list(key, default=String[]) = haskey(ENV, key) ? split(ENV[key], ":") : default
#########################################
# User input stuff
"""
better_readline(stream = stdin)
A version of `readline` that does not immediately return an empty string if the stream is closed.
It will attempt to reopen the stream and if that fails then throw an error.
"""
function better_readline(stream = stdin)
if !isopen(stream)
Base.reseteof(stream)
isopen(stream) || throw(Base.IOError("Could not open stream.", -1))
end
return readline(stream)
end
"""
bool_input
Prompted the user for a yes or no.
"""
function input_bool(prompt="")::Bool
input_choice(prompt, 'y','n')=='y'
end
"""
input_choice
Prompted the user for one of a list of options
"""
function input_choice(prompt, options::Vararg{Char})::Char
for _ in 1:100
println(prompt)
println("["*join(options, '/')*"]")
response = better_readline()
length(response)==0 && continue
reply = lowercase(first(response))
for opt in lowercase.(options)
reply==opt && return opt
end
end
error(
"Either user provided invalid input 100 times; or something has" *
"gone wrong with the IO reading. Please comment on: \n\t" *
"https://github.com/oxinabox/DataDeps.jl/issues/104"
)
end
"""
input_choice
Prompts the user for one of a list of options.
Takes a vararg of tuples of Letter, Prompt, Action (0 argument function)
Example:
```
input_choice(
('A', "Abort -- errors out", ()->error("aborted")),
('X', "eXit -- exits normally", ()->exit()),
('C', "Continue -- continues running", ()->nothing)),
)
```
"""
function input_choice(options::Vararg{Tuple{Char, <:AbstractString, Any}})
acts = Dict{Char, Any}()
prompt = ""
chars = Char[]
for (cc, prmt, act) in options
prompt*="\n [$cc] $prmt"
push!(chars, cc)
acts[lowercase(cc)] = act
end
prompt*="\n"
acts[input_choice(prompt, chars...)]()
end