GNU   davin.50webs.com/webdesign
a GNU world order – your home of everything that is free

       Main Menu          Research Projects         Photo Album            Curriculum Vitae      The Greatest Artists
    Email Address       Computer Games          Web Design          Java Training Wheels      The Fly (A Story)   
  Political Activism   Scruff the Cat       My Life Story          Smoking Cessation          Other Links      
      Tutorial 1             Tutorial 2               Tutorial 3                   Tutorial 4                 Tutorial 5      
      Tutorial 6             Tutorial 7               Tutorial 8                   Tutorial 9                 Tutorial 10      
      Tutorial 11         Dec/Hex Codes   H.T.M.L. ASCII Codes         Using Emacs           Download Links  


Web design course tutorial 6 : smart use of m4

Using the m4 language cleverly you can eliminate most of the tiresome repetitive work that is needed to build a complex Website. This tutorial will take you through some uses of m4 for this purpose.

§ 6.1 Smart comments

With the following macro definition in place:

m4_define([m4_ignore],)

you can add comments to your m4 source code that do not appear in the H.T.M.L. output. Conventional H.T.M.L. comments <!-- ... --> can be viewed in a Web browser by selecting the View Source (Internet Explorer) or View Page Source (Mozilla Firefox) menu button. Calls to the m4_ignore macro such as

m4_ignore(I do not show up in the H.T.M.L. code)

do not show up in the H.T.M.L. output and are therefore a safe place to put comments that you don't want the users of your Web pages to read, such as swear words and secret information.

§ 6.2 Number of years since a given date

With the following macro definition in place:

m4_define([m4_years],[m4_eval((((12 * 32 * m4_esyscmd(date +%Y) + 32 * (m4_esyscmd(date +%m) - 1) + m4_esyscmd(date +%d))
- (($1 * 12 * 32) + ($2 * 32) + $3))) / (12 * 32))])

The following macro call: m4_years(1973,06,17) prints out the number of years elapsed since my date of birth, i.e. my age in years.

§ 6.3 Questions and answers in the same source file

When writing Web tutorials (such as this one) it is useful to keep your questions and the answers to those questions in a single source file. In Question 6.15 you will write a macro ANSWER so that answers are not visible in question pages but are visible in the answer pages. For symmetry it is also useful to have a macro called QUESTION so that your single source file can look something like this:

QUESTION(1, What is George Bernard Shaw's middle name?)
ANSWER(1, Bernard)

QUESTION(2, How do you spell H.T.M.L.?)
ANSWER(2, H.T.M.L.)

QUESTION(3, What is the square root of 144?)
ANSWER(3, 12)

QUESTION(4, How many loaves are there in a baker's dozen?)
ANSWER(4, 13)

QUESTION(5, What is the meaning of life?)
ANSWER(5, 42)

§ 6.4 Two versions of your CV

By moving most of the code from your CV from cv.hts to cv.m4 you can have two versions of your CV, once called cv.hts for your Website, and another called cv-private.hts containing private information and more suitable for printing than your public CV. Your private CV can differ in the following ways from your public CV:

§ 6.5 Automatic numbering of sections

With the following definitions in place:

m4_define([H2_COUNT],0)
m4_define([H2],[m4_define([H2_COUNT],m4_incr([H2_COUNT]) <h2>H2_COUNT. $1 </h2>)])

You can write the following m4 code:

H2(First section)
H2(Second section)
H2(Conclusion)

and it will generate the following H.T.M.L. code:

<h2>1. First section</h2>
<h2>2. Second section</h2>
<h2>3. Conclusion</h2>
I use a similar system to this for these Web tutorials.

§ 6.6 Questions


Question 6.1: Unzip the archive file tutorial-6.tar.gz using Winzip or the tar command for the purposes of completing this tutorial.


Question 6.2: Define a macro SMILEY that expands to :-). Recall from tutorial 4 that the closing bracket character ) is problematic for m4, and therefore needs to be written using an H.T.M.L. Ascii code. See the H.T.M.L. Ascii Codes 0 - 127 for this.


Question 6.3: Define a macro DAGGER which evaluates to a red dagger (). You need to use the <font> tag as well as the H.T.M.L. code &dagger; (the H.T.M.L. code for dagger).


Question 6.4: Define a macro COOLNERDS which expands . You will need to use the <small> tag or the <big> tag twice.


Question 6.5: Open the file tutorial-6/godel.hts in Emacs. Re-write the file so that the name Godel is spelt with a German umlaut (ö). You should find the following H.T.M.L. code useful for generating the umlaut: &ouml;. The dumb way to do this is by replacing ever occurrence of Godel with G&ouml;del. However this makes your H.T.M.L. quite ugly to read. The smart way to to define an m4 macro "Godel" so that every occurrence of Godel is replaced by G&ouml;del. Define such a macro. This is a rare case where your macro name should not be in all capitals. Run m4 on the source file by changing to the tutorial-6 folder in Emacs and pressing F9.


Question 6.6: Define four macros naive, Naive, naively and Naively that expand to naïve, Naïve, naïvely and Naïvely, respectively (the "clever" way of writing these words). Using these macros you can write naive and naively and have it automatically expand to the clever way, without needing to clutter your H.T.M.L. code with &xxx; characters. To do this you will need the &iuml; character. Like Godel (above), this is a rare case where your macro name should not be in all capitals.


Question 6.7: Define a macro m4_new so that it expands to <img src="new.png" width=28 height=11>. This makes it easier to add images to documents. You can find the image new.png in the tutorial-6 folder.


Question 6.8: Define a macro m4_under_construction that displays the following centralised animated graphic:

You can find the image file under-const.png in the tutorial-6 folder.


Question 6.9: Define a macro WEBSITE which expands WEBSITE(www.davinpearson.com) to

<a href="http://www.davinpearson.com"><code>www.davinpearson.com</code></a>
  

This makes it easier to add links to Websites in your H.T.M.L. code.


Question 6.10: Define a macro which expands Here is some text to:

<font color="red"><b>Here is some text</b></font>
  


Question 6.11: Define a macro ENTRY so that the following text:

<table align=center>
   ENTRY(apple.jpg,  200, 186, This is a picture of an apple.)
   ENTRY(banana.jpg, 200, 150, This is a picture of a banana.)
   ENTRY(carrot.jpg, 200, 150, This is a picture of a carrot.)
</table>

expands to the following:

<table align=center>
  <tr>
    <td>
      <img src="apple.jpg" width=200 height=186 alt="apple">
    </td>
    <td>
      This is a picture of an apple.
    </td>
  </tr>
  <tr>
    <td>
      <img src="banana.jpg" width=200 height=150 alt="banana">
    </td>
    <td>
      This is a picture of a banana.
    </td>
  </tr>
  <tr>
    <td>
      <img src="carrot.jpg" width=200 height=150 alt="carrot">
    </td>
    <td>
      This is a picture of a carrot.
    </td>
  </tr>
</table>

apple This is a picture of an apple.
banana This is a picture of a banana.
carrot This is a picture of a carrot.

The code in Emacs. The code in a Web browser.

NOTE: the second ($2) and third ($3) arguments represent the width and height of the image, respectively.


Question 6.12: Then rewrite the macro so that the above text expands to the following:

<table align=center>
  <tr>
    <td>
      <img src="apple.jpg" width=200 height=186 alt="apple"><br>
      <center>
        This is a picture of an apple.
      </center>
    </td>
  </tr>
  <tr>
    <td>
      <img src="banana.jpg" width=200 height=150 alt="banana"><br>
      <center>
        This is a picture of a banana.
      </center>
    </td>
  </tr>
  <tr>
    <td>
      <img src="carrot.jpg" width=200 height=150 alt="carrot"><br>
      <center>
        This is a picture of a carrot.
      </center>
    </td>
  </tr>
</table>

apple
This is a picture of an apple.
banana
This is a picture of a banana.
carrot
This is a picture of a carrot.

The code in Emacs. The code in a Web browser.

What is the advantage in separating the logic from the layout? (As is done in the above.)


Question 6.13: Suppose we change the m4 source code from the previous two questions to the following:

<table align=center>
   ENTRY(apple.jpg,  200, 186, This is a picture, a picture of an apple.)
   ENTRY(banana.jpg, 200, 150, This is a picture of a banana.)
   ENTRY(carrot.jpg, 200, 150, This is a picture of a carrot.)
</table>

Use the definition of the ENTRY symbol from the previous question and run m4 on the H.T.S. source file. When you load the corresponding H.T.M.L. code into a Web browser you will notice that only part of the sentence for the first call to the ENTRY macro is printed. Your task is to change the above code so that the full sentence is printed out. I can think of four ways of doing this: Two using square brackets to quote the fourth argument, one using the H.T.M.L. Ascii code for the comma character and the fourth using the COMMA macro that you learnt about in Section Section § 4.9. See if you can think of all of the ways. A bonus mark is available for anyone who can think of another different way!


Question 6.14: Add the following macro definitions:

m4_define([COL1],#ffffee)
m4_define([COL2],#ffeedd)

to the following code:

<table border=1 width="25%" align=center>
  <tr><td bgcolor="#ffffee">Apple</td></tr>
  <tr><td bgcolor="#ffeedd">Banana</td></tr>
  <tr><td bgcolor="#ffffee">Carrot</td></tr>
  <tr><td bgcolor="#ffeedd">Dog</td></tr>
  <tr><td bgcolor="#ffffee">Egg</td></tr>
  <tr><td bgcolor="#ffeedd">Fish</td></tr>
</table>

Apple
Banana
Carrot
Dog
Egg
Fish

The code in Emacs. The code in a Web browser.

so that every occurrence of #ffffee is replaced by COL1 and every occurrence of #ffeedd is replaced by COL2. What is the advantage achieved by making this change?


Question 6.15: Create a file both.m4 that contains the questions and answers from Section § 6.3 and the following line of m4 code at the top:

m4_define([QUESTION],<p><b>Question $1:</b>$2<p>)

Create a file answers.hts which contains the following m4 code:

m4_define([ANSWER],<p><b>Answer $1:</b>$2<p>)
m4_include(both.m4)

When you run m4 on this file it creates a file called answers.html containing the questions and the answers to those questions. The next step is the challenge: Write another file called questions.hts which is like the above file (answers.hts), except that the answers do not show up. You will need to redefine the ANSWER macro to do this.


Question 6.16:  † Tricky Modify both.m4 so that the question and answer numbers in the calls to the QUESTION and ANSWER macros are not present, and rewrite the QUESTION and ANSWER macros in the three files both.m4, questions.hts and answers.hts so that they put the question and answer number in automatically. See Section § 6.5 for a hint on how to do his.


Question 6.17: Write two macros BEGIN_CENTER and END_CENTER so that the following m4 code:

BEGIN_CENTER
<pre>
Hello Adam
Hello Babara
Hello Colin
</pre>
END_CENTER

shows up centralised in a Web browser like so:

Hello Adam
Hello Babara
Hello Colin

These macros are useful for centering diagrams, equations and other special text. I use them a lot for these tutorials. You will need to use the following H.T.M.L. tags to get the right result: <table>, <tr>, <td> and possibly <center>.


Question 6.18: Write a macro m4_last_modified that expands to Last Modified: Mon Nov 13 23:34:09 NZST 2006, where the current date is printed. You will need to use the <small> tag and the m4_esyscmd macro, as well as the date command that prints the current date.


Question 6.19:  † Tricky Suppose that the following definition is in place:

m4_define([m4_ignore],)

write some m4 code that evaluates to m4_ignore without calling the macro m4_ignore. The seemingly obvious way to do this is to use square brackets [ and ] to quote the macro call. But this technique fails if you are inside one or more macro calls. Inside more macro calls needs more square brackets so in general it is difficult to use the quoting technique. I can think of two better ways to do this. The first and best way is to use the H.T.M.L. Ascii code for one of the letters in the symbol m4_ignore so that it doesn't evaluate the macro. The second (not as good) way is to temporarily undefine the m4_ignore macro and redefine it afterwards.


Question 6.20:  † Tricky Define a macro PATCH_EMAIL that expands PATCH_EMAIL(hello@example.com) to hello <i> at </i> example <dot> com. This is useful because it is dangerous to put an email addresses onto a Website since that is an invitation to spammers to send spam to that address. The following macros will be useful:

m4_patsubst(hello@example.com, \., &nbsp; <i> dot </i> &nbsp;) expands to hello@example <i> dot </i> com.

m4_patsubst(hello@example.com, @, &nbsp; <i> at </i> &nbsp;) expands to hello <i> at </i> example.com.


You can view the answers to this tutorial. A password is required.

Back to Web Design Course
This page has the following hit count:
| Main Menu | Research Projects | Photo Album | Curriculum Vitae | The Greatest Artists |
| Email Address | Computer Games | Web Design | Java Training Wheels | The Fly (A Story) |
| Political Activism | Scruff the Cat | My Life Story | Smoking Cessation | Other Links |
| Tutorial 1 | Tutorial 2 | Tutorial 3 | Tutorial 4 | Tutorial 5 |
| Tutorial 6 | Tutorial 7 | Tutorial 8 | Tutorial 9 | Tutorial 10 |
| Tutorial 11 | Dec/Hex Codes | H.T.M.L. ASCII Codes | Using Emacs | Download Links
Last modified: Mon Apr 11 19:16:54 NZST 2016
Best viewed at 800x600 or above resolution.
© Copyright 1999-2016 Davin Pearson.
Please report any broken links to