I hereby announce the public release of UseAll.jl providing @useall which is effectively a small tool to ease REPL-based worflows by pulling the content of modules/packages into the current namespace.
This simplifies developing code inside of a package from the start and thus shares the spirit of (and combines well with) Revise.jl and BestieTemplate.jl.
This is already used internally in our company for some time as code run in startup.jl now made into a proper package, with some features added and released to the public.
The following would normally be done with package code, i.e. having the code in a file. But for convenience, the following example will be REPL-only:
module MyModule
f(x) = g(x)
g(x) = 42 + x
end
You might want to test/debug/run this with
julia> x = 12
12
and copy lines from the module/package into the REPL to execute them. Unfortunately, you can’t:
julia> using .MyModule
julia> f(x)
ERROR: UndefVarError: `f` not defined in `Main`
Suggestion: check for spelling errors or missing imports.
Stacktrace:
[1] top-level scope
@ REPL[6]:1
[2] top-level scope
@ REPL:1
Instead, you need to modify each line (the function name and all method/constructor calls used to create method arguments):
julia> MyModule.f(x)
54
Alternatively, you can switch the currently active module in the REPL by entering MyModule and hitting <alt>+<m>. But this often does not work, too,
(Main.MyModule) julia> f(x)
ERROR: UndefVarError: `x` not defined in `Main.MyModule`
Suggestion: check for spelling errors or missing imports.
Stacktrace:
[1] top-level scope
@ REPL[6]:1
[2] top-level scope
@ REPL:1
as your code depends on previous definitions in your REPL session or in your startup.jl which is not available in the module/package you want to run code in.
With UseAll.jl, you can simply call to make it work
julia> @useall MyModule
julia> f(x)
54
and use everything afterwards as if all definitions of your package/module were done in Main.
Note the missing dot, i.e. @useall MyModule instead of @useall .MyModule which is needed, as the latter one does not parse and therefore cannot be used. This is normally not an issue, as most of the time you will be working with packages anyway which never need the dot prefix.
This, of course, assumes, that you have the package installed and have executed using UseAll explicitly or added it to your startup.jl (the latter one being recommended).
It should be clear, that the demodularization which @useall effectively does is a terrible idea in general when used in packages. This is a development tool meant to be used in the REPL. @useall can be useful, however, if you have something closely coupled to a package, e.g. a runtests.jl which should test many internals of the corresponding package, where it might make sense to just @useall on the package to have all identifiers readily available in runtests.jl.
UseAll.jl tries to integrate well into your development workflow.
- When used in the REPL, it tries to support tab complete for package names. It “tries” because private REPL API needs to be used, so this is not guaranteed to work with all Julia versions, although it at least should fail silently without disturbing anything else if API changes.
- When used with Revise.jl, it tries to keep bindings in sync, i.e. if you load a package with
@useallinMainand add a binding to the package later (in the same REPL session), the symbol will also be added toMain. The caveats with “tries” are again the same.
The package is not yet registered, so currently you need:
]add https://github.com/PatrickHaecker/UseAll.jl/
I hope to find a suitable Github organization to maintain it there to avoid a single point of failure (maybe someone from JuliaDebug · GitHub is interested?).