Skip to content

Conversation

mkitti
Copy link
Contributor

@mkitti mkitti commented Aug 26, 2021

Closes #38522

This is an updated version of #38522 (and also succeeds #21362, #38307), that uses a REPL backend Abstract Syntax Tree transform in order to implement the hint if the user just types exit.

One advantage of using an AST transform is that the hint and its small overhead can be removed if desired. Another is that the line string entered does not need to be parsed again.

julia> exit
suggestion: To exit Julia, use Ctrl-D, or type exit() and press enter.
exit (generic function with 2 methods)

julia> using REPL

# Remove hint and associated overhead
julia> filter!(!=(REPL.print_exit_hint), Base.active_repl_backend.ast_transforms) 
1-element Vector{Any}:
 softscope (generic function with 1 method)

julia> exit
exit (generic function with 2 methods)

The hint is conscious of if Main.exit has been redefined. It will not print the hint in that case.

julia> exit = 2
2

julia> exit
2

julia> exit()
ERROR: MethodError: objects of type Int64 are not callable
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

julia> exit = Base.exit
exit (generic function with 2 methods)

julia> exit
suggestion: To exit Julia, use Ctrl-D, or type exit() and press enter.
exit (generic function with 2 methods)

An implementation note is that this does not use Base.isbindingresolved(Main, :exit) && isdefined(Main, :exit) per #38522 (comment). Compiling isdefined(Main, :exit) will result in the :exit binding being resolved in Main, which defeats the purpose. It is also insufficient since what we really want to know is if Main.exit is Base.exit. Therefore, the if Main.exit === Base.exit statement is returned as part of the AST transform. This allows Main.exit to be redefined as above while checking if exit is what we expect it to be.

This pull request has been rebased on afc504b.

To handle the situation where the user types quit or quit() see #41990.

@mkitti
Copy link
Contributor Author

mkitti commented Aug 26, 2021

One problem with this is the suggestion is going out over stdout via println. Preferably, we would obtain an IO object from the REPL's terminal.

@mkitti
Copy link
Contributor Author

mkitti commented Aug 27, 2021

While I do think the AST transform is a good way to detect something like this in general, what we really need is a REPL specific display that just usually just calls Base.display.

@DilumAluthge DilumAluthge added the triage This should be discussed on a triage call label Nov 2, 2021
@DilumAluthge
Copy link
Member

Let's see if triage can help answer some of the questions regarding the implementation.

@oscardssmith oscardssmith removed the triage This should be discussed on a triage call label Nov 4, 2021
@mkitti
Copy link
Contributor Author

mkitti commented Nov 4, 2021

Triage suggests customizing Base.show for typeof(exit) rather than using an AST Transform.

@mkitti mkitti closed this Nov 4, 2021
@mkitti
Copy link
Contributor Author

mkitti commented Nov 5, 2021

Implement this using:

function Base.show(io::IO, m::MIME"text/plain", e::typeof(exit))
    invoke(show, Tuple{IO, MIME"text/plain", Function}, io, m, e)
    print(io, "\nsuggestion: To exit Julia, use Ctrl-D or type exit() and press enter.")
end
julia> exit
exit (generic function with 2 methods)
suggestion: To exit Julia, use Ctrl-D or type exit() and press enter.

julia> println(exit)
exit

julia> show(exit)
exit

julia> (exit, exit)
(exit, exit)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
REPL Julia's REPL (Read Eval Print Loop)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants