Skip to content

Commit

Permalink
support for keyword documentation
Browse files Browse the repository at this point in the history
closes #4226
  • Loading branch information
MikeInnes committed Jan 24, 2015
1 parent 7d073b8 commit 08663d4
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 32 deletions.
4 changes: 3 additions & 1 deletion base/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,9 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep
complete = replc,
# When we're done transform the entered line into a call to help("$line")
on_done = respond(repl, julia_prompt) do line
parse("Base.@help $line", raise=false)
haskey(Docs.keywords, symbol(line)) ? # Special-case keywords, which won't parse
:(Base.Docs.@repl $(symbol(line))) :
parse("Base.Docs.@repl $line", raise=false)
end)

# Set up shell mode
Expand Down
202 changes: 202 additions & 0 deletions base/basedocs.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,205 @@
import .Docs: keywords

keywords[:hello] = keywords[:hi] = doc"Hello, Human."

const intro = doc"""
**Welcome to Julia $(string(VERSION)).** The full manual is available at
http://docs.julialang.org/
as well many great tutorials and learning resources:
http://julialang.org/learning/
For help on a specific function or macro, type `?` followed
by its name, e.g. `?fft`, `?@time` or `?html""`, and press
enter.
You can also use `apropos("...")` to search the documentation.
"""

keywords[:help] = keywords[:?] = keywords[:julia] = keywords[:wtf] = intro

keywords[:using] = doc"""
`using` will load the given module or package and make some of its names
available for use (see also `export`). For example:
using Gadfly
loads the plotting package, Gadfly, so that the `plot` function can be used.
Names can be used via dot syntax, whether they are exported or not:
Gadfly.plot(...)
If you don't want to use the packages exports directly, see also `import`.
If you're not sure, `using` is almost definitely what you want.
"""

keywords[:import] = doc"""
import Gadfly
`import`, like `using`, will load modules and packages for use. Unlike
`using`, however, it will *not* make any `export`ed names available for use.
To use Gadfly's `plot` function after importing it, for example, you have
to write:
Gadfly.plot(...)
Import can also be used with specific names, for example
import Gadfly: plot, render
This syntax is used when you want to extend the modules functions with
new methods.
"""

keywords[:export] = doc"""
`export` is used within modules and packages to tell Julia which functions
should be made available to the user. For example:
module Test
export foo # foo is exported, but bar isn't
foo(x) = x
bar(y) = y
end
using Test
foo(1) # 1
bar(1) # Error: bar not defined
Test.bar(1) # 1
"""

keywords[:const] = doc"""
`const` is used to declare global variables which are also constant.
In almost all code (and particularly performance sensitive code)
global variables should be declared constant in this way.
const x = 5
Note that "constant-ness" is not enforced inside containers, so if
`x` is an array or dictionary (for example) you can still add and remove
elements.
Technically, you can even redefine `const` variables, although this will
generate a warning from the compiler. The only strict requirement is that
the *type* of the variable does not change, which is why `const` variables
are much faster than regular globals.
"""

keywords[:function] = doc"""
Functions are defined with the `function` keyword:
function add(a, b)
return a + b
end
Or the short form notation:
add(a, b) = a + b
The use of the `return` keyword is exactly the same as in other languages,
but is often optional. When it's not used, the last expression in the function
body will be returned by default:
function compare(a, b)
a == b && return "equal to"
a < b ? "less than" : "greater than"
end
"""

keywords[:return] = doc"""
`return` can be used function bodies to exit early and return a given value,
e.g.
function compare(a, b)
a == b && return "equal to"
a < b ? "less than" : "greater than"
end
In general you can place a `return` statement anywhere within a function
body, including within deeply nested loops or conditionals, but be careful
with `do` blocks. For example:
function test1(xs)
for x in xs
iseven(x) && return 2x
end
end
function test2(xs)
map(xs) do x
iseven(x) && return 2x
x
end
end
In the first example, the return breaks out of its enclosing function
as soon as it hits an even number, so `test1([5,6,7])` returns `12`.
You might expect the second example to behave the same way, but in fact
the `return` there only breaks out of the *inner* function (inside the `do`
block) and gives a value back to `map`. `test2([5,6,7])` then returns `[5,12,7]`.
"""

keywords[:break] = doc"""
`break` breaks out of a loop immediately. For example
i = 0
while true
i += 1
i > 10 && break
println(i)
end
prints the numbers 1 to 10.
"""

keywords[:continue] = doc"""
`continue` skips the rest of the current loop, then carries on
looping. For example
for i = 1:10
iseven(i) && continue
println(i)
end
prints the numbers 1, 3, 5..., skipping the even numbers.
"""

keywords[:do] = doc"""
The `do` keyword creates an anonymous function. For example
map(1:10) do x
2x
end
is equivalent to `map(x->2x, 1:10)`.
Use multiple arguments like so:
map(1:10, 10:20) do x, y
x + y
end
Splats (`...`) are not supported in do block notation yet.
"""

keywords[:...] = doc"""
The "splat" operator, `...`, represents a sequence of arguments. For example
add(xs...) = reduce(+, xs)
can take any number of arguments:
add(1, 2, 3, 4, 5)
`...` can also be used to apply a function to a sequence of arguments like so:
add([1, 2, 3]...) # 6
add(7, 1:100..., 1000:1100...) # 111107
"""

@doc doc"""
Executes an expression, printing the time it took to
execute and the total number of bytes its execution caused to be
Expand Down
39 changes: 12 additions & 27 deletions base/docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,11 @@ function doc(m::Module)
end
end

# Macros
# Keywords

const keywords = Dict{Symbol,Any}()

# Usage macros

isexpr(x::Expr, ts...) = x.head in ts
isexpr{T}(x::T, ts...) = T in ts
Expand Down Expand Up @@ -193,6 +197,7 @@ function docm(meta, def)
end

function docm(ex)
haskey(keywords, ex) && return keywords[ex]
isexpr(ex, :->) && return docm(ex.args...)
isexpr(ex, :call) && return :(doc($(esc(ex.args[1])), @which $(esc(ex))))
isexpr(ex, :macrocall) && (ex = namify(ex))
Expand Down Expand Up @@ -306,7 +311,7 @@ export Text, @text_str, @text_mstr
# @doc """
# `Text(s)`: Create an object that renders `s` as plain text.

# HTML("foo")
# Text("foo")

# You can also use a stream for large amounts of data:

Expand Down Expand Up @@ -346,31 +351,11 @@ catdoc(md::MD...) = MD(md...)

# REPL help

const intro = doc"""
**Welcome to Julia $(string(VERSION)).** The full manual is available at
http://docs.julialang.org/
as well many great tutorials and learning resources:
http://julialang.org/learning/
For help on a specific function or macro, type `?` followed
by its name, e.g. `?fft`, `?@time` or `?html""`, and press
enter.
You can also use `apropos("...")` to search the documentation.
"""

function replhelp(ex)
if ex === :? || ex === :help
return intro
else
quote
# Backwards-compatible with the previous help system, for now
let doc = @doc $(esc(ex))
doc nothing ? doc : Base.Help.@help_ $(esc(ex))
end
macro repl (ex)
quote
# Backwards-compatible with the previous help system, for now
let doc = @doc $(esc(ex))
doc nothing ? doc : Base.Help.@help_ $(esc(ex))
end
end
end
Expand Down
4 changes: 0 additions & 4 deletions base/help.jl
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,4 @@ macro help_(ex)
end
end

macro help (ex)
Base.Docs.replhelp(ex)
end

end # module

2 comments on commit 08663d4

@tkelman
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great functionality, but would be good to keep #9849 in mind. It would be best to keep the formatting conventions consistent across all of base.

@MikeInnes
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, I noticed docs.jl had been left out of that – I'll fix it.

Please sign in to comment.