Including a folder

Hello,

I want to be able to do something like this:

module Example
include_folder("my/modules")

end

And include_folder should look similar to this:

module Utils
function include_folder(path::AbstractString)
    paths = joinpath.(Ref(path), readdir(path))
    julia_files = filter(f -> endswith(f, ".jl"), paths)
    include.(julia_files)
end
end

The problem is that is not going to include the files in the module of the caller, but wherever include_folder is defined. I know that macros have an extra __module__ argument, representing the caller’s module, so I have tried to define a macro.

This is what I got so far:

macro include_folder(path)
    quote
        paths = joinpath.(Ref($path), readdir($path))
        local julia_files = filter(f -> endswith(f, ".jl"), paths)
        :(include.($julia_files))
    end
end

Which is wrong and returns:

include.([“my/modules/mod1.jl”, “…”])

I don’t think I understand how macros work, and my attempts at running that code inside the macro have failed (wrapping the quote in an extra eval, ommiting the last quote, etc).

So, a few questions:

  • is it possible to do this in a simpler way? (Avoiding macros alltogether)
  • is this a terrible idea for any reason?
  • how can I make this work?

Right now this work, but seems very wrong:

@eval @include_folder("my/modules")

Any help is appreciated, thanks in advance.

According to the documentation for include, “Every module (except those defined with baremodule) has its own definition of include, which evaluates the file in that module.”

But you can “Use Base.include to evaluate a file into another module.”

So maybe you can pass the required module to your include_folder function, which then Base.includes the files in that module:

module Utils
    export include_folder
    function include_folder(m::Module, path::AbstractString)
        paths = joinpath.(Ref(path), readdir(path))
        julia_files = filter(f -> endswith(f, ".jl"), paths)
        Base.include.(Ref(m), julia_files)
    end
end

And then pass the current module to include_folder with @__MODULE__

module Example
    using Utils    
    include_folder(@__MODULE__, "my/modules")
end

Thanks, that works. I must have skipped that part in the documentation. This would work:

macro include_folder(path)
    quote
        paths = joinpath.(Ref($path), readdir($path))
        local julia_files = filter(f -> endswith(f, ".jl"), paths)
        Base.include.(Ref($__module__), $julia_files)
    end
end

However I would be curious if someone could tell me how to solve my firs attempt at a macro. Not for this particular problem, but for better understanding of how macros work.