How do I document the members of a struct
so that Documenter
generates documentation for them?
"""
This is an X
"""
struct X
"This is a"
a::String
"This is b"
b::Char
"This is c"
c
end
How do I document the members of a struct
so that Documenter
generates documentation for them?
"""
This is an X
"""
struct X
"This is a"
a::String
"This is b"
b::Char
"This is c"
c
end
Fwiw some people feel that struct properties should be considered private and shouldn’t be publicly documented, preferring accessor functions instead.
I have no idea if there’s a better/canonical way, but I’ve done something like this in the past:
"""
This is an `X`
# Fields
- a: First letter of the English alphabet
- b: Second letter of the English alphabet
- c: C is for cookie
"""
struct X
a::String
b::Char
c
end
This may be really frowned upon though, I don’t know
How would you want to access it? Keep in mind that once I do X.a
, that’s just a String
. Julia has no knowledge that X.a
came from the struct X
, without metaprogramming.
True; but that’s irrelevant to the documentation, which is about what to expect when doing X.a
.
True, ? X.a
could be smart.
That would be fine if they were private (and required accessors) but as it is I can X.a
, so it should be possible to document what to expect when doing that (e.g. ? X.a
should work).
There is a difference between being considered private and enforcing that the attributes are externally inaccessible. Julia considers some things nonpublic but doesn’t enforce their inaccessibility.
Maybe I’m not (noob) seeing the wisdom of making it impossible to document (in the usual way) something that’s “considered” non-public if it in fact is publicly accessible.
It doesn’t make much sense to me that we conflate “documented” with “guaranteed to be forward compatible”, but here we are.
https://github.com/JuliaDocs/DocStringExtensions.jl has FIELDS
and TYPEDFIELDS
which can be used for automatically embedding field docs in the main docstring:
julia> using DocStringExtensions
julia> """
This is an X
$(FIELDS)
"""
struct X
"This is a"
a::String
"This is b"
b::Char
"This is c"
c
end
X
help?> X
search: X xor exp Expr exp2 exit axes expm1 exp10 export EXPORTS extrema exponent Exception expanduser ExponentialBackOff max Text nextpow nextind maximum nextprod maximum!
This is an X
• a
This is a
• b
This is b
• c
This is c
julia> """
This is an X
$(TYPEDFIELDS)
"""
struct X
"This is a"
a::String
"This is b"
b::Char
"This is c"
c
end
X
help?> X
search: X xor exp Expr exp2 exit axes expm1 exp10 export EXPORTS extrema exponent Exception expanduser ExponentialBackOff max Text nextpow nextind maximum nextprod maximum!
This is an X
• a::String
This is a
• b::Char
This is b
• c::Any
This is c
That looks good.
But how do I use that to build docs. When I
cd MY_PKG
(...) pkg> activate .
julia> using Revise
julia> include("docs/make.jl")
(after add DocStringExtensions
to docs
and putting using DocStringExtensions
in make.jl
, both of which I assume are necessary) I get ERROR: LoadError: UndefVarError: TYPEDFIELDS not defined
.
using DocStringExtensions
needs to be placed in your package where you are using TYPEDFIELDS
, not in docs/make.jl
. (It also needs to be installed in your package, not your docs
subdirectory’s Project.toml
.)
Oh wow. So (again noob) I’m definitely not understanding something here: adding a dependency to my code I order to document it (especially considering how otherwise tidy the separate doc
environment is) seems wrong.
I’m clearly trying to do something I’m not supposed to do.
The docs/Project.toml
environment is for building static documentation based on the contents of a package. That’s not the only place we want to be able to access docstrings for packages though. We also want to be able to query docstrings from a live REPL/editor. The “abbreviation” objects, such as TYPEDFIELDS
, need to be visible inside your package where your docstrings are located to be able to do their thing, so putting them into a separate environment is not possible. They have to be imported into the package’s module to work.
Yeah I see that now. Clearly my attempt to automatically document parts of structs in the way I’m used to isn’t Julian. (Again, novice here.) Having to make a documentation package a dependency is definitely (Julian or otherwise) not what I want to do.
For the most part its not bad to add lightweight dependencies to a package. The mentioned package doesn’t just add a mechanism to generate documentation, but also annotates the struct with a docstring accessible from help
and the like. If I were a user of your package, I would like getting that help in my REPL, no matter a small dependency. B.t.w. I agree with you that a public accessible thing should be easily documented. I’d say go for that package
Also, I just had a look at the source code, the src seems to be about ~1000 loc and the only secondary dependency is LibGit2
I’m totally in agreement that any publicly accessible thing should be document (and a bit confused about the assertion that any such thing should ever be “considered” private), but I just can’t bring myself to include a dependency that isn’t strictly related to what my package does — especially when the same result can be achieved (if trivially) without introducing such a dependency.
It’s good to not add lots of uneccesary dependencies (it can help with compilation time etc), so if you find the alternative sufficient, then stick with that. On the other hand, packages are there to be used, and Julia makes barrier to entry for dependencies really low. Julia also started moving lots of base code into seperate packages, like Move SharedArrays to a package · Issue #23713 · JuliaLang/julia · GitHub and encourages the community to expand and use the package infrastructure.
So basically all in moderation. You seem to know what you aim for, so stick with that
Yeah I’ve got no problem with dependences. But putting a documentation dependence in the package itself feels wrong.