Some Quick Examples

1 The "Hello World" Example

This example shows how to create the simplest possible web site - one that it would be much easier to create by hand! You get to see some of the commands and basic method of using the MillScript. In this example, we are going to build a web site that has a single HTML page with the words "hello, world!" on it.

The first thing we need to do is create a working directory for our website files. Typically we would give this web site the same name as its domain name. We also need to tell the millscript system about it. The things we type are prefixed by the "$" prompt. End of line comments are prefixed with "#".

$ website --new hello.com
Checking whether hello.com is free ... ok
Creating folders :-
    .website ... ok
    .website/cache ... ok
    .website/conf ... ok
    inventory ... ok
    .website/classes ... ok
    output ... ok
    .website/var ... ok
done
        

Now let's go to our new web site.

$ cd hello.com
$
        

The first thing we need to do is write a template that will generate our page. We keep our templates, and many other resources, in a directory called inventory. You'll find this directory was created when the web site structure was built for you. This template will be written in XHTML and stored in inventory/hello.tp. The .tp file extension tells the MillScript interpreter that the contents are a template.

<!-- This is the content for inventory/hello.tp -->
<html>
<body>Hello, World!</body>
</html>
        

The next thing we need to do is write the top-level script in MillScript. This will have to instantiate the template and generate a page by using the page function. By default, the MillScript will look for a file called "site.ms". Here's our "site.ms" file. The .ms file extension tells the MillScript interpreter that this is a script.

# This is a MillScript end-of-line comment
htmlFile(
    "hello",    # name the HTML file, .html will be added
    hello()     # instantiate the template
);
        

At this point we are able to run the MillScript itself. It will produce its output in the "output" directory. It is perhaps a bit annoying that the output directory is fixed but, in my opinion, this reduces the chance of dreadful mistakes. Since we are in the website directory and want to mill the script "site.ms" we can run build site.ms without further ado. The build command picks up the right defaults from the context.

$ build site.ms
Lots of output
$
        

2 Working Quietly, Working Tersely

If You may prefer the "website" program to go about its work quietly unless it finds an error. In this case you can use the --quiet option (shorthand -q). We'll use it to clean out the directory we just created.

$ website --quiet --purge
Are you sure you want to purge? (y/n) y
$
        

In addition, shorthand options can be combined. Instead of writing --quiet and --new snafoo.com you can abbreviate it to this

$ website -q -n snafoo.com
$
        

and you can push the two options together and write

$ website -qn snafoo.com
$
        

When the "website" program sees an option that begins with only one "-" it explodes the remaining letters into their longhand version. In other words writing -qn is exactly the same as writing -u -p which is the same as writing --unattended --purge. And because this expansion is checked prior to anything else being done the accidental omission of a "-" is unlikely to cause damage.

$ website -unattended --purge snafu.com
Unknown option "d" in compact argument "-unattended"
$
        
" Example">

3 The "Hello, <Your Name Here>" Example

In this example we illustrate how to insert ad hoc material into a web site. To do this we will simply repeat the first example except we will substitute your name for the word "world".

The MillScript System provides a simple but powerful insertion method. When it is generating a page, if it encounters the custom tag

<item val=<em>script</em>/>
        

it will replace the tag with the result of the expression. Possibly the most common expression is a variable.

This feature combines very nicely with autoloading. When the compiler encounters an unknown global variable it searches the inventory for a file with a matching name. If it finds a file whose name, excluding any extension, is the same as the variable, it loads the file. If everything goes to plan, this will define the variable and compilation can continue.

In this case, we will add a file called "yourname.txt" to the inventory. The .txt extension tells the MillScript compiler that the file is raw ASCII text.

The "site.ms" file remains the same as above but the file "hello.tp" needs to be altered to include our name.

<html>
<body>Hello, <item val="yourname"/>!</body>
</html>
        

You do not have to supply the ".txt" extension - in fact you shouldn't. The extension is worked out by Millscript by inspecting the files in the Inventory. By omitting the extension this gives you the freedom to change from GIF to JPG (for example) without altering a line of code.

Now, we should create the file "yourname.txt" with your own name in it - or the file "yourname.gif" with a picture of yourself. It is your choice. In either case, Millscript will pick up the appropriate file and do the right thing.

To create your web site you simply run Millscript exactly as before,(build site.ms).

4 A Little MillScript

Before we go any further, it would be a good idea to have quick review of some of the basic elements of MillScript. We'll need to be able to define functions and use them, declare variables and use if-forms. For a more extended introduction you can read the MillScript Language Summary.

We define functions in MillScript with the function syntax. Let's write a function that is passed two arguments and returns their sum :-

function add( x, y ) =>
    x + y
endfunction;
        

Here's another function that checks out whether a string is non-empty.

function nonempty( s ) =>
    s /= ""
endfunction;
        

There are several points to note:

  1. The => symbol is used to separate the definition part from the main body of the function.
  2. You don't need an explicit return statement to return results from a function.
  3. You separate expressions with semi-colons (;). These are required only to improve error reporting.
  4. There are lots of keywords that operate like brackets in MillScript. function has to be paired up with endfunction, for example. Other important examples are if/endif and for/endfor. This is a bit more verbose than, say, JavaScript but it is a lot more robust against simple mistakes.
You can call functions using the familiar 'prefix' form :-
add( 1, 2 )
        
Or, equivalently, you can use the 'dotted' form :-
1.add( 2 )
        
These mean exactly the same thing. (In the following examples we stick to the prefix form in order to keep things simple. This syntactic freedom is provided to help you more directly express your intentions. You can declare variables with the var syntax. This is written like this :-
var x = nonempty( "foo" );
        

If you do not want to subsequently update the variable you should consider the alternative const declaration. This marks the variable so that any attempt to update it will generate a complaint.

If-expressions are easy to understand. You can use them as statements or expressions.

# use as statement.
if x < y then
    println( "x < y" );
else
    # use as an expression.
    var d = if x - y > 1 then "big" else "small" endif;
    println( "the difference is ", d );
endif
        

For loops are very sophisticated in MillScript - in fact they are one the most powerful looping constructs found in any programming language (to the best of my knowledge). For our examples, we only need to know a little bit about them.

We can use them to iterate over all the numbers between two limits, the elements of a list or the key-value pairs of a map. Here's some simple examples.

# Iterate from 1 to 10.
for i from 1 to 10 do
     .... code involving i ... 
endfor;

# Iterate over the elements in a list L
for e in L do
     .... code involving e ... 
endfor;

# Iterate over the key/value pairs of a map M
for k & v in M do
     .... code involving k and v... 
endfor;
        

For loops declare their loop variables for you. In fact it is not possible to introduce an uninitialized variable in MillScript! Furthermore, these loop variables are declared as "const" so they are protected against accidental assignment.