Het maken van tekstbestanden met m4 macro's

ArticleCategory:

Webdesign

AuthorImage:

[Photo of the Author]

TranslationInfo:

original in en John Perr 

en to nl Tom Uijldert

AboutTheAuthor:

Linux gebruiker sinds 1994; hij is één van de franse redacteuren van LinuxFocus.

Abstract:

In deze les wordt beschreven hoe men het onderhoud van tekst- en HTML bestanden kan vereenvoudigen met behulp van de m4 macro processor.

ArticleIllustration:

[Illustration]

ArticleBody:

Introductie

Een macrotaal is vaak nodig bij het gebruik van een tekst editor. De meeste hebben reeds zo'n mogelijkheid. Zelfs programmeurs hebben hierover de beschikking middels de C preprocessor cpp. Bij een toepassing als het onderhoud van configuratiebestanden of het onderhouden van een kleine website, kan de GNU/m4 macro processor een handig hulpmiddel zijn om het werk te verlichten. De GNU/m4 macro processor is een standaard onderdeel van Linux en is ook een standaard bij Unix gebruikers.

Hieronder laten we zien hoe de GNU/m4 macro processor gebruikt kan worden in het onderhoud van de HTML pagina's van een kleine website. Het pakket zorgt voor coherentie over de hele site. Uiteraard zijn er tientallen manieren om hetzelfde te bereiken met andere hulpmiddelen; dat is het mooie van Unix.

Deze techniek wordt gebruikt voor het construeren van het overbekende bestand sendmail.cfg. Er is een m4 macro-pakket te verkrijgen bij de universiteit van Berkeley en ontworpen door Eric Allman.

De GNU/m4 macro processor mogelijkheden houden niet op bij het veranderen van tekst en HTML. Het kan heel handig zijn voor programmeurs die de mogelijkheden van CPP uit willen breiden of voor diegene die de mogelijkheden van CPP ook in andere talen willen toepassen.

Definitie

Een macro processor is een programma dat commando's (macro's) interpreteert die zijn gedefinieerd door de gebruiker. Macro's worden meestal vermengd met tekst om te worden verwerkt. De volgende definitie bijvoorbeeld:

define(AUTHOR,`Agatha Christie<[email protected]>')

geeft de mogelijkheid om het woord AUTHOR op welke plaats dan ook in een tekst te zetten. Het zal worden vervangen door "Agatha Christie<[email protected]>" na bewerking door m4. Er zijn natuurlijk ook bruikbaarder functies, die we nu gaan bekijken.

Een voorbeeld

Laten we aannemen dat we een website moeten onderhouden met daarop dezelfde pagina's maar in verschillende talen. Verder heeft iedere pagina dezelfde kop en voet, om de site een coherent aanzien te geven. Om de zaak eenvoudig te houden en te voorkomen dat we een browser nodig hebben om het resultaat te bekijken, zullen we alleen met tekst werken. Hierdoor zijn gebruikers van Lynx ook in staat om de site te bekijken. Hier is de HTML-code voor 1 pagina:

HTML Versie

  
<!-- Start of header -->
<HTML>
<HEAD>
<TITLE>Lynx homepage</TITLE>
<META name="description" content="Site lynx et m4"> 
</HEAD>
<BODY BGCOLOR="#FFFFFF" LINK="#008000" VLINK="#808080" ALINK="#8080FF">
<TABLE>
  <TBODY>
  <TR><TD align=middle colspan="2">
      <H1>Lynx a fully-featured World Wide Web client for character-cell
displays</H1>
  <TR><TD align="left" valign="top" width="15%">
      <a href="./index-en.html">English</A><BR>
      <a href="./index-fr.html">French</A><BR>
      <a href="./index-es.html">Italian</A><BR>
      <a href="./index-it.html">Spanish</A><BR>
      <a href="./index-de.html">German</A><BR>
      <TD align=left>
<!-- End of header -->

      <P>Links to the current sources and support materials for Lynx are
   maintained at <A HREF="http://www.crl.com/~subir/lynx.html">Lynx
   links</A></P>
      <P> and at the Lynx homepage
      <A HREF="http://lynx.browser.org/">Lynx
      Information.</A></P>
      <P>View these pages for information about Lynx, including new
      updates.</P>

      <P>Lynx is distributed under the GNU General Public License (GPL) without
   restrictions on usage or redistribution.  The Lynx copyright statement,
   "COPYHEADER", and GNU GPL, "COPYING", are included in the top-level
   directory of the distribution.  Lynx is supported by the Lynx user
   community, an entirely volunteer (and unofficial) organization.</P>

<!-- Start of footer -->
</TBODY>
</TABLE>
<HR size="0" noshadow>
<FONT SIZE=-2>
<EM>Page maintained by John Perr.<BR>
Page updated on 25/07/99
- © <A HREF="mailto:[email protected]">lynx.browser.org</A>1999
</EM></FONT>
</BODY>
</HTML>
<!-- End of footer -->
Hier is het resultaat:
[Click here to enlarge image] [Click here to enlarge image]
met lynx met netscape

Alle pagina's hebben een kop en voet in dezelfde stijl. Alleen de taal en de inhoud zullen verschillen. We gaan nu m4 macro's ontwerpen die in de HTML tekst worden verwerkt, om daar alle herhaalde data uit te halen.
Alvorens op de details van die macro's in te gaan, gaan we eerst kijken naar bovenstaand voorbeeld maar dan met macro's:

Macro Version

  
LYNX_TITRE(Lynx a fully-featured World Wide Web
            client for character-cell displays)
LYNX_ENTETE(Lynx homepage)

      <P>Links to the current sources and support materials
      for Lynx are maintained at
      <A HREF="http://www.crl.com/~subir/lynx.html">
      Lynx links</A></P>
      <P> and at the Lynx homepage
      <A HREF="http://lynx.browser.org/">
      Lynx Information.</A></P>
      <P>View these pages for information about Lynx,
      including new updates.</P>

      <P>Lynx is distributed under the
      GNU General Public License (GPL) without
   restrictions on usage or redistribution.
   The Lynx copyright statement, "COPYHEADER",
   and GNU GPL, "COPYING", are included in the top-level
   directory of the distribution.
   Lynx is supported by the Lynx user community,
   an entirely volunteer (and unofficial) organization.</P>
LYNX_PIED

Hiermee is het schrijven van HTML pagina's eenvoudiger en de leesbaarheid wordt niet gehinderd door HTML-tags. Om pagina's in andere talen te maken, moeten er vertalingen worden gemaakt. De franse pagina wordt dan als volgt:

  
LYNX_TITRE(Lynx un navigateur en mode console)
LYNX_ENTETE(Un site pour les utilisateurs de lynx)

   <P>Visitez le
   <A HREF="http://lynx.browser.org/">
   site officiel de lynx</A>
   pour plus d'informations sur Lynx,
   y compris les nouvelles mises � jour.</P>
       
   <P>Les liens vers les sources de la version
   courante et divers supports pour Lynx sont
   tenus � jour sur le site
   <A HREF="http://www.crl.com/~subir/lynx.html">
   liens Lynx</A>.</P>

   <P>Lynx est distribue dans le cadre de la lisence GNU
   (General Public License - GPL)
   sans restriction sur son utilisation ni sa distribution.
   Les mentions des droits de reproduction de Lynx, "COPYHEADER",
   et GNU GPL, "COPYING", sont inclus dans la racine de
   l'arborescence de la distribution. Lynx est supporte par
   la communaute des utilisateurs de Lynx, une communaute
   enti�rement benevole (et non-officielle).</P>
LYNX_PIED

Bij iedere taal worden dezelfde macro's LYNX_TITRE, LYNX_ENTETE en LYNX_PIED gebuikt maar met andere argumenten. Deze drie macro's zijn een efficiënt alternatief voor de HTML codes voor de kop- en voet regels. Dit is het belangrijkste voordeel van het systeem: de definitie van de kop- en voet regels zijn consistent over de hele site. Als de opmaak van kop of voet moet worden veranderd, kan worden volstaan met een wijziging van de macro-definities in plaats van het met de hand wijzigen van iedere pagina.

Definitie van macro's

Hierboven zijn 3 macro's gedefinieerd voor het realiseren van het grootste deel van de opmaak. Hieronder het bestand wat de macro's definieert. Toelichting volgt:
  
divert(-1)
# File mac.css
# Version 1.0 M4 macros for Lynx
#
# A file trans-LANG.m4 is defined for each
# language, based on the french one.
# If no translation file exist,
# french is the default.
#
divert(0)
changequote({,})dnl # change quotes to curly braces
ifdef({LANG},,{define({LANG},{fr})})dnl # Default= french
include({trans-}LANG{.m4})dnl	  # call translation file
undefine({format})dnl		  # Suppress the format definition
define({_ANNEE_},esyscmd(date +%Y))dnl 	  #Current year
define({LYNX_TITRE},{define(_TITLE_,$1)})dnl # First macro
dnl # Second macro
define({LYNX_ENTETE},{<!-- Header start -->
<HTML>
<HEAD>
<TITLE>$1</TITLE>
<META name="description" content="Site lynx and m4"> 
<META name="keywords" content="m4, lynx, GPL">
</HEAD>
<BODY BGCOLOR="#FFFFFF" LINK="#008000" VLINK="#808080" ALINK="#8080FF">
<TABLE>
  <TBODY>
  <TR><TD align=middle colspan="2">
      <H1>_TITLE_</H1>
  <TR><TD align="left" valign="top" width="15%">
      <a href="./index-en.html">_ANGLAIS_</A><BR>
      <a href="./index-fr.html">_FRANCAIS_</A><BR>
      <a href="./index-es.html">_ESPAGNOL_</A><BR>
      <a href="./index-it.html">_ITALIEN_</A><BR>
      <a href="./index-de.html">_ALLEMAND_</A><BR>
      <TD align=left>
<!-- end of header -->})dnl
dnl # Third macro
define({LYNX_PIED},{<!-- Start of footer -->
</TBODY>
</TABLE>
<HR size="0" noshadow>
<FONT SIZE=-2>
<EM>_MAINTENEUR_.<BR>
_MAJ_
esyscmd(date +%d/%m/%y)
- &copy <A HREF="mailto:[email protected]">
lynx.browser.org</A>
_ANNEE_</EM></FONT>
</BODY>
</HTML>
<!-- End of footer -->})dnl

Toelichting

De regels tussen divert(-1) en divert(0) is commentaar. divert is één van de ingebouwde macro's van de m4 processor. Het is bedoeld om de uitvoer om te leiden. De waarde -1 vertelt de processor de daaropvolgende tekst niet in het HTML bestand te zetten, wat precies is wat we willen.

De macro changequote herdefinieert het aanhalingsteken wat normaal in gebruik is voor het groeperen van macro argumenten. Hij wordt vervangen door accolades omdat in teksten, en dan vooral in franse teksten, aanhalingstekens veel worden gebruikt. Dit zou een foute interpretatie van macro's kunnen veroorzaken. Accolades worden niet zo vaak gebruikt voor tekst of HTML, vandaar deze herdefinitie.

De macro ifdef wordt gebruikt om te testen of de LANG macro is gedefinieerd. Zo niet, dan wordt het standaard "fr". LANG wordt gebruikt om de taal in te stellen. We zullen in het voorbeeld hieronder laten zien hoe de taal te definiëren van een HTML-pagina met gebruikmaking van m4.

De regel met include heeft dezelfde betekenis als in C en wordt gebruikt om een ander bestand in te lezen. Het wordt hier gebruikt om taal-afhankelijke macro's, gebruikt in de kop- en voet regels, in te laden. Hier de inhoud, afhankelijk van de taal:

  
divert(-1)
# File trans-fr.m4
# Definitions for french
divert(0)
define({_ANGLAIS_},{Anglais})dnl
define({_FRANCAIS_},{Francais})dnl
define({_ITALIEN_},{Espagnol})dnl
define({_ESPAGNOL_},{Italien})dnl
define({_ALLEMAND_},{Allemand})dnl
define({_WEBMASTER_},{John Perr})dnl
define({_MAINTENEUR_},{Page maintenue par _WEBMASTER_})dnl 
define({_MAJ_},{Date de mise à jour:})dnl
  
divert(-1)
# File trans-en.m4
# Definitions for english
divert(0)
define({_ANGLAIS_},{English})dnl
define({_FRANCAIS_},{French})dnl
define({_ITALIEN_},{Spanish})dnl
define({_ESPAGNOL_},{Italian})dnl
define({_ALLEMAND_},{German})dnl
define({_WEBMASTER_},{John Perr})dnl
define({_MAINTENEUR_},{Page maintained by _WEBMASTER_})dnl
define({_MAJ_},{Page updated on })dnl

Als je het Spaans, Italiaans of Duits machtig bent, dan zou je analoge bestanden aan kunnen maken voor deze talen.

De regel met undefine doet de standaard definitie van de ingebouwde format macro teniet omdat deze hier niet wordt gebruikt. Bij het weglaten van deze regel zou, iedere keer dat het woord format in de tekst voorkomt, het woord vervallen, behalve als het tussen aanhalingstekens staat (accolades in dit geval). Dit is niet aan te raden bij het veranderen van eenvoudige web-pagina's.

Daarna wordt het huidige jaar gedefinieerd. Deze wordt verkregen middels de macro easycmd, die het Unix commando date aanroept. Het commando wordt ook gebruikt in de voet regels om de datum te kunnen laten zien waarop de pagina het laatst is veranderd.

De volgende regels definiëren de eerste van onze drie macro's: LYNX_TITRE. Deze definieert een ander macro, _TITRE_ genaamd. Deze tweede definitie is nodig om de titel meerdere malen in de kop- en voet regels te kunnen verwerken vanuit één definitie. Let op het gebruik van $1 om te refereren aan het eerste argument van de macro.

De rest van de regels definiëren de andere twee macro's: LYNX_ENTETE en LYNX_PIED die de inhoud van de kop- en voetregels van onze HTML-pagina bevatten, met uitzondering van de variabele inhoud van die regels. Dat zijn:

Het dnl aan het eind van de regel is een ingebouwde macro van m4 die het volgende aangeeft: verwijder alles tot aan het einde van de regel. dnl voorkomt het genereren van een lege regel bij het uitvoeren van een macro.

Pagina's maken

Nu het systeem gereed is, wordt het genereren van de web-pagina met het volgende commando opgestart:

XX is daarbij de code die wordt gebruikt voor iedere taal. Merk op dat de optie -D wordt gebruikt die, net als bij gcc, een macro definieert vanaf de commando-regel.

Samenvatting

In de volgende tabel worden de bestanden genoemd met hun toepassing.

De volgende bestanden worden gebruikt voor het genereren van HTML pagina's:
index-XX.html De inhoud van de pagina. Dat is tekst, geschreven door de auteur of de vertaler. Dit verschilt per pagina en per taal (de code is XX=en voor Engels, es voor Spaans, etc...).
mac.css Standaard definities. Dit bestand zit in alle pagina's en talen. Het is een soort stijl-pagina.
trans-XX.m4 Standaard definities voor een taal. Dit bestand wordt gebruikt door alle pagina's van één bepaalde taal (de code XX=en voor Engels, es voor Spaans, etc...).

Afronding

Ondanks de kracht van m4, kan het niet worden vergeleken met scripting-talen als Perl of Tcl. Als men het eenmaal door heeft, is het een snel en handig hulpmiddel voor het bewerken van tekstbestanden. Raadpleeg de documentatie die bij de distributie zit om meer te weten te komen. Er moet een dictaat in zitten van ongeveer 30 pagina's die alle aspecten van de GNU/m4 processor behandelt. Je kan ook kijken op de site Linux User Group of Bordeaux (ABUL) die wordt onderhouden met een pakket m4 macro's, zoals hier gepresenteerd.

Links

GNU/m4 is verkrijgbaar bij ftp://prep.ai.mit.edu/pub/gnu/m4-1.4.tar.gz
Ophalen van files die hier worden genoemd: The Lynx m4 macro kit

Met dank aan Paul Kienzle voor het nakijken van dit artikel.