Qompose

Qompose Tutorial

To start using Qompose, let's start with a simple page. Begin your .qf file like this:

|||

... and then code your page as normal, taking care to double any $ signs and not to start any new lines with a #, a - or a | unless you escape them with a \. (Remember that the blank page, which is what ||| declares, is the default token.) Such a page is reasonably pointless, however, because Qompose was designed for making it easier to build a collection of pages with templating methods. The best way to tackle this is to create several pages and see what we can do with Qompose's tokens.

The obvious method is to put the HTML headers and footers aside. Like this:

|html header||
<html>
<head>
<title>My Web Pages</title>
</head>
<body>

|html footer||
</body>
</html>

Now you can create your pages like this:

|||
$html header.
<h2>My web pages</h2>
<p>
These are my web pages.
</p>
$html footer.

The substitutions of $html header. and $html footer. will, of course, do the obvious. And they can be re-used in other pages you build under Qompose. This specific example gets the more useful the more complex you have built your HTML headers.

Still, this example is probably a bit contrived and reasonably simplistic. But we can expand it further. First of all, let's create some pages with a bit of design. Here is what they look like.

On the surface, this looks like something that would be easy to create with four static pages. But notice that they all have a common look. What if I wanted to change the look one day? Qompose lets me isolate that sort of thing reasonably easy. First we have the header and footer tokens:

|html header||
<html>
<head>
<title>Qompose Example 1</title>
<style type="text/css">
 body { background-color: #efefef; 
        font: 14pt Verdana, Arial, sans-serif; 
        color: #660066;
        margin: 1.5em; }
 a { color: #0000cc; }
 a:visited { color: #000066; }
 h2 { color: #006600; border-bottom: solid #006600; }
</style>
</head>
<body>

|html footer||
</body>
</html>

They contain some style sheet entries and the common page code. Next we have the default page:

|||
$-html header.
<h2>My pages</h2>
<p>
Welcome to my web pages!
</p>
$-all page links.
$html footer.

Notice that this time we are referencing the $html header. token with a leading dash: $-html header. This tells Qompose to expand other token references in that token along the way. As it happens, there aren't any, but look we do it again for $-all page links. Here is what $-all page links. is:

|all page links||%= $*page name. repl
$-page link.$!page name+.$!page title+.

This token obviously needs to be recursively expanded. Ignoring the %= stuff for the moment, you see that including this token will expand the $page link. token, then will increment without expanding $page name. and $page title. What does that do? Actually, "increment" is the wrong word. Qompose supports multiple entries having the same token name, but referencing it will only ever return one entry. This is how you get to the next one.

The %= turns the rest of the line into an RPN expression. Remember that the RPN processor begins with the rest of the token's text on the stack. This expression then gets the number of entries called $page name., then replicates the text already on the stack that number of times. So if there were eight entries called $page name., then $all page links. would be expanded eight times. And since there is an increment for $page name. (and $page title.) the practical upshot of this expression is that $page link. is expanded once for every entry called $page name.

So what's $page link.?

|page link||
<p><a href="example1a.qf?$page name.">$page title.</a><p>

This is how we build the list of links on the page! Setting aside the URL for the moment, this is the kind of processing Qompose was created for. Whilst it would be possible to simply list all the relevant URLs and their titles, it would make maintaining such a list a headache. Instead, this neatly and elegantly will generate a full list no matter how many entries there are. And you only have to change or add entries in one spot.

These two tokens could easily have been combined into one. The reason I didn't do this was mostly because there are another two tokens performing a similar function that I wanted to mirror (you'll meet them shortly). The other reason is that I've used this trick in several other pages so I know it works.

Now for that URL. Qompose always loads a null token as the page, so to load another page, we have to use another file. But this time, we're supplying a parameter. More this shortly. Last, we have rather different line.

-include example1b.qf

This simply loads the indicated file at this point. Why use an external file? Because we have a second page that needs it, too. So putting it into a separate file means they can both access it.

So let's look at the other file.

|||
$-html header.
$-all page content.
$html footer.

Once again, we see the by-now familiar null token, $html header. and $html footer. but in the middle we only have a token called $all page content. Where's the HTML?

|all page content||%= $*page name. repl
$-page content.$!page name+.$!page title+.$!page text+.

|page content||%= $page name. $1. == drop
<h2>$page title.</h2>
$page text.

Whilst it seems the HTML seems to have dropped off to a trickle, the truth is that we're still fishing out which page to show. These two tokens are of much the same structure as the tokens $all page link. and $page link. but there's a key difference: the second token has an expression. When we gave the URL in $page link., we also referenced the token called $page name., supplying it in a fashion that makes it the first parameter. When actually evaluating that URL, any parameters you supply are available as $1., $2., etc.

And that's what we're doing here. Since the URL has said which page to load, we have to look at all of them and only display the right page. The expression compares the current value of $page name. with the value that was supplied on the URL (which was $1.). If they don't match, this token suddenly becomes nothing and Qompose keeps going in the token that called it. If they do match, then the RPN expression continues. The comparison happens to leave the matched value on the stack, so we have to drop it off to leave the proper contents of the token.

It is at this point that the imperative nature of Qompose becomes clear. There is no way of coding it the way you would in C or Perl, which is, loop until you find it and then stop. In Qompose, you loop on all of them, and set it up so that only the one you want will respond.

Lastly, there is an include line:

-include example1.qf

Hang on! This is just including the first file! Well, yes. You have to remember that we have some common elements in the first file that the second needs. But since Qompose's tokens are list-aware, it is sensitive to the order in which tokens and token lists are declared. Putting the include here therefore accomplishes three things:

  1. We get the common tokens, like $html header., that we're using.
  2. We also get an include to the data file (example1b.qf>
  3. By putting after this files's ||| token, the one declared in the included file is simple never used.

Elegant? I think so.

Finally, we have the content of the three pages:

|page name||cat
|page title||My cat
|page text||
<p>
Well, I don't have a cat that's <em>mine</em> 
as such. Instead there's a cat who is owned by the other 
people I live with and she seems to like me lots.
</p>
<p>
I don't have a picture of her, sorry. I should, I know.
</p>

|page name||PC
|page title||My Computers
|page text||
<p>
I have several PCs, all networked together (ooh - aren't 
I a nerd!). One of them acts as a big file server for me
and some of my housemates.
</p>

|page name||Me
|page title||Me
|page text||
<p>
What did you want to know about me? Apart from the fact 
I work with computers, of course. (Which should be quite
obvious.)
</p>

As you can see, we have multiple entries for the three tokens. It is a matter of a few moments to add a fourth, and the links page and the real page all work automatically.

In a bigger site, the actual contents would not be in tokens like this, but be in their own files that are loaded with the $< construct. The -include directive can also be used to pool common tokens for several files. The Qompose web site, for instance, puts tokens similar to $html header. in a file called html.qf. It provides support for local header graphics, custom style sheet extensions and navigation bars - all catered for by particular tokens being declared in the local file. Other areas of this web server put their link list into a separate file, again, for inclusion by several .qf files.

Additional tricks are also possible with the RPN processor. Although you can probably figure out how the Qompose documentation is presented, the Previous and Next links at the bottom of the page are also done automatically.

I should add that this is probably just one way to do it - it happens to be the way I do it, but hopefully now you will be able to experiment with the full range of abilities in Qompose.

< Prev: Setting up Qompose> Next: Change Log