Skip to content

Commit 650dbc8

Browse files
add timeout to prompt
1 parent aaf2b9f commit 650dbc8

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

base/util.jl

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -278,26 +278,45 @@ end
278278
getpass(prompt::AbstractString) = getpass(stdin, stdout, prompt)
279279

280280
"""
281-
prompt(message; default="") -> Union{String, Nothing}
281+
prompt(message; default="", timeout=nothing) -> Union{String, Nothing}
282282
283283
Displays the `message` then waits for user input. Input is terminated when a newline (\\n)
284284
is encountered or EOF (^D) character is entered on a blank line. If a `default` is provided
285-
then the user can enter just a newline character to select the `default`.
285+
then the user can enter just a newline character to select the `default`. A `timeout` in seconds
286+
greater than 0 can be provided, after which the default will be returned.
286287
287288
See also `Base.getpass` and `Base.winprompt` for secure entry of passwords.
288289
"""
289-
function prompt(input::IO, output::IO, message::AbstractString; default::AbstractString="")
290-
msg = !isempty(default) ? "$message [$default]: " : "$message: "
290+
function prompt(input::IO, output::IO, message::AbstractString; default::AbstractString="", timeout::Union{Nothing, Int} = nothing)
291+
if !isnothing(timeout) && timeout > 0
292+
msg = !isempty(default) ? "$message [$default] timeout $timeout seconds: " : "$message: "
293+
timeout_timer = Timer(timeout)
294+
else
295+
msg = !isempty(default) ? "$message [$default]: " : "$message: "
296+
timeout_timer = nothing
297+
end
291298
print(output, msg)
292-
uinput = readline(input, keep=true)
299+
t = @async readline(input, keep=true)
300+
while !istaskdone(t) && (!isnothing(timeout_timer) && isopen(timeout_timer))
301+
sleep(0.1)
302+
end
303+
if !isnothing(timeout_timer) && !istaskdone(t)
304+
try
305+
Base.throwto(t, InterruptException())
306+
catch
307+
end
308+
println(output, "timed out")
309+
return default
310+
end
311+
uinput = fetch(t)
293312
isempty(uinput) && return nothing # Encountered an EOF
294313
uinput = chomp(uinput)
295314
isempty(uinput) ? default : uinput
296315
end
297316

298317
# allow new prompt methods to be defined if stdin has been
299318
# redirected to some custom stream, e.g. in IJulia.
300-
prompt(message::AbstractString; default::AbstractString="") = prompt(stdin, stdout, message, default=default)
319+
prompt(message::AbstractString; default::AbstractString="",timeout::Union{Nothing, Int} = nothing) = prompt(stdin, stdout, message, default=default, timeout=timeout)
301320

302321
# Windows authentication prompt
303322
if Sys.iswindows()

0 commit comments

Comments
 (0)