Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move REPL to stdlib #25544

Merged
merged 2 commits into from
Jan 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions base/arrayshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ function _display(io::IO, X::AbstractArray)
print_array(io, X)
end

show(io::IO, ::MIME"text/plain", X::AbstractArray) = _display(io, X)

## printing with `show`

Expand Down
39 changes: 28 additions & 11 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ function repl_cmd(cmd, out)
nothing
end

function ip_matches_func(ip, func::Symbol)
for fr in StackTraces.lookup(ip)
if fr === StackTraces.UNKNOWN || fr.from_c
return false
end
fr.func === func && return true
end
return false
end

function display_error(io::IO, er, bt)
if !isempty(bt)
st = stacktrace(bt)
Expand All @@ -148,7 +158,7 @@ function display_error(io::IO, er, bt)
end
print_with_color(Base.error_color(), io, "ERROR: "; bold = true)
# remove REPL-related frames from interactive printing
eval_ind = findlast(addr->Base.REPL.ip_matches_func(addr, :eval), bt)
eval_ind = findlast(addr->ip_matches_func(addr, :eval), bt)
if eval_ind !== nothing
bt = bt[1:eval_ind-1]
end
Expand Down Expand Up @@ -339,9 +349,6 @@ function load_juliarc()
nothing
end

import .Terminals
import .REPL

const repl_hooks = []

"""
Expand All @@ -366,7 +373,11 @@ function __atreplinit(repl)
end
_atreplinit(repl) = invokelatest(__atreplinit, repl)

# The REPL stdlib hooks into Base using this Ref
const REPL_MODULE_REF = Ref{Module}()

function _start()
repl_stdlib_loaded = isassigned(REPL_MODULE_REF)
empty!(ARGS)
append!(ARGS, Core.ARGS)
opts = JLOptions()
Expand All @@ -383,22 +394,25 @@ function _start()
banner |= opts.banner != 0 && is_interactive
color_set || (global have_color = false)
else
if !repl_stdlib_loaded
error("REPL standard library not loaded, cannot start a REPL.")
end
term_env = get(ENV, "TERM", @static Sys.iswindows() ? "" : "dumb")
term = Terminals.TTYTerminal(term_env, STDIN, STDOUT, STDERR)
term = REPL_MODULE_REF[].Terminals.TTYTerminal(term_env, STDIN, STDOUT, STDERR)
global is_interactive = true
banner |= opts.banner != 0
color_set || (global have_color = Terminals.hascolor(term))
banner && REPL.banner(term,term)
color_set || (global have_color = REPL_MODULE_REF[].Terminals.hascolor(term))
banner && REPL_MODULE_REF[].banner(term,term)
if term.term_type == "dumb"
active_repl = REPL.BasicREPL(term)
active_repl = REPL_MODULE_REF[].BasicREPL(term)
quiet || @warn "Terminal not fully functional"
else
active_repl = REPL.LineEditREPL(term, have_color, true)
active_repl = REPL_MODULE_REF[].LineEditREPL(term, have_color, true)
active_repl.history_file = history_file
end
# Make sure any displays pushed in .juliarc.jl ends up above the
# REPLDisplay
pushdisplay(REPL.REPLDisplay(active_repl))
pushdisplay(REPL_MODULE_REF[].REPLDisplay(active_repl))
end
else
banner |= opts.banner != 0 && is_interactive
Expand All @@ -417,8 +431,11 @@ function _start()
end
end
else
if !repl_stdlib_loaded
error("REPL standard library not loaded")
end
_atreplinit(active_repl)
REPL.run_repl(active_repl, backend->(global active_repl_backend = backend))
REPL_MODULE_REF[].run_repl(active_repl, backend->(global active_repl_backend = backend))
end
end
catch err
Expand Down
4 changes: 2 additions & 2 deletions base/docs/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ repl_corrections(s) = repl_corrections(STDOUT, s)
# inverse of latex_symbols Dict, lazily created as needed
const symbols_latex = Dict{String,String}()
function symbol_latex(s::String)
if isempty(symbols_latex)
for (k,v) in Base.REPLCompletions.latex_symbols
if isempty(symbols_latex) && isassigned(Base.REPL_MODULE_REF)
for (k,v) in Base.REPL_MODULE_REF[].REPLCompletions.latex_symbols
symbols_latex[v] = k
end
end
Expand Down
158 changes: 0 additions & 158 deletions base/replutil.jl → base/errorshow.jl
Original file line number Diff line number Diff line change
@@ -1,163 +1,5 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# fallback text/plain representation of any type:
show(io::IO, ::MIME"text/plain", x) = show(io, x)

# multiline show functions for types defined before multimedia.jl:
function show(io::IO, ::MIME"text/plain", iter::Union{KeySet,ValueIterator})
print(io, summary(iter))
isempty(iter) && return
print(io, ". ", isa(iter,KeySet) ? "Keys" : "Values", ":")
limit::Bool = get(io, :limit, false)
if limit
sz = displaysize(io)
rows, cols = sz[1] - 3, sz[2]
rows < 2 && (print(io, " …"); return)
cols < 4 && (cols = 4)
cols -= 2 # For prefix " "
rows -= 1 # For summary
else
rows = cols = typemax(Int)
end

for (i, v) in enumerate(iter)
print(io, "\n ")
i == rows < length(iter) && (print(io, "⋮"); break)

if limit
str = sprint(show, v, context=io, sizehint=0)
str = _truncate_at_width_or_chars(str, cols, "\r\n")
print(io, str)
else
show(io, v)
end
end
end

function show(io::IO, ::MIME"text/plain", t::AbstractDict{K,V}) where {K,V}
# show more descriptively, with one line per key/value pair
recur_io = IOContext(io, :SHOWN_SET => t)
limit::Bool = get(io, :limit, false)
if !haskey(io, :compact)
recur_io = IOContext(recur_io, :compact => true)
end

print(io, summary(t))
isempty(t) && return
print(io, ":")
show_circular(io, t) && return
if limit
sz = displaysize(io)
rows, cols = sz[1] - 3, sz[2]
rows < 2 && (print(io, " …"); return)
cols < 12 && (cols = 12) # Minimum widths of 2 for key, 4 for value
cols -= 6 # Subtract the widths of prefix " " separator " => "
rows -= 1 # Subtract the summary

# determine max key width to align the output, caching the strings
ks = Vector{AbstractString}(uninitialized, min(rows, length(t)))
vs = Vector{AbstractString}(uninitialized, min(rows, length(t)))
keylen = 0
vallen = 0
for (i, (k, v)) in enumerate(t)
i > rows && break
ks[i] = sprint(show, k, context=recur_io, sizehint=0)
vs[i] = sprint(show, v, context=recur_io, sizehint=0)
keylen = clamp(length(ks[i]), keylen, cols)
vallen = clamp(length(vs[i]), vallen, cols)
end
if keylen > max(div(cols, 2), cols - vallen)
keylen = max(cld(cols, 3), cols - vallen)
end
else
rows = cols = typemax(Int)
end

for (i, (k, v)) in enumerate(t)
print(io, "\n ")
i == rows < length(t) && (print(io, rpad("⋮", keylen), " => ⋮"); break)

if limit
key = rpad(_truncate_at_width_or_chars(ks[i], keylen, "\r\n"), keylen)
else
key = sprint(show, k, context=recur_io, sizehint=0)
end
print(recur_io, key)
print(io, " => ")

if limit
val = _truncate_at_width_or_chars(vs[i], cols - keylen, "\r\n")
print(io, val)
else
show(recur_io, v)
end
end
end

function show(io::IO, ::MIME"text/plain", f::Function)
ft = typeof(f)
mt = ft.name.mt
if isa(f, Core.IntrinsicFunction)
show(io, f)
id = Core.Intrinsics.bitcast(Int32, f)
print(io, " (intrinsic function #$id)")
elseif isa(f, Core.Builtin)
print(io, mt.name, " (built-in function)")
else
name = mt.name
isself = isdefined(ft.name.module, name) &&
ft == typeof(getfield(ft.name.module, name))
n = length(methods(f))
m = n==1 ? "method" : "methods"
sname = string(name)
ns = (isself || '#' in sname) ? sname : string("(::", ft, ")")
what = startswith(ns, '@') ? "macro" : "generic function"
print(io, ns, " (", what, " with $n $m)")
end
end

function show(io::IO, ::MIME"text/plain", r::LinSpace)
# show for linspace, e.g.
# linspace(1,3,7)
# 7-element LinSpace{Float64}:
# 1.0,1.33333,1.66667,2.0,2.33333,2.66667,3.0
print(io, summary(r))
if !isempty(r)
println(io, ":")
print_range(io, r)
end
end

function show(io::IO, ::MIME"text/plain", t::Task)
show(io, t)
if t.state == :failed
println(io)
showerror(io, CapturedException(t.result, t.backtrace))
end
end

show(io::IO, ::MIME"text/plain", X::AbstractArray) = _display(io, X)
show(io::IO, ::MIME"text/plain", r::AbstractRange) = show(io, r) # always use the compact form for printing ranges

function show(io::IO, ::MIME"text/plain", opt::JLOptions)
println(io, "JLOptions(")
fields = fieldnames(JLOptions)
nfields = length(fields)
for (i, f) in enumerate(fields)
v = getfield(opt, i)
if isa(v, Ptr{UInt8})
v = (v != C_NULL) ? unsafe_string(v) : ""
elseif isa(v, Ptr{Ptr{UInt8}})
v = unsafe_load_commands(v)
end
println(io, " ", f, " = ", repr(v), i < nfields ? "," : "")
end
print(io, ")")
end


# showing exception objects as descriptive error messages

"""
showerror(io, e)

Expand Down
Loading