Modules in Mokvino Web


Mokvino Web is a collection of scripts for GNU Awk, GNU Make and Mokvino which can be used to build and maintain websites.

Groups of related user-defined macros to be used by several pages should be placed in modules. Define a module foo by placing macro definitions in etc/foo.m5. The user may define as many uniquely named modules as necessary. The content of a user-defined module will usually have the following form:

shift(

# User-defined macros go here.

)\

The enclosing shift ensures that blank lines within the module will be essentially ignored.

To use the module from any source file, including other modules, write:

load(`foo')\

This kind of call is idempotent; if the module has already been loaded, its contents won't be expanded again. Mokvino Web also records the fact that the source file that causes a module to be loaded will be dependent on the file that holds the module. Use loadsys instead of load if you want to prevent that record.

Loading modules automatically

Don't want to have to go back to the top of a page to load a module to use a macro? Define the macro in etc/page.m5, so it's available to every page! But hold on — any changes to the macro will cause the entire site to be rebuilt, because almost everything uses etc/page.m5.

You can avoid that by keeping the macro in a separate module, but defining a loader with the same name in etc/page.m5:

# In etc/page.m5
define(`IMPLNOTE', `load(`implnote')\
indir(`$$0'$$!?@$$?@)')
# In etc/implnote.m5
define(`IMPLNOTE', ``This is an implementation note.'')

Your page will now only depend on etc/implnote.m5 if it uses IMPLNOTE.

The idiom is likely to be well used, so a predefined macro autoload is available to do the work for you, with the first argument being the module to load, and remaining arguments being macros defined by it:

# In etc/page.m5
autoload(`implnote', `IMPLNOTE')\

But there's still a problem. Adding a new loader to etc/page.m5 also will cause the entire site to be rebuilt. The solution is to ensure your site is up-to-date first, then define the loader, then touch all your targets so they won't be rebuilt. Then touch the sources of pages that use the new macro. If it's truly new, that won't be very many!

More robustly, you could place your auto-loading macros in a separate module:

# In etc/pagesys.m5
autoload(`implnote', `IMPLNOTE')\

…and then load it from their original location without recording dependencies:

# In etc/page.m5
loadsys(`pagesys')\

The first argument of autoload is the name of the user module to load, and all remaining arguments are names of macros defined by that module. Note that autoload does nothing if the module has already been loaded, so it won't destroy real definitions if it happens to be expanded after the module has been loaded.

Predefining macros

If you want some macros predefined, without having to load any modules explcitly, you can specify a file containing them in Makefile:

# In Makefile
M5WEB_PREDEFINED += etc/common.m5

It will not be treated as a module, so don't try to load it as one with load or loadsys. Its main use is to set up auto-loaded macros.