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

A usage cookbook #338

Merged
merged 4 commits into from Aug 25, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -18,7 +18,7 @@ git:
## (tests will run but not make your overall status red)
matrix:
allow_failures:
- julia: nightly
- os: osx

script:
- export JULIA_PROJECT=""
Expand Down
1 change: 1 addition & 0 deletions docs/make.jl
Expand Up @@ -10,6 +10,7 @@ makedocs(
pages = [
"Home" => "index.md",
"config.md",
"cookbook.md",
"limitations.md",
"debugging.md",
"internals.md",
Expand Down
196 changes: 196 additions & 0 deletions docs/src/cookbook.md
@@ -0,0 +1,196 @@
# Revise usage: a cookbook

## Package-centric usage

For code that might be useful more than once, it's often a good idea to put it in
a package.
For creating packages, the author recommends [PkgTemplates.jl](https://github.com/invenia/PkgTemplates.jl).
A fallback is to use "plain" `Pkg` commands.
Both options are described below.

### PkgTemplates

!!! note
Because PkgTemplates integrates nicely with [`git`](https://git-scm.com/),
this approach might require you to do some configuration.
(Once you get things set up, you shouldn't have to do this part ever again.)
PkgTemplates needs you to configure your `git` user name and email.
Some instructions on configuration are [here](https://help.github.com/en/articles/set-up-git)
and [here](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup).
It's also helpful to sign up for a [GitHub account](https://github.com/)
and set git's `github.user` variable.
The [PkgTemplates documentation](https://invenia.github.io/PkgTemplates.jl/stable/)
may also be useful.

If you struggle with this part, consider trying the "plain" `Pkg` variant below.

!!! note
If the current directory in your Julia session is itself a package folder, PkgTemplates
will use it as the parent environment (project) for your new package.
To reduce confusion, before trying the commands below it may help to first ensure you're in a
a "neutral" directory, for example by typing `cd()` at the Julia prompt.

Let's create a new package, `MyPkg`, to play with.

```julia
julia> using PkgTemplates

julia> t = Template()
Template:
→ User: timholy
→ Host: github.com
→ License: MIT (Tim Holy <tim.holy@gmail.com> 2019)
→ Package directory: ~/.julia/dev
→ Minimum Julia version: v1.0
→ SSH remote: No
→ Add packages to main environment: Yes
→ Commit Manifest.toml: No
→ Plugins: None

julia> generate("MyPkg", t)
Generating project MyPkg:
/home/tim/.julia/dev/MyPkg/Project.toml
/home/tim/.julia/dev/MyPkg/src/MyPkg.jl
[lots more output suppressed]
```

In the first few lines you can see the location of your new package, here
the directory `/home/tim/.julia/dev/MyPkg`.

Before doing anything else, let's try it out:

```julia
julia> using Revise # you must do this before loading any revisable packages

julia> using MyPkg
[ Info: Precompiling MyPkg [102b5b08-597c-4d40-b98a-e9249f4d01f4]

julia> MyPkg.greet()
Hello World!
```

(It's perfectly fine if you see a different string of digits and letters after the "Precompiling MyPkg" message.)
You'll note that Julia found your package without you having to take any extra steps.

*Without* quitting this Julia session, open the `MyPkg.jl` file in an editor.
You might be able to open it with

```julia
julia> edit(pathof(MyPkg))
```

although that might require [configuring your EDITOR environment variable](https://askubuntu.com/questions/432524/how-do-i-find-and-set-my-editor-environment-variable).

You should see something like this:

```julia
module MyPkg

greet() = print("Hello World!")

end # module
```

This is the basic package created by PkgTemplates. Let's modify `greet` to return
a different message:

```julia
module MyPkg

greet() = print("Hello, revised World!")

end # module
```

Now go back to that same Julia session, and try calling `greet` again.
After a pause (the code of Revise and its dependencies is compiling), you should see

```julia
julia> MyPkg.greet()
Hello, revised World!
```

From this point forward, revisions should be fast. You can modify `MyPkg.jl`
quite extensively without quitting the Julia session, although there are some [Limitations](@ref).


### Using Pkg

[Pkg](https://julialang.github.io/Pkg.jl/v1/) works similarly to `PkgTemplates`,
but requires less configuration while also doing less on your behalf.
Let's create a blank `MyPkg` using `Pkg`. (If you tried the `PkgTemplates` version
above, you might first have to delete the package with `Pkg.rm("MyPkg")` following by
a complete removal from your `dev` directory.)

```julia
julia> using Pkg

julia> cd(Pkg.devdir()) # take us to the standard "development directory"

(v1.2) pkg> generate MyPkg
Generating project MyPkg:
MyPkg/Project.toml
MyPkg/src/MyPkg.jl

(v1.2) pkg> dev MyPkg
[ Info: resolving package identifier `MyPkg` as a directory at `~/.julia/dev/MyPkg`.
...
```

For the line starting `(v1.2) pkg>`, hit the `]` key at the beginning of the line,
then type `generate MyPkg`.
The next line, `dev MyPkg`, is necessary to tell `Pkg` about the existence of this new package.

Now you can do the following:
```julia
julia> using MyPkg
[ Info: Precompiling MyPkg [efe7ebfe-4313-4388-9b6c-3590daf47143]

julia> edit(pathof(MyPkg))
```
and the rest should be similar to what's above under `PkgTemplates`.
Note that with this approach, `MyPkg` has not been set up for version
control.


## `includet` usage

The alternative to creating packages is to manually load individual source files.
This approach is intended for quick-and-dirty development;
if you want to track multiple files and/or have some files include other files,
you should consider switching to the package style above.

Open your editor and create a file like this:

```julia
mygreeting() = "Hello, world!"
```

Save it as `mygreet.jl` in some directory. Here we will assume it's being saved in `/tmp/`.

Now load the code with `includet`, which stands for "include and track":

```julia
julia> using Revise

julia> includet("/tmp/mygreet.jl")

julia> mygreeting()
"Hello, world!"
```

Now, in your editor modify `mygreeting` to do this:

```julia
mygreeting() = "Hello, revised world!"
```

and then try it in the same session:

```julia
julia> mygreeting()
"Hello, revised world!"
```

As described above, the first revision you make may be very slow, but later revisions
should be fast.
2 changes: 2 additions & 0 deletions docs/src/index.md
Expand Up @@ -70,6 +70,8 @@ ERROR: UndefVarError: f not defined

all without restarting Julia.

If you need more examples, see [Revise usage: a cookbook](@ref).

## Other key features of Revise

Revise updates its internal paths when you change versions of a package.
Expand Down
21 changes: 9 additions & 12 deletions docs/src/limitations.md
@@ -1,6 +1,14 @@
# Limitations

Revise (really, Julia itself) can handle many kinds of code changes, but a few may require special treatment:
There are some kinds of changes that Revise (or often, Julia itself) cannot incorporate into a running Julia session:

- changes to type definitions
- adding new source files to packages, or file/module renames
- conflicts between variables and functions sharing the same name

These kinds of changes require that you restart your Julia session.

In addition, some situations may require special handling:

### Macros and generated functions

Expand Down Expand Up @@ -53,14 +61,3 @@ end # module

and the corresponding edit to the code would be to modify it to `greetcaller(x) = greet("Bar")`
and `remotecall_fetch(greetcaller, p, 1)`.

### Changes that Revise cannot handle

Finally, there are some kinds of changes that Revise cannot incorporate into a running Julia session:

- changes to type definitions
- file or module renames
- adding new source files to packages
- conflicts between variables and functions sharing the same name

These kinds of changes require that you restart your Julia session.