Prehtml, version 2.8
Télécharger l'ensemble du projet
(sources, exécutable pour linux, et mini-documentation). Ce
lien fonctionne sur mon site, mais pas forcément si cette page est
recopiée ailleurs! Si ça ne marche pas, essayez http://mjulier.free.fr/prehtml/prehtml-current.tar.gz
(format .tar.gz, à décoder en lançant "tar -zxf prehtml.tar.gz", un
répertoire nommé prehtml sera créé, contenant le code source et
l'exécutable qui s'appelle simplement "prehtml").
Mais avant d'utiliser ce programme, jetez un coup d'oeil rapide
aux questions légales.
Paramètres en ligne de commande
Le programme se lance de la façon suivante:
prehtml [options] <fichier1.prehtml> [<fichier2.prehtml> ...]
Principe général:
Pour chaque fichier "nom.prehtml" en entrée, un fichier
"nom.html" est créé par le logiciel (sauf commandes spéciales).
De même, pour un fichier "nom.prehtm" en entrée, un fichier
"nom.htm" est créé.
Code de retour
Standard: retour non nul si le programme a rencontré une
erreur.
Options (qui peuvent être combinées)
-d : debug
Option présente depuis le départ, mais elle est rarement
commode.
Le fichier généré est envoyé dans la sortie standard (stdout) en
même temps que dans le fichier de destination.
L'intérêt est, parfois, de comprendre à quel endroit une erreur se
produit.
-s : structure
Depuis v1.9: affiche le détail des fichiers dans lesquels on
rentre ou on sort.
Utile pour déboguer les pages utilisant beaucoup de fichiers
inclus.
-S : Shell
Depuis v1.9: affiche les commandes Shell lancées.
Le Shell Unix est à la base du logiciel prehtml,
normalement c'est invisible, mais avec cette option on voit les
commandes lancées et on peut parfois comprendre pourquoi une
commande a échoué ou n'a pas donné le résultat attendu.
-b <bash,...> : Bash, appelle un shell autre que "sh"
Depuis v2.5, permet de choisir le shell utilisé, par
exemple "bash" au lieu de "sh" qui est lancé par défaut, pour
disposer d'une syntaxe plus pratique. Les formats "-bbash"
ou "-b bash" sont acceptés tous les deux.
-8 : caractères 8 bits (supposés être iso-8859-1 plus le caractères "€")
-u : caractères 8 bits (supposés être Unicode UTF-8)
Depuis v2.4, permet une plus grande souplesse dans
l'utilisant des jeux de caractères.
Par défaut (aucun paramètre), prehtml décode en entrée
les codes HTML en caractères iso-8859-1 (occidental), par exemple
le texte "é" est transformé dans le caractère 0xE9 ("é"
dans le jeu iso-8859-1). Par exception, le caractère "€" est
décodé selon son numéro dans le jeu iso-8859-15.
En sortie, les caractères sont recodés en HTML, donc tel que
"é" dans notre exemple.
(sauf pour les codes de type URL, qui sont codés différemment,
tels que "%E9").
Ceci pose un problème lorsque le texte d'entrée contient des
caractères codés en 8 bits dans un autre jeu de caractères que
iso-8859-1.
Avec l'option "-8", les caractères 8 bits sont laissés en l'état:
ainsi, si le texte d'entrée contient des caractères 8 bits dans
n'importe quel jeu de caractères, ceux-ci sont maintenus dans la
sortie. Si cependant le texte d'entrée contient des codes HTML
comme "é", ceux-ci continuent à être décodés selon le
jeu iso-8859-1. C'est donc une option utile si on utilise des
caractères 8 bits.
Avec l'option "-u", le fonctionnement est le même, sauf que les
codes HTML sont décodés dans le jeu de caractères Unicode UTF-8,
qui est devenu le plus courant sur le web car il permet d'afficher
facilement toutes les langues du monde. C'est donc l'option à
utiliser si on utilise le codage Unicode UTF-8.
Si les fichiers d'entrées ne contiennent pas de caractères codés
en HTML tels que "é", les deux options "-8" et "-u"
sont identiques.
Bien sûr, les codes HTML correspondant à des caractères 7 bits
continuent à être décodés, à savoir "<", ">",
"&", " " et """ (correspondant à "<",
">", "&", espace insécable, et double guillemets). Sans
cela, le logiciel ne fonctionnerait pas.
-f : force l'écriture
Depuis v2.6, écrit le fichier en sortie même s'il est identique
à celui qui existe déjà (peut être utile pour les Makefile)
-h, --help : aide
Depuis v1.9, cette commande affiche la liste des paramètres en
ligne de commande.
Recompilation
Aller dans le répertoire contenant les fichiers source, et taper
"make". L'exécutable est créé avec les informations de débogage:
pour les supprimer tapez "strip prehtml".
Il faut avoir "make", j'ai utilisé GNU make, mais je pense que ça
marche avec n'importe quel make Unix.
Il faut aussi avoir un compilateur C. Par défaut, j'ai mis "gcc",
pour en utiliser un autre il faut modifier la ligne "CC=gcc" du
fichier Makefile.
Si vous compilez ce programme sur un système non-Unix, je ne sais
pas ce que ça peut donner, ni même si ça peut marcher. Testé sur
Linux/i386.
Origine du projet
Des difficultés pour maintenir une liste de dépêches d'information
sur un site consacré au vélo comme moyen de transport dans la région
de Montpellier.
Initialement, chaque fois que je rajoutais une information, il
fallait que je modifie une page "actualites.html", en écrivant le
texte de la nouvelle information. Puis je rajoutais une cible
<A NAME="pistes_etroites"> sur l'article, puis je recopiais
le titre en haut de la page d'actualités avec un lien vers cette
info <A HREF="#pistes_etroites"> pour retrouver facilement
les dernières infos, et enfin je rajoutais cette info sur la page
d'accueil "index.html" pour signaler la nouveauté <A
HREF="actualites.html#pistes_etroites">. C'était beaucoup de
travail à chaque fois, sans compter le travail d'archivage des
informations un peu périmées.
Ensuite, j'ai été remplacé par un jeune génie des maths et de
l'informatique, qui a automatisé tout le processus avec des
scripts Perl et shell dans tous les sens, et quelques utilitaires
Unix. Brillant, il faut le dire, mais incompréhensible: j'aime
bien le Perl, mais à chaque fois que je m'y remets 3 mois après la
dernière fois, j'ai oublié toute la syntaxe. Et le système rendait
impossible ou presque l'utilisation d'éditeurs HTML un peu évolués
comme Netscape/Mozilla et équivalents.
J'ai donc décidé de faire mon propre système, en me basant sur le
langage qui me paraissait le plus simple et le plus connu: le
Bourne-Shell, c'est-à-dire le langage de la console d'Unix.
Pourquoi ne pas utiliser plutôt PHP? Bon, déjà, ce n'est pas
l'usage classique de PHP, que la plupart des gens font tourner sur
le serveur; cela dit, rien n'empêcherait de préparer d'abord les
pages avec PHP sur sa propre machine, avant de les mettre sur le
serveur. Le principal avantage de mon programme par rapport à PHP
est celui-ci: je peux éditer mes pages dans un éditeur Wysiwyg
(j'utilise Mozilla Composer), et quand je tape "<echo
$lien>", mon programme arrive à faire ce qu'il faut même si
c'est devenu "<echo $lien>" (codage HTML), ou bien
"%3Cecho%$20lien%3E" (codage utilisé dans les liens eux-mêmes).
Alors qu'avec PHP, il faut inclure les commandes dans des balises
<?php ...>, chose en pratique impossible à faire facilement.
Regardez mes exemples, en bas de cette page, pour comprendre ce
qu'on peut faire facilement avec mon système.
Si vous connaissez le shell, prehtml vous paraîtra
évident. Sinon, vous avez le choix: soit apprendre le shell, soit
vous passer de prehtml et trouver une autre solution à vos
problèmes. Pour l'instant, je suis à ma connaissance le seul et
unique utilisateur de ce programme.
Prehtml est écrit en C standard. Le C++ serait plus adapté mais
j'aurais passé plus de temps à m'y remettre qu'à tout faire en C
(le langage utilisé dans les microcontrôleurs...). On m'a fait
remarqué qu'il aurait été plus simple d'utiliser des analyseurs
syntaxiques tout faits: c'est juste, mais je ne connais pas du
tout ces choses-là. Et que Perl sait faire tout cela ou presque:
c'est exact, mais comme je l'ai signalé, ma mémoire n'arrive pas à
retenir la syntaxe du Perl: à force de vouloir englobler toutes
les syntaxes existantes dans le monde de la programmation, je
trouve que ça perd un peu sa logique. Et je trouve le Perl très
difficile à déboguer (peut-être par manque d'habitude).
Syntaxe
Les fonctions sont écrites sous une forme qui ressemble à des
balises HTML. Par exemple <SHELL titre="Le vélo">. Bien sûr,
ce sont des balises inconnues du HTML! Mais la différence est que si
l'on utilise un éditeur HTML, cette balise risque fort de devenir
ceci "<SHELL titre="Le
vélo">" (c'est ce que fournissait Netscape
Composer). Mais ce n'est pas grave, prehtml est prévu pour décoder
ce charabia et exécuter la commande tout aussi bien. Cela dit, si la
commande est tapée à la main, donc réellement sous la forme
<SHELL titre="Le vélo">, ça marche également. Note: depuis v2.8, le même
codage doit être utilisé pour l'ouverture et la fermeture de la
balise: <BALISE> (non codé), ou <BALISE> (codage
HTML), ou "%3CBALISE%3E" (code URL), le caractère ">" n'est plus
accepté pour fermer une balise ouverte avec un codage, afin d'éviter
une fermeture intempestive par une balise HTML contenue à
l'intérieur.
Les commandes prehtml fonctionnent en minuscules ou en
majuscules. Mais attention car le shell, lui, fait la différence!
"ls" donne la liste des fichiers, mais pas "LS", et si vous
définissez "$titre", alors "$Titre" n'est pas défini.
On lance le programme en tapant "prehtml
<liste_de_fichiers.prehtml>". Pour chaque fichier .prehtml,
un fichier .html est créé (sauf cas spécial mentionné plus bas).
Si le fichier source s'appelle .phtm, le fichier créé s'appelle
.htm. Si on donne plusieurs fichiers, le programme fonctionne
comme si on le lançait successivement avec chaque fichier. Si le
fichier qui doit être créé existe déjà et est exactement identique
à celui qui devrait être créé, il n'est pas modifié (sa date n'est
pas affectée, ce qui est utile pour des programmes automatiques
comme Makefile ou sitecopy, utilisables pour créer ou pour
télécharger le site).
Trêve de baratin, voici la liste des commandes, leur syntaxe, et
des exemples:
Index des commandes
- <SHELL commande_shell>:
exécute une commande shell
- <ECHO texte>: écrit quelque
chose dans le fichier
- <SHELLECHO commande_shell>:
comme <SHELL>, sauf que le résultat est écrit dans le
fichier créé.
- <ECHONOESC>: comme
<ECHO>, sauf que la sortie n'est pas recodée en HTML.
- <SHELLECHONOESC>:
comme <SHELLECHO>, sauf que la sortie n'est pas recodée en
HTML.
- <INCLUDE fichier(s)>:
inclut un ou des fichiers dans le fichier principal.
- <NOTINCLUDE fichiers>:
comme <INCLUDE>, sauf que les fichiers inclus et traités
ne sont pas retransmis dans la sortie.
- <REINCLUDE fichiers>:
comme <INCLUDE>, sauf que le fichier en cours de création
est repris à son commencement.
- <IF condition>... [<ELIF
condition2,...>...][<ELSE>...] <FI>:
permet de faire des conditions.
- <FOR variable IN liste>......
<DONE>: fait une boucle sur une liste, comme
en shell.
- <WHILE condition>....<DONE>:
fait une boucle sur une condition, comme en shell.
- <GENERATE
nom_de_fichier>.....</GENERATE>: commande
pour créer une série de fichiers.
- <CHUT>... </CHUT>:
supprime momentanément la sortie dans un fichier.
- <ERROR message> et <WARNING
message>: provoque une erreur ou un
avertissement.
- <TAG message>: crée une
balise HTML quelconque.
- <REM message>: ne fait rien du
tout (remarque = commentaire court).
- <RAW autre_mot_clé
paramètres>: indique que les caractères
"<", ">", "&" sont utilisés tels quels sans être
échappés
- Variable $file : nom du fichier
source principal.
- Variable $thisfile : nom du
fichier source en cours de traitement (éventuellement inclus).
- Variable $dest :
nom du fichier destinataire (en ignorant les commandes
<GENERATE>).
- Changements de répertoire.
Détail des commandes
- <SHELL commande_shell>:
Permet d'exécuter une commande shell discrètement,
c'est-à-dire sans sortie dans le fichier .html créé. Exemples:
- <SHELL titre="Des pistes cyclables sur le trottoir">:
permet de définir une variable pour la suite
- <SHELL numero_info=`expr $numero_info + 1`>: permet
d'incrémenter une variable.
- <SHELL ls infos/*.html | tee liste.txt>: crée un
fichier utilisable par la suite. Cet exemple sert surtout à
signaler une limitation: il est impossible de mettre le
caractère ">" dans une commande prehtml, car il signale la
fin d'une commande. Il n'y a pas de code d'échappement,
peut-être serait-ce utile? Mais pour une simple redirection
vers un fichier, le programme "tee" fonctionne très bien.
- <ECHO texte>: permet
d'écrire ce qu'on veut dans le fichier créé, comme la commande
"echo" du shell:
- Info n°<ECHO $numero_info>: <ECHO
$titre>. Notez que le fait de créer un lien n'empêche
pas la fonction de marcher, mais il faut faire attention à ce
que le lien englobe bien toute la commande, du "<" au
">".
- <shell ref="sans_bagnoles">: ceci définit une
variable
Cliquez ici pour lire l'info :
l'adresse indiquée pour ce lien est <echo #$ref>, ce qui
sera remplacé par #sans_bagnoles
La journée du 22 septembre a été
une réussite...: juste au début de cette ligne se trouve une
cible (champ <A NAME>), dont le nom est <ECHO
#$ref>: le nom deviendra "#sans_bagnoles" après passage par
prehtml.
- Notez que l'on peut parfois inclure des balises
HTML dans des commandes prehtml, mais avec précautions: les
caractères < et > sont codés spécialement, et ce codage
est décodé à la sortie. Exemple:
<shell titre="C'est très joli">: la variable
$titre va prendre la valeur "C'est _lt_B_gt_très_lt_/B_gt_
joli"
<echo $titre>: le shell va fournir la valeur de la
variable $titre, mais prehtml va décoder cela et fournir la
chaîne suivante: "C'est <B>très</B>
joli", ce qui s'affichera bien "C'est très joli" dans
le navigateur.
Il est évident qu'un tel système n'est pas toujours pertinent.
L'exemple cité est sans doute le seul qui a un intérêt pratique.
Si la commande contient vraiment "_lt_", le premier "_"
deviendra "_und_". À la fin, le texte "_und_lt_" redeviendra
donc "_lt_", l'honneur est sauf.
- <SHELLECHO commande_shell>:
comme <SHELL>, sauf que le résultat est écrit dans le
fichier créé. Si la commande donne plusieurs lignes, des sauts
de lignes sont insérés entre chaque ligne (NB: globalement le
HTML n'est pas sensible aux sauts de ligne), mais ni au début,
ni à la fin. Il serait peut-être plus rusé d'insérer des
<P> entre chaque ligne, mais j'attends vos suggestions
pour savoir ce qui est le mieux
- Dernière mise à jour le <SHELLECHO date "+%A %e %B
%Y à %Hh%M">. Notez que:
- je peux mettre toute la commande en gras pour faire
ressortir le résultat, ou bien plus que la commande, mais
pas une fraction de la commande (sous peine d'erreurs
imprévisibles)
- le "à" inclus dans la commande (éventuellement sous la
forme à qui est décodée avant d'être envoyée au
shell) est recodé au format HTML (à)avant d'être
écrit dans le fichier de sortie. C'est également le
comportement de <ECHO>
- Et pour finir philosophons sur ceci: <SHELLECHO
fortune>.
- <ECHONOESC>: comme
<ECHO>, sauf que la sortie n'est pas recodée en HTML: ce
n'est sans doute pas très utile, mais sait-on jamais. "NOESC"
signifie ici "no escape", pas d'échappement des caractères
spéciaux pour le HTML.
- <shell nom="El Señor Julier">
<meta name="Author" content="<ECHONOESC $nom>">
- <SHELLECHONOESC>:
comme <SHELLECHO>, sauf que la sortie n'est pas recodée en
HTML. Utile si vous faîtes marcher une commande qui produit
réellement du HTML. Un exemple relativement simple:
- Voici la liste des fichiers HTML:
<SHELLECHONOESC ls *.html | awk $'{print $0"\074P\076"}'>:
remarquez l'échappement $'....' (compris par le shell) qui
petmet de transformer \074 en < et \076 en >. La commande
envoyée à awk est donc '{print $0"<P>"}', ce qui lui dit
d'écrire chaque ligne de l'entrée avec <P> à la fin.
L'ensemble permet de sortir la liste des fichiers avec un
passage de ligne au format HTML entre chaque.
- <INCLUDE fichiers>:
inclut un ou des fichiers dans le fichier principal.
Remarque 1: quand je dis inclure, je veux dire que les
fichiers inclus seront traités comme s'ils étaient dans le fichier
source. Les fonctions prehtml des fichiers inclus sont exécutées.
Remarque 2: on peut inclure plusieurs fichiers avec une
seule commande, c'est la syntaxe de la commande "cat"
Remarque 3: cette commande (comme presque toutes les
commandes de prehtml) est récursive: les sous-fichiers peuvent en
inclure à leur tour... Ils peuvent même s'inclure eux-mêmes, mais
ça ne doit pas boucler indéfiniment!
Remarque 4: si on inclut un fichier créé avec un éditeur
HTML, celui-ci contiendra certainement des balises telles que
<HTML><HEAD></HEAD><BODY>....</BODY></HTML>.
L'insertion
des
fichiers commence après le champ <BODY> (s'il existe) et se
termine avant </BODY> (s'il existe), ce qui permet de
l'inclure dans un autre fichier HTML sans se poser de
questions.<INCLUDE bandeau_haut.htm>: pratique pour définir
un entête, que l'on peut changer en même temps dans toutes les
pages du site.
- Info n°<echo $numero_info>:
<INCLUDE depeche_${numero_info}.html>: dois-je vraiment
détailler l'utilité de ceci?
- <INCLUDE definitionscommunes/*.htm>: on peut faire ça
si l'on veut.
- <NOTINCLUDE fichiers>:
comme <INCLUDE>, sauf que les fichiers inclus et traités
ne sont pas retransmis dans la sortie. Pourtant, toutes les
opérations sont faites (même les sous-inclusions de fichiers,
etc...). Principale utilité: connaître des variables qui vont
être définies dans un fichier inclus. Exemple:
- <shell fichier=depeche_${annee}_${numero_info}.htm>
<NOTINCLUDE $fichier>
(Le fichier "depeche_2001_1.htm" contient la commande suivante:
<shell titre="Tous à vélo!">)
N°<echo "$numero_info : $titre">
(produit:
"N°1 : Tous à vélo!")
- <REINCLUDE fichiers>:
comme <INCLUDE>, sauf que le fichier en cours de création
est repris à son commencement, et que l'entête du premier
fichier inclus n'est pas supprimé. Si <REINCLUDE> est
rencontré dans une commande <GENERATE>, ça fonctionne
également, mais attention: il faut alors qu'un <REINCLUDE>
soit trouvé pour toutes les fois qu'un fichier a été créé avec
<GENERATE>, sinon certains fichiers créés n'auront plus
d'entête ! Par contre, si <REINCLUDE> est rencontré après
une commande </GENERATE>, cela provoque une erreur.
Par ailleurs, si <REINCLUDE> est rencontré dans un fichier
"non inclu" (avec <NOTINCLUDE>) il est traité comme un
<INCLUDE> normal. L'intérêt est que l'on peut vouloir
exécuter les commandes inclues dans une page, qui vole
elle-même la mise en page d'une autre, mais sans reprendre la dite
mise en page ni perdre le début du fichier en cours de création.
- (je suis dans un fichier qui contient le texte, mais dont
le titre, les mots clés, et les couleurs ne sont pas
définies);
<shell titre="Contactez-nous!">
<REINCLUDE canvas.htm>
Pour nous contacter: tél:.... e-mail:.....
Dans cet exemple, le fichier "canvas.htm" est une page HTML
vide, mais avec des couleurs définies, ainsi que les mots clés
valables pour tout le site, et comme titre la commande "<echo
$titre>". La queue de ce fichier (à partir de </BODY>
n'est pas transmise, ce qui permet d'enchaîner directement sur
le corps du fichier principal. J'ai donc "volé" la présentation
de la page "canvas.htm", tout en y mettant le titre désiré.
Idéal pour fixer la présentation de toutes les pages!
- (exemple avec GENERATE)
<shell fichiers="un.html deux.html trois.html">
<for fich in $fichiers>
<GENERATE $fich>
<shell titre="Le titre de cette page est $fich">
<REINCLUDE canvas.htm>...et voilà, vous lisez présentement
le fichier <echo $fich>!
</GENERATE>
- exemple à plusieurs niveaux (utilisé pour le site http://collectiftramway.free.fr,
mais là j'ai nettement simplifié):
fichiers principaux: une_page.prehtml
(édités avec Netscape Composer) |
<shell titre="Une page"><reinclude
presentation.htm> |
fichier de présentation: presentation.htm
(ce fichier aussi est édité avec Netscape Composer) |
<shell titre_complet="Collectif Tramway - $titre";
feuilledestyle=colltram.css><reinclude
style.htm>
Sommaire:
bla
bla
bla |
<CHUT> |
</CHUT> |
fichier pour appeler les CSS (cascading
style sheets), ce que Netscape Composer version 4.76 ne
gère pas: style.htm
(édité avec un éditeur de texte normal) |
<html><head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta name="GENERATOR"
content="Mozilla/4.76[fr]/Linux +
prehtml/unix_console">
<meta name="AUTHOR" content="Collectif
Tramway">
<meta name="DESCRIPTION" content="bla bla
bla"
<meta name="KEYWORDS" content="bla, blo,
blu">
<META HTTP-EQUIV="Content-Style-Type"
CONTENT="text/css">
<LINK REL="STYLESHEET" HREF="<echo
$feuilledestyle>">
<title><echo
$titrecomplet></title></head>
<body>
|
feuille de style: colltram.css
(avec un éditeur de texte normal) |
/* définition des entêtes */
H1 { display: block;font-size: 1.7em; margin: .67em
auto; font-weight: bolder; }
H2 { display: block; font-size: 1.4em; margin: .83em
auto;
font-weight: bolder; }
/* etc...*/ |
- <IF condition>... [<ELIF
condition2,...>...][<ELSE>...] <FI>: permet
de faire des conditions. La syntaxe de l'instruction "if" du
shell, mais sans le point-virgule ";" à la fin. Note: il n'y a
pas de "then". La commande <ELSE> est facultative. Bien
sûr, les <IF> peuvent être imbriqués entre eux, ce qui est
souvent utile. Pour gérer les cas qui s'excluent mutuellement,
la balise <ELIF> est pratique. La condition peut être une
commande normale, l'instruction "test", ou bien une expression
entre crochets [ ] (ne pas oublier les espaces obligatoires), ce
qui revient au même que "test", je crois.
- <IF [ $file = index.prehtml ]>ACCUEIL<ELSE>Accueil<FI>
pratique pour faire des bandeaux qui
s'adaptent à chaque page.
- <IF [ $x = debut ]>LISTE
= [[[<ELIF [ $x = premier ]><echo "$txt"><ELIF
[ $x = suite ]><echo
", $txt"><ELIF [ $f = fin ]>]]]<ELSE><ERROR
"valeur x=$x inattendue!"><FI>
Le code <ELIF> permet de gérer les
cas multiples sans avoir à imbriquer les
<IF>...<FI>. Le <ELSE> reste optionnel.
- <FOR variable IN liste>......
<DONE>: comme en shell: la variable designée par
valoir successivement chaque mot de la liste. Ce qui est entre
<FOR> et <DONE> va être lu autant de fois qu'il y a
de mots dans la liste. C'est une instruction indispensables pour
faire des pages un peu dynamiques, car elle permet de faire des
boucles. On peut imbriquer les <FOR>, mais le <DONE>
doit être dans le même fichier que le <FOR> (le contraire
sera d'ailleurs très bizarre).
- <FOR fichier IN depeches/depeche*.htm>
<notinclude $fichier>
- <echo $titre>
<DONE>: ceci permet de générer une liste de titres toute
simple
- <FOR fichier IN $liste_de_fichiers>
<include $fichier><DONE>: ceci
permet de lister joliment le contenu de plusieurs fichiers.
- <WHILE
condition>....<DONE>: exécute la partie entre
<WHILE> et <DONE> tant que la condition est vraie
(et donc aucune fois si la condition est fausse dès le départ.
Je suppose qu'il y a des cas où c'est plus utile que
<FOR>. On peut également imbriquer les <WHILE> entre
eux (ou bien avec les <FOR>).
- <shell nb=1>
<WHILE [ -f depeche_${nb}.htm ]> (fait la boucle tant
qu'il existe un fichier du nom demandé)
<include depeche_${nb}.htm>
<shell nb=`expr $nb + 1`>
<DONE>
- <GENERATE
nom_de_fichier>.....</GENERATE>: commande
spéciale qui demande à prehtml de ne pas créer le fichier
normalement prévu, mais celui qui est indiqué dans la commande.
La seule utilisation intéressante est à l'intérieur d'une boucle
<FOR> ou <WHILE>, auquel cas les instructions
<GENERATE> et </GENERATE> sont rencontrées plusieurs
fois avec un nom différent à chaque fois.
Un fichier est créé pour chaque nom (le même nom ne peut venir
qu'une seule fois). Le début et la fin du fichier sont communs à
tous les fichiers créés, et correspondent respectivement à la
partie avant <GENERATE> et à la partie après
</GENERATE>. Par contre, la partie variable correspond à la
partie qui se trouve entre ces deux commandes.
Remarque 1: après un </GENERATE> et avant un
<GENERATE> suivant, il ne doit y avoir que des caractères
"blancs" (espaces, tabulations, sauts de ligne "\n"), car
autrement le programme ne saurait pas où envoyer ces caractères.
Attention, les caractères blancs, ça ne comprends pas les
<BR> ou les <P> et </P> que peut inclure un
éditeur HTML si on tape sur ENTRÉE.
Remarque 2: contrairement aux autres instructions, il n'est
pas possible d'imbriquer les <GENERATE>.
Exemple:
- <for annee in 19?? 20??>
<GENERATE archives_${annee}.html>Archives de l'année
<echo $annee>
<for depeche in ${annee}/depeche*.htm>
<include $depeche>
<done>
</GENERATE>
<done>
- <CHUT>... </CHUT>:
supprime momentanément la sortie dans un fichier. On peut
remarquer que <NOTINCLUDE> est à peu près équivalent à
<CHUT><INCLUDE></CHUT>. On peut imbriquer les
<CHUT>.
Cette balise peut servir à mettre des commentaires, mais sa
véritable utilité est due aux éditeurs HTML. Si l'on veut qu'une
boucle génère un tableau ou une liste, par exemple, il faut
d'abord générer le début du tableau (ou de la liste), puis chaque
ligne, puis la fin. Or un éditeur HTML type "Wysiwyg" ne permet
pas de faire un début de tableau sans mettre aussi la fin. La
façon la plus simple de contourner le problème est de mettre
<CHUT> à l'endroit qui est inutile. Attention car si on ne
fait pas attention, on peut générer du HTML incorrect (NB: il
existe des programmes pour vérifier la qualité du HTML: par
exemple "weblint", programme gratuit, au moins sur Linux). Exemple
d'utilisation pour un tableau:
- On génère d'abord le début du tableau (on s'arrête juste à
la fin de la dernière cellule de la 1ère ligne)
Titre d'une colonne |
Titre de l'autre colonne<CHUT> |
- Pour chaque élément, on reprend à la fin d'une ligne, et on
génère la ligne suivante, puis on s'arrête juste à la fin
<FOR variable IN liste>
|
</CHUT> |
dans une ligne: une cellule |
et une autre cellule<CHUT> |
<DONE>
- Puis on termine la dernière ligne et le tableau lui-même
- Bref, on a créé un tableau sans même savoir quel est le nom
des balises HTML pour cela! Il est cependant utile de
connaître un peu le HTML. Par exemple pour les couleurs: on
peut définir la couleur du tableau (juste au début), la
couleur de chaque ligne, et la couleur de chaque cellule. Par
exemple, dans l'exemple indiqué, le début est indiqué avec le
"fond du tableau" jaune, donc tout le tableau apparaîtra en
jaune, sauf la première ligne, dont le "fond de ligne" est en
bleu clair: la première ligne apparaîtra en bleu clair, car la
couleur de ligne est prioritaire sur la couleur de fond.
- <ERROR message> et <WARNING
message>: provoque une erreur ou un avertissement
volontaire, avec le même format que la commande <ECHO>
(l'erreur stoppe prehtml, tandis que l'avertissement n'empêche
pas le programme de continuer son fonctionnement):
<CHUT>ceci vérifie que la nouvelle fraîche n'est pas
périmée:
<shell info_peremption=20011104> (date de péremption au
format "AAAAMMJJ")
<if [ `date +%Y%m%d` -gt "$info_peremption" ]>
alors on provoque une
erreur
<ERROR "Retirez
l'information, elle est périmée:
\$info_peremption=$info_peremption">
<fi>
Là, mon vieux, tu vas être obligé de mettre ton site à jour pour
recompiler cette page!!!
(avec WARNING, ce serait moins exigeant...)
</CHUT>
- <TAG message>: crée une
balise HTML, avec le même format que la commande <ECHO>
<TAG div class=\"$style_courant\">
- exemple 1: inclure une partie dans des balises <NAV
id="id_nav">...</NAV>
<TAG NAV 'id="id_nav"'>...<TAG /NAV>
- exemple 2: ajouter un commentaire HTML <!-- Commentaire
HTML -->
<TAG !-- Commentaire HTML -->
- <REM message>: ne fait rien du
tout. Ça permet d'insérer un commentaire court:
- <shell titre="Le titre de la page"><REM ne pas
oublier de définir le titre ici>
Pour les commentaires plus longs, les balises
<CHUT>...</CHUT> sont plus pratiques:
<CHUT>
Explications: indiquez le titre dans la ligne suivante,
vous pouvez changer le style de caractères du titre si
nécessaire,
mais il faut le faire uniquement à l'intérieur des guillemets,
"ainsi"
</CHUT>
<shell titre="Le titre de cette page">
- <RAW
autre_mot_clé paramètres>: indique que les
caractères "<", ">", "&" sont utilisés tels quels sans
être échappés en "_lt_", "_gt_", "_und_"
- exemple: <RAW SHELL read -a valeurs
<<<"$chaine">
sans cela, le code "<<<" (here string) n'est pas
envoyé au shell
- note: cet échappement n'est pas strictement obligatoire si
les chaînes sont entre guillemets ou apostrophes, mais il
évite certaines erreurs car ces 3 caractères ont des
significations spéciales dans le shell Unix
- variable $file : cette variable est
définie automatiquement, et est égale au nom du fichier
principal que l'on traite (bref, un fichier ".prehtml"). La
variable $file ne prend donc pas le nom des fichiers inclus.
- variable $thisfile : cette
variable prend le nom du fichier dans lequel elle est définie.
Ceci n'a probablement aucun intérêt.
- variable $dest : cette variable
prend le nom du fichier qui est en train d'être créé (donc un
fichier .html). Notez que si on utilise les balises
<GENERATE>, la variable $dest reste égale à la valeur
qu'elle avait avant la balise <GENERATE>. L'application la
plus évidente est la création de bandeaux qui s'adaptent selon
la page:
- <include bandeau.htm>
avec un fichier "bandeau.htm" contenant ceci:
<if [ $dest = index.html ]>Accueil<else>Accueil<fi> |
<if [ $dest = page.html ]>Page<else>Page<fi> |
- Comportement concernant les
changements de répertoire:
- le répertoire courant est celui à partir duquel on a lancé
prehtml. Il est utilisé pour lire et écrire les
fichiers, et pour l'exécution des commandes shell
- on peut donner un chemin relatif (prehtml
depeches/*.prehtml) ou absolu (prehtml ~/site/*.prehtml). Pour
déterminer le nom des fichiers créés à partir des .prehtml, le
programme retire juste le "p": les fichiers HTML sont donc
créés dans le même répertoire que les fichiers sources, même
si ce n'est pas le répertoire courant.
- attention cependant: un commande telle que <INCLUDE
bandeau.htm> ira chercher le fichier dans le répertoire
courant, pas nécessairement dans le répertoire où se trouve le
fichier source. De même, une commande telle que <FOR
fichier IN depeche*.htm> utilisera tous les fichiers
"depeche*.html" se trouvant dans le répertoire courant.
Bugs et limitations
- bug: les espaces insécables posent un problème. Ils
sont transformés en espaces normaux dans les commandes pour
éviter des erreurs difficiles à dépister, mais du coup ils ne
traversent pas la chaîne de traitement.
- limitation: la gestion des jeux de caractères est
partielle, ça fonctionne en iso-8859-1 (plus le caractère "€"
issu du iso-8859-15), ou bien les caractères 8 bits (n'importe
quel jeu de caractères dont Unicode UTF-8).
Il peut donc y avoir des problèmes dans d'autres cas, par
exemple s'il y a plusieurs jeux de caractères utilisés ou si le
code HTML contient des caractères d'échappement (genre
"é") autres que ceux utilisés pour les caractères
iso-8859-1.
Globalement, le problème sera généralement bien résolu, soit en
utilisant uniquement les caractères iso-8859-1 (Europe
occidentale), soit en utilisant uniquement les caractères UTF-8
(Unicode) et en lançant prehtml avec l'option "-u".
- limitation: Le shell est potentiellement dangereux,
comme tout langage complet: ne traitez pas un fichier .prehtml
d'origine inconnue, si jamais il contenait <SHELL rm -R
\>, vous pourriez effacer tout le disque.
- limitation: Le shell se bloque facilement, par
exemple avec <echo "salut>, à cause du guillemet non
refermé. S'il manque un guillemet ou autre, la commande ne
démarre pas, et le programme s'arrête après 3 secondes. Si la
commande dure plus de 30 secondes, le programme le signale et
indique à quel endroit c'est arrivé, mais continue le traitement
sans erreur.
- limitation: On ne peut pas mettre ">" dans une
commande prehtml puisque c'est le signal de fin de commande.
Pour contourner, il y a "tee" pour les redirections, ou bien les
codes d'échappement du shell en $'\074....\076'
- limitation: Si on veut réellement écrire une commande
prehtml dans le fichier HTML, il est difficile de faire en sorte
qu'elle ne soit pas décodée par prehtml. Mieux vaut écrire la
page directement en HTML (comme celle-ci par exemple), ou bien
inclure directement une page HTML (par exemple avec
<SHELLECHONOESC cat un_fichier.html>). Si vous voulez
réellement taper une commande, vous pouvez toujours inclure
quelque chose qui va empêcher prehtml de repérer la commande:
par exemple <<ECHO>WHILE> donne <WHILE>,
puisque <ECHO> tout seul ne donne aucune sortie.
- limitation: C'est pour les amateurs de shell, mais à
tout prendre, il est plus utile d'apprendre le shell que
d'apprendre un langage que l'on ne retrouvera jamais.
- limitation: Serait-il utile d'avoir une version de
<SHELLECHO> qui inclue des <P> à la fin de chaque
ligne? Ça n'a rien de difficile.
- limitation: Les caractères accentués non terminés par
";" ne sont pas décodés (exemple: é au lieu de
é), je crois que ceci est une entorse à la norme
HTML, mais les éditeurs HTML incluent toujours le point-virgule.
Trucs et astuces
Pour m'en sortir entre les extensions, j'utile ces conventions:
- .prehtml: fichiers qui doivent être traités par prehtml
- .html: fichiers écrits directement sous la forme définitive,
et fichiers générés par prehtml
- .htm: fichiers inclus par prehtml
Pour lancer prehtml, il y a au moins deux bonnes méthodes:
- si tous les fichiers sont dans le même répertoire, et qu'ils
ne sont pas trop gros (question de vitesse), on peut lancer:
prehtml *.prehtml (ce qui traite l'ensemble des fichiers)
- utiliser l'utilitaire "make", avec un fichier nommé
"Makefile" qui contient les lignes suivantes:
faitprehtml.htm : *.prehtml
prehtml $?
touch faitprehtml.htm
Le fichier "faitprehtml.htm", dans cet exemple, sert juste à
sauvegarder la date du dernier traitement par prehtml. Les
fichiers *.prehtml plus récents sont alors traités avec prehtml.
Voici un exemple de Makefile que j'utilise:
# Je définie ici la liste des fichiers à
traiter par prehtml
sources=*.prehtml projet/*.prehtml
actualite/*.prehtml affiches/*.prehtml
# action par défaut
all :
faitprehtml.synchro faitdepeches.synchro index.html
quidonc.html
if grep -r -n /home/julier *.htm *.html *.prehtml; \
then
echo
Lien incorrect!; exit 2; fi
# cette page contient la liste des
associations adhérentes au collectif:
# elle doit être refaite dès que la liste
des associations a bougé,
# même si le fichier "quidonc.prehtml" est
inchangé
quidonc.html: liste/*/asso*.htm
prehtml quidonc.prehtml
# sert à oublier quand a tourner prehtml
pour la dernière fois
oublie :
rm -f faitprehtml.synchro faitdepeches.synchro
# oblige à traiter pour les fichiers
.prehtml
force : oublie all
# La page d'accueil doit être refaite à
chaque fichier modifié,
# car j'ai mis a la date de dernière
modification dessus.
index.html: $(sources) */* */*/*
prehtml index.prehtml
# traitement normal pour toutes les
pages: on lance prehtml uniquement
# sur les fichiers .prehtml qui ont été
modifiés depuis la dernière fois
faitprehtml.synchro: $(sources)
prehtml $?
touch faitprehtml.synchro
# traitement à part pour les pages
d'actualités, qui sont créées à partir
# d'un fichier .prehtml qui crée d'autres
fichiers avec <GENERATE>: je retraite
# toute la liste dès qu'il y a une
nouvelle info (fichiers info*.htm)
faitdepeches.synchro: actualite/info*.htm
prehtml actualite/*.prehtml
touch faitdepeches.synchro
# Ceci ne sert pas à grand-chose
clean : oublie
rm -f *.tmp *~ core a.out
Pour transférer les fichier sur le serveur j'utilise "sitecopy" (un
programme gratuit). Pour ne transférer que les bons fichiers, le
fichier de configuration ~/.sitecopyrc contient les lignes
suivantes:
exclude "*.htm"
exclude "*.prehtml"
exclude "*.tmp"
exclude "Makefile"
Questions légales
Tout le monde a le droit d'utiliser ce programme, de le recompiler
(en enlevant les informations de débogage par exemple...), de
l'adapter à d'autres systèmes d'exploitation, de le modifier pour
son usage ou pour l'usage d'autrui.
Les limitations sont les suivantes:
- Il doit être indiqué quel est l'auteur original (Michel
Julier) et le lien internet où se trouve la version initiale, et
si des modifications ont été apportées par d'autres personnes.
- Il est possible de le vendre (bonne chance!), mais il n'est
pas possible d'interdire aux utilisateurs de le redistribuer
(gratuitement ou non).
- Ce programme doit être fourni avec ses sources complètes et
sa documentation, même s'il a été modifié par quelqu'un d'autre
que moi.
Historique
- 01/01/2025: version 2.8: ajout du préfixe "RAW"
- 08/04/2016: version 2.7: autorisation des fonctions de test
qui ont une sortie dans stdout (ex: <if echo $fichier|grep
2016>)
- 31/01/2015: version 2.6: ajout de l'option "-f" (force
l'écriture même si le fichier de sortie est inchangé)
- 27/12/2014: version 2.5: ajout de l'option "-b" (shell "bash"
ou autre, au lieu du Bourne-shell "sh" lancé par défaut);
correction de bugs.
- 09/10/2014: version 2.4: ajout des options "-8" (caractères 8
bits) et -u (caractères Unicode UTF-8)
- 06/02/2013: version 2.3: ajout des balises <ELIF> ("else
if") et <REM> ("remarque": commentaire)
- 17/11/2012: version 2.2: correction d'un bug bloquant (boucle
infinie) en présence de certains codes d'échappement.
- 11/09/2011: version 2.1: correction d'un bug bloquant
(variable non initialisée), se mettant à poser un problème
(peut-être suite à la mise à jour de la bibliothèque C ou C++)
- 02/12/2009: version 2.0: passage en C++, sans aucune
modification de fonctionnalités
Pour simplifier le code, et éviter les risques de coupures de
lignes trop longues dans les quelques cas où ça n'aurait pas été
prévu, le programme a été passé en C++.
Le style de codage et la majorité des fonctions utilisées reste
du C, mais les listes chaînées ou les tableaux se réallouant à
la volée ont été supprimées. Sont utilisés à la place: le type
"vector" et le type "string" du C++. Aucune allocation explicite
(par malloc() ou new) n'est plus utilisée.
- 10/10/2007: version 1.9: ajout d'options de débogage ("-s",
"-S") et d'une aide ("-h", "--help").
- 13/04/2007: version 1.8: modification d'une commande shell
utilisée en interne (read) pour éviter des blocages
- 14/08/2006: version 1.7: ajout des extensions .prehtml et
.prehtm comme noms valides. Ceci car .phtm et .phtml sont
parfois refusés par certains éditeurs HTML en tant que
correspondant à des programmes en PHP. Les extensions .phtml et
.phtm restent utilisables
- 20/08/2005: version 1.6: amélioration du comportement des
fonctions dont la réponse est longue, de façon à éviter les
passages à la ligne intempestifs tous les 160 caractères.
- 03/10/2004: version 1.5: modification de la communication
entre le process principal et le process du shell Unix qui est
lancé en parallèle. Au lieu des fichiers FIFO nommés (pas très
élégant, et non portable sur une machine non-Unix), ce sont
maintenant les fonctions pipe() et dup2() qui sont utilisées.
- 20/04/2003: version 1.4: traitement spécifique du codage des
caractères dans les liens. Alors que Netscape Composer version 4
laissait gentiment des codes comme <a href="<echo
$lien>">cliquez ici</a>, Netscape Composer versions
6 et 7 ou Mozilla 1.3 (que j'utilise maintenant) détectent des
caractères interdits dans un lien et transforment en <a
href="%3Cecho%20$lien%3E">cliquez ici</a>. Cette
nouvelle version détecte ce codage, le décode avant de traiter
la commande prehtml, puis recode le résultat de la même manière
(au lieu du codage HTML genre "é")
- 03/08/2002: correction d'un bug qui rendait inutilisable la
fonction <SHELLECHONOESC>
- 18/05/2002: ajout de <TAG>
- 26/01/2002: version 1.3: modification des spécifs de
<REINCLUDE>, pour permettre de mettre <REINCLUDE>
dans un fichier inclus (exemple à plusieurs niveaux dans cette
doc): j'en avais besoin et en fait c'était devenu réalisable
depuis la version 1.2
- 28/11/2001: version 1.2: Correction d'un gros bug dans
<REINCLUDE>: on pouvait retrouver un fichier avec plein
d'entêtes mises à la suite (ce qui ne semble poser de problème
dans aucun navigateur!).
- 17/10/2001: version 1.1: Correction de <REINCLUDE>, qui
marche maintenant même dans <GENERATE>, et ajout des
commandes <ERROR> et <WARNING>.
- 23/10/2001: version 1.0.beta-2. Ajout de <REINCLUDE>.
- 15/10/2001: version 1.0.beta-1. Grand nettoyage: gestion
complète du shell bloqué ou tardant trop, et de l'arre par
l'utilisateur; effacement des fichiers temporaires en cas
d'arrêt brutal.
- 13/10/2001: version 1.0. C'est la première modification
depuis un mois: détection des blocages du shell (guillemet non
fermé, possibilité limitée d'inclure du HTML dans les
commandes). Je décide de mettre enfin un numéro de version.
- 27/09/2001: le programme fonctionne vraiment bien, je
l'utilise pour la création d'un autre site: http://collectiftramway.free.fr
(association militant pour améliorer les projets de tramway à
Montpellier).
- 14/09/2001: le programme fonctionne, je commence à l'utiliser
pour un site réel: http://montpellier.fubicy.org
(association de cyclistes urbains à Montpellier)
- 31/08/2001: idée originale d'un préprocesseur basé sur le
shell, et utilisable depuis un éditeur HTML Wysiwyg. Une brève
recherche sur internet, et je ne trouve rien dans ce genre. En
fait, je voudrais un genre de PHP, mais simple, et qui vise le
traitement avant de télécharger les pages sur un serveur (et non
le traitement à la demande).
Moi
J'ai une page ici.
Adresse de cette page: http://mjulier.free.fr/prehtml/lisezmoi.html