Skip to content

Commit

Permalink
move REPL to stdlib
Browse files Browse the repository at this point in the history
  • Loading branch information
KristofferC committed Jan 21, 2018
1 parent a7e4d1c commit 73c989b
Show file tree
Hide file tree
Showing 28 changed files with 422 additions and 365 deletions.
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
258 changes: 4 additions & 254 deletions base/precompile.jl

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -466,12 +466,6 @@ include("asyncmap.jl")
include("multimedia.jl")
using .Multimedia

# frontend
include("repl/Terminals.jl")
include("repl/LineEdit.jl")
include("repl/REPLCompletions.jl")
include("repl/REPL.jl")

# deprecated functions
include("deprecated.jl")

Expand Down Expand Up @@ -528,6 +522,7 @@ Base.require(Base, :SparseArrays)
Base.require(Base, :SuiteSparse)
Base.require(Base, :Test)
Base.require(Base, :Unicode)
Base.require(Base, :REPL)

@eval Base begin
@deprecate_binding Test root_module(Base, :Test) true ", run `using Test` instead"
Expand Down Expand Up @@ -555,6 +550,12 @@ Base.require(Base, :Unicode)
@deprecate_binding LinAlg root_module(Base, :LinearAlgebra) true ", run `using LinearAlgebra` instead"
@deprecate_binding(I, root_module(Base, :LinearAlgebra).I, true,
", run `using LinearAlgebra` to load linear algebra functionality.")

# PR 25544
@deprecate_binding REPL root_module(Base, :REPL) true ", run `using REPL` instead"
@deprecate_binding LineEdit root_module(Base, :REPL).LineEdit true ", use `REPL.LineEdit` instead"
@deprecate_binding REPLCompletions root_module(Base, :REPL).REPLCompletions true ", use `REPL.REPLCompletions` instead"
@deprecate_binding Terminals root_module(Base, :REPL).Terminals true ", use `REPL.Terminals` instead"
end

empty!(DEPOT_PATH)
Expand Down
1 change: 0 additions & 1 deletion doc/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ const PAGES = [
"manual/networking-and-streams.md",
"manual/parallel-computing.md",
"manual/dates.md",
"manual/interacting-with-julia.md",
"manual/running-external-programs.md",
"manual/calling-c-and-fortran-code.md",
"manual/handling-operating-system-variation.md",
Expand Down
1 change: 0 additions & 1 deletion doc/src/base/base.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ Some general notes:
Base.exit
Base.quit
Base.atexit
Base.atreplinit
Base.isinteractive
Base.varinfo
Base.summarysize
Expand Down
2 changes: 1 addition & 1 deletion doc/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ Please read the [release notes](NEWS.md) to see what has changed since the last
* [Calling C and Fortran Code](@ref)
* [Handling Operating System Variation](@ref)
* [Environment Variables](@ref)
* [Interacting With Julia](@ref)
* [Embedding Julia](@ref)
* [Packages](@ref)
* [Profiling](@ref)
Expand Down Expand Up @@ -77,6 +76,7 @@ Please read the [release notes](NEWS.md) to see what has changed since the last

## Standard Library

* [The Julia REPL](@ref)
* [Base64](@ref)
* [CRC32c](@ref)
* [Dates and Time](@ref stdlib-dates)
Expand Down
2 changes: 1 addition & 1 deletion doc/src/manual/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ Environment variables that determine how REPL output should be formatted at the
terminal. Generally, these variables should be set to [ANSI terminal escape
sequences](https://ascii-table.com/ansi-escape-sequences.php). Julia provides
a high-level interface with much of the same functionality: see the section on
[Interacting With Julia](@ref).
[The Julia REPL](@ref).

### `JULIA_ERROR_COLOR`

Expand Down
1 change: 0 additions & 1 deletion doc/src/manual/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
* [Calling C and Fortran Code](@ref)
* [Handling Operating System Variation](@ref)
* [Environment Variables](@ref)
* [Interacting With Julia](@ref)
* [Embedding Julia](@ref)
* [Packages](@ref)
* [Package Development](@ref)
Expand Down
6 changes: 3 additions & 3 deletions doc/src/manual/unicode-input.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ the symbol).
#
# Generate a table containing all LaTeX and Emoji tab completions available in the REPL.
#
import REPL
const NBSP = '\u00A0'
function tab_completions(symbols...)
Expand Down Expand Up @@ -75,8 +75,8 @@ end
table_entries(
tab_completions(
Base.REPLCompletions.latex_symbols,
Base.REPLCompletions.emoji_symbols
REPL.REPLCompletions.latex_symbols,
REPL.REPLCompletions.emoji_symbols
),
unicode_data()
)
Expand Down
2 changes: 1 addition & 1 deletion doc/src/manual/workflow-tips.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Here are some tips for working with Julia efficiently.

## REPL-based workflow

As already elaborated in [Interacting With Julia](@ref), Julia's REPL provides rich functionality
As already elaborated in [The Julia REPL](@ref), Julia's REPL provides rich functionality
that facilitates an efficient interactive workflow. Here are some tips that might further enhance
your experience at the command line.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Interacting With Julia
# The Julia REPL

Julia comes with a full-featured interactive command-line REPL (read-eval-print loop) built into
the `julia` executable. In addition to allowing quick and easy evaluation of Julia statements,
Expand Down Expand Up @@ -196,16 +196,17 @@ to do so).
### Customizing keybindings

Julia's REPL keybindings may be fully customized to a user's preferences by passing a dictionary
to `REPL.setup_interface()`. The keys of this dictionary may be characters or strings. The key
to `REPL.setup_interface`. The keys of this dictionary may be characters or strings. The key
`'*'` refers to the default action. Control plus character `x` bindings are indicated with `"^x"`.
Meta plus `x` can be written `"\\Mx"`. The values of the custom keymap must be `nothing` (indicating
that the input should be ignored) or functions that accept the signature `(PromptState, AbstractREPL, Char)`.
The `REPL.setup_interface()` function must be called before the REPL is initialized, by registering
the operation with `atreplinit()`. For example, to bind the up and down arrow keys to move through
The `REPL.setup_interface` function must be called before the REPL is initialized, by registering
the operation with [`atreplinit`](@ref) . For example, to bind the up and down arrow keys to move through
history without prefix search, one could put the following code in `.juliarc.jl`:

```julia
import Base: LineEdit, REPL
import REPL
import REPL.LineEdit

const mykeys = Dict{Any,Any}(
# Up Arrow
Expand Down Expand Up @@ -255,7 +256,7 @@ julia> e¹ = [1 0]
1×2 Array{Int64,2}:
1 0
julia> \sqrt[TAB]2 # √ is equivalent to the sqrt() function
julia> \sqrt[TAB]2 # √ is equivalent to the sqrt function
julia> √2
1.4142135623730951
Expand Down Expand Up @@ -375,3 +376,9 @@ ENV["JULIA_ERROR_COLOR"] = :magenta
ENV["JULIA_WARN_COLOR"] = :yellow
ENV["JULIA_INFO_COLOR"] = :cyan
```

## References

```@docs
Base.atreplinit
```
3 changes: 2 additions & 1 deletion base/repl/LineEdit.jl → stdlib/REPL/src/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

module LineEdit

import ..REPL
using ..Terminals

import ..Terminals: raw!, width, height, cmove, getX,
Expand Down Expand Up @@ -85,7 +86,7 @@ options(s::PromptState) =
# in the REPL module
s.p.repl.options
else
Base.REPL.GlobalOptions
REPL.GlobalOptions
end

function setmark(s::MIState, guess_region_active::Bool=true)
Expand Down
30 changes: 16 additions & 14 deletions base/repl/REPL.jl → stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
module REPL

using Base.Meta
using ..Terminals
using ..LineEdit
using ..REPLCompletions

export
AbstractREPL,
Expand All @@ -20,6 +17,12 @@ import Base:
AnyDict,
==


include("Terminals.jl")
using .Terminals

include("LineEdit.jl")
using .LineEdit
import ..LineEdit:
CompletionProvider,
HistoryProvider,
Expand All @@ -36,6 +39,13 @@ import ..LineEdit:
terminal,
MIState

include("REPLCompletions.jl")
using .REPLCompletions

function __init__()
Base.REPL_MODULE_REF[] = REPL
end

abstract type AbstractREPL end

answer_color(::AbstractREPL) = ""
Expand Down Expand Up @@ -103,17 +113,6 @@ function start_repl_backend(repl_channel::Channel, response_channel::Channel)
end
backend
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

struct REPLDisplay{R<:AbstractREPL} <: AbstractDisplay
repl::R
end
Expand Down Expand Up @@ -1138,4 +1137,7 @@ function start_repl_server(port::Int)
end
end

include("precompile.jl")
_precompile_()

end # module
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ end

# Returns the value in a expression if sym is defined in current namespace fn.
# This method is used to iterate to the value of a expression like:
# :(Base.REPLCompletions.whitespace_chars) a `dump` of this expression
# :(REPL.REPLCompletions.whitespace_chars) a `dump` of this expression
# will show it consist of Expr, QuoteNode's and Symbol's which all needs to
# be handled differently to iterate down to get the value of whitespace_chars.
function get_value(sym::Expr, fn)
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# https://www.w3.org/Math/characters/unicode.xml
# by the following Julia script:
#=
import REPL
using LightXML
xdoc = parse_file("unicode.xml")
latexsym = []
Expand Down Expand Up @@ -49,7 +50,7 @@ end
#=
fname = "unicode-math-table.tex"
isfile(fname) || download("https://mirror.math.ku.edu/tex-archive/macros/latex/contrib/unicode-math/$fname", fname)
const latex_strings = Set(values(Base.REPLCompletions.latex_symbols))
const latex_strings = Set(values(REPL.REPLCompletions.latex_symbols))
open(fname) do f
for L in eachline(f)
x = map(s -> rstrip(s, [' ','\t','\n']),
Expand Down
Loading

0 comments on commit 73c989b

Please sign in to comment.