Search code examples
modulejuliadocstring

Julia: List docstrings inside a module


Is there a way to pull ALL the docstrings from the following module main, including the docstrings of module nested, which reside inside module main, without already knowing what modules are inside module main?

"This is Module main"
module main

"This is fA()"
fA(x) = x

"This is module nested"
module nested

"This is fB()"
fB(x) = x

end

end

I can get the docstrings for module main and module nested, assuming I already know that module nested exists inside module main.

? main
This is Module main
? main.nested
This is Module nested

I am familiar with names(), which helps, but not that much in its simplest incantation:

names(main, all = true)
7-element Array{Symbol,1}:
 Symbol("##meta#252")
 Symbol("#eval")     
 Symbol("#fA")       
 :eval               
 :fA                 
 :main               
 :nested             

Interpreting the output of names()is not easy: it's not obvious that nested is a module inside main.


Solution

  • The question is not entirely clear, but here is some useful code:

    # check if a symbol is a nested module
    issubmodule(m::Module, s::Symbol) = isa(eval(m,s),Module) && module_name(m) != s
    
    # get a list of all submodules of module m
    submodules(m) = filter(x->issubmodule(m,x),names(m,true))
    
    # get a list of all docstring bindings in a module
    allbindings(m) = [ [y[2].data[:binding] for y in x[2].docs]
      for x in eval(m,Base.Docs.META)]
    
    # recursively get all docstrings from a module and submodules
    function alldocs(m)
        thedocs = map(x->Base.Docs.doc(x[1]),allbindings(m))
        return vcat(thedocs,map(x->alldocs(eval(m,x)),submodules(m))...)
    end
    

    Now you have:

    julia> alldocs(main)
      This is fA()
      This is Module main
      This is module nested
      This is fB()
    

    Hope this helps.