3.5 Albatross Macros
Description: Albatross Macros
Keywords: albatross

#
3.5 Albatross Macros

In the previous section we demonstrated a program which can be used to display pages from a collection of template files. You might recall that the HTML in the template files was very repetitive. In this section you will see how Albatross macros can be used to introduce a common look to all HTML pages.

If we look at the `main.html` template file again you will notice that there really is very little content which is unique to this page.

    <html>
     <head>
      <title>Simple Content Management - main page.</title>
     </head>
     <body>
      <h1>Simple Content Management - main page</h1>
      <hr noshade>
      This is the main page.
     </body>
    </html>

Using Albatross macros we can place all of the boilerplate into a macro. Once defined, the macro can be reused in all template files.

The sample program from this section is supplied in the `samples/templates/content2` directory and can be installed in your web server `cgi-bin` directory by running the following commands.

    cd samples/templates/content2
    python install.py

First consider the macro in the `macros.html` template file.

    <al-macro name="doc">
    <html>
     <head>
      <title>Simple Content Management - <al-usearg name="title"></title>
     </head>
     <body>
      <h1>Simple Content Management - <al-usearg name="title"></h1>
      <hr noshade>
      <al-usearg>
     </body>
    </html>
    </al-macro>

Now we can change `main.html` to use the macro.

    <al-expand name="doc">
      <al-setarg name="title">main page</al-setarg>
      This is the main page.
    </al-expand>

Likewise, the `other.html` file.

    <al-expand name="doc">
      <al-setarg name="title">other page</al-setarg>
      This is the other page.
    </al-expand>

And finally the error page `oops1.html`.

    <al-expand name="doc">
      <al-setarg name="title">error page</al-setarg>
      <al-if expr="page == 'oops.html'">
       You actually requested the error page!
      <al-else>
       Sorry, the page <font color="red"><al-value expr="page"></font>
       does not exist.
      </al-if>
    </al-expand>

We also have to modify the application to load the macro definition before loading the requested pages.

    #!/usr/bin/python
    import os
    from albatross import SimpleContext, TemplateLoadError

    script_name = os.environ['SCRIPT_NAME']
    request_uri = os.environ['REQUEST_URI']
    page = request_uri[len(script_name) + 1:]
    if not page:
        page = 'main.html'

    ctx = SimpleContext('templ')
    ctx.load_template('macros.html').to_html(ctx)
    ctx.locals.page = page
    try:
        templ = ctx.load_template(page)
    except TemplateLoadError:
        templ = ctx.load_template('oops.html')

    templ.to_html(ctx)

    print 'Content-Type: text/html'
    print
    ctx.flush_content()

Test the program by trying a few requests with your browser:

http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py
http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py/main.html
http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py/other.html
http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py/error.html
http://www.object-craft.com.au/cgi-bin/alsamp/content2/content.py/oops.html

The only new line in this program is the following:

    ctx.load_template('macros.html').to_html(ctx)

This loads the file which contains the macro definition and then executes it. Executing the macro definition registers the macro with the execution context, it does not produce any output. This means that once defined the macro is available to all templates interpreted by the execution context. The template is not needed once the macro has been registered so we can discard the template file.

When you use Albatross application objects the macro definition is registered in the application object so can be defined once and then used with all execution contexts.

There is one small problem with the program. What happens if the browser requests `macros.html`? Suffice to say, you do not get much useful output. The way to handle this problem is to modify the program to treat requests for `macros.html` as an error.

Let's revisit the macro definition in `macros.html` and see how it works. Albatross macros use four tags; `<al-macro>`, `<al-usearg>`, `<al-expand>`, and `<al-setarg>`.

    <al-macro name="doc">
    <html>
     <head>
      <title>Simple Content Management - <al-usearg name="title"></title>
     </head>
     <body>
      <h1>Simple Content Management - <al-usearg name="title"></h1>
      <hr noshade>
      <al-usearg>
     </body>
    </html>
    </al-macro>

The `<al-macro>` tag is used to define a named macro. The `name` attribute uniquely identifies the macro within the execution context. In our template file we have defined a macro called `"doc"`. All content enclosed in the `<al-macro>` tag will be substituted when the macro is expanded via the `<al-expand>` tag.

In all but the most simple macros you will want to pass some arguments to the macro. The place where the arguments will be expanded is controlled via the `<al-usearg>` tag in the macro definition. All macros accept an ``unnamed'' argument which captures all of the content within the `<al-expand>` tag not enclosed by `<al-setarg>` tags. The unnamed argument is retrieved within the macro definition by using `<al-usearg>` without specifying a `name` attribute.

In our example we used a fairly complex macro. If you are still a bit confused the following sections should hopefully clear up that confusion.

Subsections

- 3.5.1 Zero Argument Macros
- 3.5.2 Single Argument Macros
- 3.5.3 Multiple Argument Macros
- 3.5.4 Nesting Macros