How to preserve default struct help entry while adding something else?

If I define a struct without any documentation entry above, I get a nice overview of the fields when searching for help about it, like this:

julia> struct A
         x::Float64
         i::Int
       end

help?> A
search: A Any any all abs ARGS ans axes atan asin asec any! all! acsc acot acos abs2 Array atanh atand asinh asind asech asecd ascii

  No documentation found.

  Summary
  ≡≡≡≡≡≡≡≡≡

  struct A <: Any

  Fields
  ≡≡≡≡≡≡≡≡

  x :: Float64
  i :: Int64


However, if I add something, I loose that fine summary:

julia> """
       Now I added some documentation.
       """
       struct A
         x::Float64
         i::Int
       end
A

help?> A
search: A Any any all abs ARGS ans axes atan asin asec any! all! acsc acot acos abs2 Array atanh atand asinh asind asech asecd ascii

  Now I added some documentation.

How to add some more information on top of the help entry and preserve the printing of that summary?

1 Like

Maybe TYPEDEF and TYPEFIELDS from Home · DocStringExtensions.jl ?

2 Likes

The function doing that is at

./share/julia/stdlib/v1.6/REPL/src/docview.jl

One can call it like this:

ulia> """
       Test
        
       $(REPL.summarize(Docs.Binding(Main,:A),A))

       """
       struct A
         x::Float64
         i::Int
       end
A

help?> A
search: A Any any all abs ARGS ans axes atan asin asec any! all! acsc acot acos abs2 Array atanh atand asinh asind asech asecd ascii

  Test

  No documentation found.

  Summary
  ≡≡≡≡≡≡≡≡≡

  struct A <: Any

  Fields
  ≡≡≡≡≡≡≡≡

  x :: Float64
  i :: Int64


(I don’t know what the second argument of Binding is for, anything does the same here).

But unfortunately it will print “No documentation found” with the summary.

function summarize(io::IO, T::DataType, binding::Binding)
    println(io, "# Summary")
    println(io, "```")
    println(io,
            T.abstract ? "abstract type" :
            T.mutable  ? "mutable struct" :
            Base.isstructtype(T) ? "struct" : "primitive type",
            " ", T, " <: ", supertype(T)
            )
    println(io, "```")
    if !T.abstract && T.name !== Tuple.name && !isempty(fieldnames(T))
        println(io, "# Fields")
        println(io, "```")
        pad = maximum(length(string(f)) for f in fieldnames(T))
        for (f, t) in zip(fieldnames(T), T.types)
            println(io, rpad(f, pad), " :: ", t)
        end
        println(io, "```")
    end
    if !isempty(subtypes(T))
        println(io, "# Subtypes")
        println(io, "```")
        for t in subtypes(T)
            println(io, t)
        end
        println(io, "```")
    end
    if supertype(T) != Any
        println(io, "# Supertype Hierarchy")
        println(io, "```")
        Base.show_supertypes(io, T)
        println(io)
        println(io, "```")
    end
end

It would be nice if that function was split like this below, then one would be able to call each of the info prints, but I do not understand the role of the IOBuffer() there and how it translates or not in printing to the REPL:

function summarize(io::IO, T::DataType, binding::Binding)
    summarize_Summary(io,T)
    summarize_Fields(io,T)
    summarize_Subtypes(io,T)
    summarize_Supertypes(io,T)
end

function summarize(T::DataType)
    io = IOBuffer()
    summarize_Summary(io,T)
    summarize_Fields(io,T)
    summarize_Subtypes(io,T)
    summarize_Supertypes(io,T)
end

function summarize_Summary(io::IO, T::DataType)
    println(io, "# Summary")
    println(io, "```")
    println(io,
            T.abstract ? "abstract type" :
            T.mutable  ? "mutable struct" :
            Base.isstructtype(T) ? "struct" : "primitive type",
            " ", T, " <: ", supertype(T)
            )
    println(io, "```")
end

function summarize_Fields(io::IO, T::DataType)
    if !T.abstract && T.name !== Tuple.name && !isempty(fieldnames(T))
        println(io, "# Fields")
        println(io, "```")
        pad = maximum(length(string(f)) for f in fieldnames(T))
        for (f, t) in zip(fieldnames(T), T.types)
            println(io, rpad(f, pad), " :: ", t)
        end
        println(io, "```")
    end
end

function summarize_Subtypes(io::IO, T::DataType)
    if !isempty(subtypes(T))
        println(io, "# Subtypes")
        println(io, "```")
        for t in subtypes(T)
            println(io, t)
        end
        println(io, "```")
    end
end


That looks somewhat underground :slight_smile: .

Seems to solve most of it :-). Thanks.