SimplePlutoInclude.jl

Export the @plutoinclude macro to simplify including external files inside Pluto notebooks
Author disberd
Popularity
2 Stars
Updated Last
5 Months Ago
Started In
June 2024

SimplePlutoInclude

Build Status Coverage Aqua QA

This packages exports a single macro @plutoinclude which is a simplified version of the @plutoinclude macro which was exported by PlutoDevMacros.jl up to version v0.7.

Basic Functionality

This macro tries to simplify the process of including a julia file inside a Pluto notebook with the possibility of reloading the file once its contents are updated. The target file can be any valid julia file (including another Pluto notebook), and this macro simply performs the following steps:

  1. Create an empty temporary module (outside of the Pluto workspace)
  2. Include the target file within the temporary module
  3. Explicitly imports (from the module created in 1.) the names defined in the included file in the current Pluto workspace

You can check the test_notebook.jl file in the test folder (or the Video Examples) for some more usage examples.

Note

The temporary module is created during macro expansion time in order to be able to extract the names and explicitly import them in the expression generated by the macro. This means that reloading the contents of the file can only be done by manually reloading the cell containing the @plutoinclude macro.

Important

Any package that is imported or used within the included file must also be present in the environment of the notebook calling the @plutoinclude macro. This macro tries to be as simple as possible and does not handles the environment of the included file. For more complex cases, consider using the other macros defined in PlutoDevMacros.jl

Specifying the file to include

The path to the file to be included can be specified either as a plain String, or as any expression that will evaluate to a String in the caller module (i.e. the Pluto workspace where the @plutoinclude macro is called).

An example use of @plutoinclude is fed a path as input based on a variable defined in the notebook is the following: image

Warning

When specifying the path as an expression depending on variables/functions defined in the notebook itself, the @plutoinclude macro might behave strangely as the code loading is happening during macro expansion. The following two strange behaviors are important to know about when using variables/functions defined within the notebook as input to the macro:

  • The cell containing the macro might error when running for the first time after opening a notebook, depending on the cell loading order within the notebook. This is because the symbol/function is evaluated during the first macro expansion, so before the cell definining the symbol/function is first executed. This can easily be solved by manually re-running the cell with @plutoinclude.
  • The @plutoinclude macro will not reload the contents of the file upon reactive run (i.e. when the cell is ran because one of its dependencies has been changed, and not because it was manually re-run). This is because the macro is not expanded/compiled again upon reactive run, so the module containing the included file will not be re-created.
    • Since version v0.2.0, the macro will try to catch this behavior and show a warning in the macro cell when this happens, prompting the user to manually re-run the cell. See the Video Examples.

Customizing imported names

The names to be introduced into the Pluto workspace are simply extracted from the temporary module using Base.names(tempmodule), and filtering out some of the output names (e.g. gensym-ed names and other like eval and include).

By default, the call to Base.names will have the all keyword argument set to true in order to export all names defined directly within the included file.

The @plutoinclude macro accepts as additional inputs any number of assignments expression of the form name = value where value must be a Bool. These expression are parsed at the beginning of the macro expansion and grouped as kwargs that are passed to the Base.names call. One could example set the all kwarg to false as in the example below: image

Note

Setting all to false will not export any name defined in the included file unless something is explicitly marked with export or public within the file.

Note

If you want to avoid exporting some specific variables from an included Pluto notebook, like for example the variables defined with @bind, consider marking them in the original notebook as Disabled in file, so they will be commented out in the source file and will not be included in the temporary module generated by @plutoinclude.

Files containing a single module definition

Files that only contain a single module definition are treated differently. The macro, in this case, will import in the calling (Pluto) workspace the names extracted from this single module, instead of the names at the file top-level (which would only be the module's name).

Alternatives

The functionality provided by the @plutoinclude macro is very similar to the @ingredients macro from PlutoLinks.jl. The main difference is the fact that while @ingredients does not explicitly import any name inside the calling Pluto notebook, @plutoinclude does. This often simplifies interactive development as one does not need to always prepend the module name to access the variables defined within the file

Note

@ingredients also tracks changes in the file and rerun dependent cells when updating the file. While a mode supporting Revise is planned for the next release of SimplePlutoInclude, automatic reload of dependent cells is not planned for this macro as the reload of the file is intended to only be done manually to accidentally avoid triggering long-running cells each time a file is changed.

Video Examples

The following 3 video examples will show warnings that the macro throws when the path is specified as a symbol (and not directly as a string) and the path or contents of the pointed files are changed

Contents have changed

0d4a7233-185a-45b2-bf12-a549f9d3c2fd.mp4

Path has changed and is invalid

3f8e634c-ef8c-4c14-8c36-b687383a1aef.mp4

Path has changed and is valid

d3de18b3-69f8-41b4-b1ce-baa7ddaa5cb0.mp4

Single module files

This is an example showing that files containing a single module definition are treated by importing the names defined within the module itself (instead of the normal behavior that will only see the module as variable generated by the file):

f8278a86-fa0c-42ed-8233-0deaf903e50c.mp4

Warning when no names are imported

When a file is imported via @plutoinclude and no variables are extracted from it, the macro will output a warning. This is mostly happening when the all keyword is specifically set to false, as shown below:

98960eaa-9d84-46f7-bbbe-89a86ce10acc.mp4