Util::EvalSnippet - eval snippets of code in the context of a caller marker


Use snippet files to make instant changes to apps that normally require a restart. Example usage:

    use Util::EvalSnippet;

    sub some_method {


When developing in many frameworks (Catalyst, mod_perl etc), every save involves an app reload that can take from a few seconds to over a minute on your dev server. This module helps you minimize the inconvenience by allowing you to develop code in snippets, saving as you go, and then merge your changes back into your application's module when you're done.


Default: "eval_snippet"



Place the function in your module, in a method that the app is not caching, and reload the app that will call that code.

A snippet will automatically appear in the ~/eval-snippets directory.

You can change the eval snippets directory by setting the SNIPPET_DIR environment variable, if you prefer.

If you need more than one snippet in a module, name them:

    package Some::Module;
    use Util::EvalSnippet;

    sub some_method {

When you run the code, the module creates the following snippet files in your snippets directory:


Snippets are created with header comments. Do not delete them.

Make changes and save in your snippets directory, then reload your view to see the updated code in action without having to wait for an app restart.

When you're finished with development, merge the module's snippets back into the module by running, in a shell:

    perl-eval-snippet --merge Some::Module

That will merge the snippets into the module, and remove the "use Util::EvalSnippet;" statement.

After merging, it's probably a good idea for you to examine the code in situ to confirm the spacing looks good and, of course, to confirm all is well.

If you're only done with one snippet, you can merge it in on it's own using:

    perl-eval-snippet --merge Some::Module-one

The "use Util::EvalSnippet;" statement is only removed if there are no more eval_snippet() calls left in the code.

Note: If you're working on multiple instances of a module namespace (different branches etc), either ensure you neame snippets uniquely, or ensure the SNIPPET_DIR environment variable is set differently for each. This tool is not designed (yet :D) to work across multiple instances of the same file.



By default, snippets are created in the ~/eval-snippets directory. If you want to change that, set the environment var SNIPPET_DIR to point to where you would like snippets saved.


If you want to, you can add a sanity check so that snippet code won't run outside of your development environment. If you set the ALLOW_SNIPPETS env var to a true value and use the module like this:

    use Util::EvalSnippet 'safe';

it will die unless the env var is set.

That way, the paranoid amongst you can be sure that the snippets are never run outside of your dev environment - since the code involves blind eval of a text file, this may or may not be a security concern for you.

If you end up using the module a lot, adding a git hook to reject commits containing Util::EvalSnippet code may also be useful.


As, basically, a templating solution, there are some things that are not easily dealt with.

For example, this module does not do anything clever with string interpolation, so some things will not work. The main inconvenience is embedded literal variables in strings. Eg, say you have a view that returns content to the browser:

    sub some_view {
      my $self = shift;

and you have this in a snippet:

    return '<p>The variable is called $x</p>';

it will not do what you think it should.

This should not be issues in most environments as you should be using templates for your views.

Another place where this may not work is for dynamically created variables.

Both of these issues involve bad design patterns anyway, so they won't affect you, right? :D


Copyright 2018 Clive Holloway

Licensed for distribution under the GNU GENERAL PUBLIC LICENSE

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 240:

'=item' outside of any '=over'

Around line 263:

You forgot a '=back' before '=head1'