Skip to content

Commit

Permalink
REPL help for LaTeX tab completion (#19858)
Browse files Browse the repository at this point in the history
* make it possible to get REPL help directed to a caller-specified io::IO

* add REPL help for latex tab completion
  • Loading branch information
stevengj authored Jan 6, 2017
1 parent f550489 commit 84d9eac
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 16 deletions.
71 changes: 58 additions & 13 deletions base/docs/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ end

# REPL help

function helpmode(line::AbstractString)
function helpmode(io::IO, line::AbstractString)
line = strip(line)
expr =
if haskey(keywords, Symbol(line))
Expand All @@ -109,16 +109,18 @@ function helpmode(line::AbstractString)
# definition if it exists.
(isexpr(x, :macrocall, 1) && !endswith(line, "()")) ? quot(x) : x
end
:(Base.Docs.@repl $expr)
# the following must call repl(io, expr) via the @repl macro
# so that the resulting expressions are evaluated in the Base.Docs namespace
:(Base.Docs.@repl $io $expr)
end
helpmode(line::AbstractString) = helpmode(STDOUT, line)

function repl_search(io::IO, s)
pre = "search:"
print(io, pre)
printmatches(io, s, completions(s), cols = displaysize(io)[2] - length(pre))
println(io, "\n")
end

repl_search(s) = repl_search(STDOUT, s)

function repl_corrections(io::IO, s)
Expand All @@ -128,26 +130,69 @@ function repl_corrections(io::IO, s)
end
print_correction(io, s)
end

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
symbols_latex[v] = k
end
end
return get(symbols_latex, s, "")
end
function repl_latex(io::IO, s::String)
latex = symbol_latex(s)
if !isempty(latex)
print(io, "\"")
Markdown.with_output_format(:cyan, io) do io
print(io, s)
end
print(io, "\" can be typed by ")
Markdown.with_output_format(:cyan, io) do io
print(io, latex, "<tab>")
end
println(io, '\n')
elseif any(c -> haskey(symbols_latex, string(c)), s)
print(io, "\"")
Markdown.with_output_format(:cyan, io) do io
print(io, s)
end
print(io, "\" can be typed by ")
Markdown.with_output_format(:cyan, io) do io
for c in s
cstr = string(c)
if haskey(symbols_latex, cstr)
print(io, symbols_latex[cstr], "<tab>")
else
print(io, c)
end
end
end
println(io, '\n')
end
end
repl_latex(s::String) = repl_latex(STDOUT, s)

macro repl(ex) repl(ex) end
macro repl(io, ex) repl(io, ex) end

function repl(s::Symbol)
function repl(io::IO, s::Symbol)
str = string(s)
quote
repl_search($(string(s)))
($(isdefined(s) || haskey(keywords, s))) || repl_corrections($(string(s)))
repl_latex($io, $str)
repl_search($io, $str)
($(isdefined(s) || haskey(keywords, s))) || repl_corrections($io, $str)
$(_repl(s))
end
end

isregex(x) = isexpr(x, :macrocall, 2) && x.args[1] === Symbol("@r_str") && !isempty(x.args[2])
repl(io::IO, ex::Expr) = isregex(ex) ? :(apropos($io, $ex)) : _repl(ex)
repl(io::IO, str::AbstractString) = :(apropos($io, $str))
repl(io::IO, other) = :(@doc $(esc(other)))

repl(ex::Expr) = isregex(ex) ? :(apropos($ex)) : _repl(ex)

repl(str::AbstractString) = :(apropos($str))

repl(other) = :(@doc $(esc(other)))
repl(x) = repl(STDOUT, x)

function _repl(x)
docs = (isexpr(x, :call) && !any(isexpr(x, :(::)) for x in x.args)) ?
Expand Down
9 changes: 8 additions & 1 deletion doc/src/manual/unicode-input.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Unicode Input

The following table lists Unicode characters that can be entered via
tab completion of LaTeX-like abbreviations in the Julia REPL (and
in various other editing environments). You can also get information on how to
type a symbol by entering it in the REPL help, i.e. by typing `?` and then
entering the symbol in the REPL (e.g., by copy-paste from somewhere you saw
the symbol).

!!! warning

This table may appear to contain missing characters in the second column, or even
Expand Down Expand Up @@ -28,7 +35,7 @@ function unicode_data()
for line in readlines(unidata)
id, name, desc = split(line, ";")[[1, 2, 11]]
codepoint = parse(UInt32, "0x$id")
names[codepoint] = name == "" ? desc : desc == "" ? name : "$name / $desc"
names[codepoint] = titlecase(lowercase(name == "" ? desc : desc == "" ? name : "$name / $desc"))
end
end
return names
Expand Down
4 changes: 3 additions & 1 deletion doc/src/manual/variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ julia> 안녕하세요 = "Hello"
In the Julia REPL and several other Julia editing environments, you can type many Unicode math
symbols by typing the backslashed LaTeX symbol name followed by tab. For example, the variable
name `δ` can be entered by typing `\delta`-*tab*, or even `α̂₂` by `\alpha`-*tab*-`\hat`-
*tab*-`\_2`-*tab*.
*tab*-`\_2`-*tab*. (If you find a symbol somewhere, e.g. in someone else's code,
that you don't know how to type, the REPL help will tell you: just type `?` and
then paste the symbol.)

Julia will even let you redefine built-in constants and functions if needed:

Expand Down
14 changes: 13 additions & 1 deletion test/docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -908,5 +908,17 @@ for (line, expr) in Pair[
"\"...\"" => "...",
"r\"...\"" => :(r"..."),
]
@test Docs.helpmode(line) == :(Base.Docs.@repl($expr))
@test Docs.helpmode(line) == :(Base.Docs.@repl($STDOUT, $expr))
buf = IOBuffer()
@test eval(Base, Docs.helpmode(buf, line)) isa Union{Base.Markdown.MD,Void}
end

let save_color = Base.have_color
try
eval(Base, :(have_color = false))
@test sprint(Base.Docs.repl_latex, "") == "\"\" can be typed by \\sqrt<tab>\n\n"
@test sprint(Base.Docs.repl_latex, "x̂₂") == "\"x̂₂\" can be typed by x\\hat<tab>\\_2<tab>\n\n"
finally
eval(Base, :(have_color = $save_color))
end
end

0 comments on commit 84d9eac

Please sign in to comment.