As you can tell, plugins play a central role in setting up a package.
The three main entrypoints for plugins to do work are the [`prehook`](@ref), the [`hook`](@ref), and the [`posthook`](@ref).
As the names might imply, they basically mean "before the main stage", "the main stage", and "after the main stage", respectively.
Each stage is basically identical, since the functions take the exact same arguments.
However, the multiple stages allow us to depend on artifacts of the previous stages.
For example, the [`Git`](@ref) plugin uses [`posthook`](@ref) to commit all generated files, but it wouldn't make sense to do that before the files are generated.
But what about dependencies within the same stage?
In this case, we have [`priority`](@ref) to define which plugins go when.
The [`Git`](@ref) plugin also uses this function to lower its posthook's priority, so that even if other plugins generate files in their posthooks, they still get committed (provided that those plugins didn't set an even lower priority).
To understand how they're implemented, let's look at simplified versions of two plugins: [`Documenter`](@ref) to explore templating, and [`Git`](@ref) to further clarify the multi-stage pipeline.
First of all, `@with_kw_noshow` comes from [Parameters.jl](https://github.com/mauro3/Parameters.jl), and it just defines a nice keyword constructor for us.
The default values for our type are using [`default_file`](@ref) to point to files in this repository.
```@docs
default_file
```
The first method we implement for `Documenter` is [`gitignore`](@ref), so that packages created with this plugin ignore documentation build artifacts.
These two functions, [`gitignore`](@ref) and [`badges`](@ref), are currently the only "special" functions for cross-plugin interactions.
In other cases, you can still access the [`Template`](@ref)'s plugins to depend on the presence/properties of other plugins, although that's less powerful.
Hopefully, this demonstrates the level of control you have over the package generation process when developing plugins, and when it makes sense to exercise that power!
But what if we want to do a little more than just generate one file?
A good example of this is the [`Tests`](@ref) plugin.
It creates `runtests.jl`, but it also modifies the `Project.toml` to include the `Test` dependency.
Of course, we could use a normal [`Plugin`](@ref), but it turns out there's a way to avoid that while still getting the extra capbilities that we want.
There is also a default [`prehook`](@ref) implementation for [`BasicPlugin`](@ref)s, which checks that the plugin's [`source`](@ref) file exists, and throws an `ArgumentError` otherwise.
If you want to extend the prehook but keep the file existence check, use the `invoke` method as described above.
There are a few predicate functions for plugins that are occasionally used to answer questions like "does this `Template` have any code coverage plugins?".
If you're implementing a plugin that fits into one of the following categories, it would be wise to implement the corresponding predicate function to return `true` for instances of your type.