How to include local module with struct into notebook scope

I am trying use Pluto with a local module.

I have a module like:

foo.jl

module foo

export foobar

    struct foobar
        A:Int
    end
end 

I think the recommended way to do this is:

notebook1.jl

include("foo.jl")
using .foo

However the issue here is that the my struct is only exported to the cell where I did using .foo. I still have to do foo.foobar to access the struct in a new Pluto cell.

So I have to do an import to manually import foo to the scope of the whole notebook.

notebook2.jl

include("foo.jl")
using .foo
import .foo: foobar

This is fine for one struct but in reality I have a module with a bunch of stuff to import and I don’t want the added overhead of explicitly importing.

I have looked all around and found various recommendations on how to accomplish this. Fonsp had the idea of the ingredients function to sort of extend the import function to work better with Pluto reactivity.

notebook3.jl

function ingredients(path::String)
	# this is from the Julia source code (evalfile in base/loading.jl)
	# but with the modification that it returns the module instead of the last object
	name = Symbol(basename(path))
	m = Module(name)
	Core.eval(m,
        Expr(:toplevel,
             :(eval(x) = $(Expr(:core, :eval))($name, x)),
             :(include(x) = $(Expr(:top, :include))($name, x)),
             :(include(mapexpr::Function, x) = $(Expr(:top, :include))(mapexpr, $name, x)),
             :(include($path))))
	m
end

foo = ingredients("foo.jl")

import .foo: foobar

This gives warning `could not import foo.jl.foobar into workspace

I think the exact syntax for importing local modules in julia in general has changed: (include, using, import, .using, etc.) since that discussion and I’m wondering about what is the current best practice.

2 Likes