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

Generate # Extended help with all component descriptions #47

Merged
merged 9 commits into from
Jul 1, 2024
1 change: 1 addition & 0 deletions src/Interfaces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export @implements, @interface

include("arguments.jl")
include("interface.jl")
include("documentation.jl")
include("implements.jl")
include("test.jl")

Expand Down
42 changes: 42 additions & 0 deletions src/documentation.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
function _help_header(@nospecialize(interface::Type{<:Interface}))
m_keys = mandatory_keys(interface)
o_keys = optional_keys(interface)
return "An Interfaces.jl `Interface` with mandatory components `$m_keys` and optional components `$o_keys`."
end

function _extended_help(@nospecialize(interface::Type{<:Interface}))
comp = components(interface)

io_buf = IOBuffer()
# ^(More efficient and readable than string concatenation)

println(io_buf, "# Extended help")
!isempty(comp.mandatory) && println(io_buf, "\n## Mandatory keys:\n")
_list_keys(io_buf, comp.mandatory)

!isempty(comp.optional) && println(io_buf, "\n## Optional keys:\n")
_list_keys(io_buf, comp.optional)

return String(take!(io_buf))
end

function _list_keys(io::IO, @nospecialize(component))
for key in keys(component)
print(io, "* `$key`")
values = component[key]
if values isa Tuple && all(Base.Fix2(isa, Pair), values)
# Such as `iterate = ("description1" => f, "description2" => g)`
println(io, ":")
for value in values
println(io, " * $(first(value))")
end
elseif values isa Pair
# Such as `iterate = "description" => f`
println(io, ": $(first(values))")
else
# all other cases, like `iterate = f`
println(io)
end
end
return nothing
end
8 changes: 5 additions & 3 deletions src/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,16 @@ macro interface(interface::Symbol, type, components, description)
# Generate a docstring for the interface
let description=$description,
interfacesym=$(QuoteNode(interface)),
m_keys=$Interfaces.mandatory_keys($interface),
o_keys=$Interfaces.optional_keys($interface)
header=$Interfaces._help_header($interface),
extended_help=$Interfaces._extended_help($interface)
@doc """
$(" ") $interfacesym

An Interfaces.jl `Interface` with mandatory components `$m_keys` and optional components `$o_keys`.
$header

$description

$extended_help
""" $interface
end
end |> esc
Expand Down
3 changes: 3 additions & 0 deletions test/advanced.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,6 @@ using Test #src
@test Interfaces.test(Group.GroupInterface, Float64) #src
@test !Interfaces.test(Group.GroupInterface, Int, int_pairs) #src
@test_throws ArgumentError Interfaces.test(Group.GroupInterface, Float64, int_pairs) #src

include("test_generated_docs.jl") #src

42 changes: 42 additions & 0 deletions test/test_generated_docs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
expected_extended_help = """# Extended help

## Mandatory keys:

* `neutral_check`:
* neutral stable
* `multiplication_check`:
* multiplication stable
* `inversion_check`:
* inversion stable
* inversion works"""

@test strip(Interfaces._extended_help(Group.GroupInterface)) == strip(expected_extended_help)


expected_docs = """```
GroupInterface
```

An Interfaces.jl `Interface` with mandatory components `(:neutral_check, :multiplication_check, :inversion_check)` and optional components `()`.

A group is a set of elements with a neutral element where you can perform multiplications and inversions.

The conditions checking the interface accept an `Arguments` object with two fields named `x` and `y`. The type of the first field `x` must be the type you wish to declare as implementing `GroupInterface`.

# Extended help

## Mandatory keys:

* `neutral_check`:

* neutral stable
* `multiplication_check`:

* multiplication stable
* `inversion_check`:

* inversion stable
* inversion works"""

@test strip(string(@doc Group.GroupInterface)) == strip(expected_docs)

Loading