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

Document how to generate docs locally #1413

Open
aviks opened this issue Sep 6, 2020 · 22 comments
Open

Document how to generate docs locally #1413

aviks opened this issue Sep 6, 2020 · 22 comments

Comments

@aviks
Copy link
Contributor

aviks commented Sep 6, 2020

Apologies if I've missed something, but I could not find, either by reading the Documenter docs, or googling, how to generate the docs locally while developing. The correct incantation is present in most travis configs, and was pointed out to me on Slack. Unless I have missed something obvious, I think it would be good to document the commands needed. They are not obvious, at least to me. At the very least, this issue can serve as a reminder to myself, since I had to look it up multiple times over the last months as I developed new packages.

This is what I ended up doing, running from a shell. This presumes that the current directory is the package root, and that there exists a docs specific Project.toml. This project file must contain Documenter and the package in question as depdendencies. The following incantations can add the depedencies required, and generate the manifest

julia --project=docs/ -e 'using Pkg; Pkg.add("Documenter")'
julia --project=docs/ -e 'using Pkg; Pkg.add("MyPkg")'
julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd()));Pkg.instantiate()'

After that, the following incantation runs the doc generation.

julia --project=docs/  docs/make.jl
@mortenpi
Copy link
Member

mortenpi commented Sep 6, 2020

Yeah, this would be good to have in the manual somewhere. What I usually do is the following, if you have the standard setup with docs/Project.toml:

$ julia --project=docs/
pkg> instantiate
pkg> dev .
julia> include("docs/make.jl")

You can even drop a using Revise in there so that you wouldn't have to reload Julia when updating the docstrings.

@aviks
Copy link
Contributor Author

aviks commented Sep 6, 2020

What I usually do is the following

Yeah, that sounds reasonable. All of this is, of course, obvious in retrospect, but I've struggle with figuring this out, and seen other's do that.

@haampie
Copy link

haampie commented Oct 19, 2020

This came up on Slack too; the Documenter docs are making people run julia make.jl all the time.

@haampie
Copy link

haampie commented Oct 20, 2020

It would be nice to write a guide targeted for package developers who interactively write docs and view the result in their browser. I wrote a bit about how to do it from scratch, how to use Revise etc, but unfortunately Revise does not pick up docs for new function definitions it seems :( so I'm not sure if a Revise-first approach is that great

@MichaelHatherly
Copy link
Member

unfortunately Revise does not pick up docs for new function definitions it seems :( so I'm not sure if a Revise-first approach is that great

Docstring updates work for me on Revise 3.1.4, with either tracked packages of just using includet. (Everything should be Revise-first 😃)

It would be nice to write a guide targeted for package developers who interactively write docs and view the result in their browser

We're happy to accept PRs for the docs, there's always improvements that could be made.

@haampie
Copy link

haampie commented Oct 20, 2020

You are absolutely right 😆. It was late yesterday, I forgot to either export the function from the package or reference it properly in the docs :D. I'll make that PR later tonight then.

@haampie
Copy link

haampie commented Oct 22, 2020

Hm, still experiencing issues when using Revise. I was writing the following for an interactive package development / docs writing guide, but if you follow along and get to the last step... it doesn't pick up the new function with its docs. Can someone reproduce?


Guide for package developers

This guide is intended for users who write docs as they develop a new package. For this use case you want to keep a single Julia REPL session open throughout the guide. To keep track of code and docs changes of your package, you need to install Revise.jl globally first. Enter the Pkg REPL by pressing ] and run:

(@v1.5) pkg> add Revise

julia> using Revise

Go back to the Pkg REPL and generate a new package:

(@v1.5) pkg> generate Example
 Generating  project Example:
    Example/Project.toml
    Example/src/Example.jl

Use your favorite editor to create a docs/ folder within the package such that you end up with the following structure (make.jl and index.md empty files):

Example/
├── docs
│   ├── make.jl
│   └── src
│       └── index.md
├── Project.toml
└── src
    └── Example.jl

Typically Documenter is not a true dependency of your package, but merely a development tool. Therefore, create a fresh environment in the docs/ folder and add Documenter and the Example package itself as dependencies:

(@v1.5) pkg> activate Example/docs
 Activating new environment at `~/Documents/projects/Example/docs/Project.toml`

(docs) pkg> add Documenter

(docs) pkg> dev Example
[ Info: Resolving package identifier `Example` as a directory at `~/Documents/projects/Example`.

Open make.jl in your editor and fill it with the following minimal boilerplate:

using Documenter, Example

makedocs(sitename="My Documentation")

You might also want to add contents to index.md:

# Example.jl Documentation

Hello world!

In your REPL you can now include the make.jl script:

julia> cd("Example")

julia> include("docs/make.jl")
[ Info: Precompiling Example [86743d7e-c321-4af5-beac-c79b42746a03]
[ Info: SetupBuildDirectory: setting up build directory.
[ Info: Doctest: running doctests.
[ Info: ExpandTemplates: expanding markdown templates.
[ Info: CrossReferences: building cross-references.
[ Info: CheckDocument: running document checks.
[ Info: Populate: populating indices.
[ Info: RenderDocument: rendering document.
[ Info: HTMLWriter: rendering HTML pages.

The docs/ folder now contains the file build/index.html. Open this in your browser to view the generated docs.

Next, we add a new function to our package and document it. Replace the contents of Example.jl with the following:

module Example

export func

"""
    func(x)

Returns double the number `x` plus `1`.
"""
func(x) = 2x + 1

end

And document this function in index.md using

# Example.jl Documentation

```@docs
func(x)
```

In the REPL we can now include the make.jl file once more:

julia> include("docs/make.jl")
[ Info: SetupBuildDirectory: setting up build directory.
[ Info: Doctest: running doctests.
[ Info: ExpandTemplates: expanding markdown templates.
┌ Warning: no docs found for 'func(x)' in `@docs` block in src/index.md:3-5```@docs
│ func(x)
```
└ @ Documenter.Expanders ~/.julia/packages/Documenter/pjwqp/src/Expanders.jl:334
[ Info: CrossReferences: building cross-references.
[ Info: CheckDocument: running document checks.
[ Info: Populate: populating indices.
[ Info: RenderDocument: rendering document.
[ Info: HTMLWriter: rendering HTML pages.

Now refresh the index.html page in your browser

@fredrikekre
Copy link
Member

I think you need

```@docs
Example.func(x)
```
```
or
```
makedocs(..., modules=[Example])
```
?

@haampie
Copy link

haampie commented Oct 22, 2020

With both those changes it doesn't seems to work for me:

┌ Warning: no docs found for 'Example.func(x)' in `@docs` block in src/index.md:3-5
│ ```@docs
│ Example.func(x)
│ ```
└ @ Documenter.Expanders ~/.julia/packages/Documenter/pjwqp/src/Expanders.jl:334

Let me try once more from the start... edit: nope. Revise doesn't seem to pick it up for me. That's a bit of a bummer, since it's hard to write a guide that advocates interactive development & viewing docs if this doesn't work out of the box.

@fredrikekre
Copy link
Member

I used this pattern all day yesterday and it worked flawlessly...

@haampie
Copy link

haampie commented Oct 22, 2020

Hm. And I'm pretty sure I used this approach succesfully 3 years ago too. I wonder what's different here.

@fredrikekre
Copy link
Member

Do you have Revise v3?

@haampie
Copy link

haampie commented Oct 22, 2020

(@v1.5) pkg> st Revise
Status `~/.julia/environments/v1.5/Project.toml`
  [295af30f] Revise v3.1.5

@haampie
Copy link

haampie commented Oct 22, 2020

After restarting the REPL it does pick up changes by the way :). Let's see if we can avoid having to put that step in the guide.

@fredrikekre
Copy link
Member

Ah, I know what is wrong. Revise does not track packages recursively into include, so you need

using Revise, Example
include("docs/make.jl")

@haampie
Copy link

haampie commented Oct 22, 2020

Oh, thanks for pointing that out. Only more reasons to document this workflow!

Edit: unfortunately not working (yet) when explicitly using Example after using Revise and before the first include("docs/make.jl"). Will try again later.

@haampie
Copy link

haampie commented Oct 22, 2020

Seems like the problem is no new docstrings are picked up if the package had no docstrings in the first place.

@Nauss
Copy link

Nauss commented Nov 21, 2020

I tried to use this approach to generate the docs locally on my Windows 10 machine (julia 1.5.2).
I already had an existing project so I skipped the generate step but I run:

(docs) pkg> dev MyProject

I get the following error:

  Updating registry at `C:\Users\...\.julia\registries\General`
ERROR: The following package names could not be resolved:
 * MyProject (36230cab-47f6-4611-a9ad-d42316f9a74f in manifest but not in project)

If I use dev ../MyProject instead, everything else works the same.

Should this be mentioned as an alternative or am I missing something ?

@mortenpi
Copy link
Member

@Nauss pkg> dev is relative to the current working directory and the example above assumes you're in the parent directory of MyProject. In your case, as you're already in MyProject/, you could just run pkg> dev ..

@Nauss
Copy link

Nauss commented Nov 22, 2020

Thanks !!

I'm pretty new to Julia and knew I was missing something !

@goerz
Copy link
Member

goerz commented Feb 13, 2024

How about adding the following code at the top of default make.jl file that DocumenterTools.generate produces:

if abspath(PROGRAM_FILE) == @__FILE__
    # When running the `make.jl` file as a script, automatically activate the
    # `docs` environment and dev-install the main package into that environment
    import Pkg
    Pkg.activate(@__DIR__)
    Pkg.develop(path=joinpath(@__DIR__, ".."))
    Pkg.instantiate()
end

That code snippet could be discussed in more detail in a rewrite of the Documenter Guide.

It would probably help out a lot of people, and with the if abspath(PROGRAM_FILE) == @__FILE__ it wouldn't get in the way of alternative workflows. For example, my own workflow is that I instantiate the test environment and include(docs/make.jl) there. This is because I prefer a single REPL where I can interactively run tests, build documentation, or whatever else I might need while developing the package.

@mortenpi
Copy link
Member

mortenpi commented Feb 13, 2024

I think my preference would be to have it as a separate script (but one that we could definitely auto-generate for the user). I'd prefer not to re-run all the Pkg machinery every time I do julia --project=docs/ docs/make.jl.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants