PPWizard umožňuje vkládat do skriptů i programové kódy jazyka Rexx, díky čemuž se stává velmi silným nástrojem, který není svázán počtem svých vlastních funkcí. Tento článek je takovým malým výletem do jazyka Rexx a jeho praktického využití při generování WWW stránek.

Opakování

Opakování částí kódu (takzvané smyčky) můžete najít v programovacích jazycích pod pojmy for, repeat, while a jinými. Základní konstrukce pro opakování neabsentuje ani v repertoáru funkcí PPWizardu samotného:

#{
  Opakovaná část.
#}

Kdybychom v našem kódu tuto konstrukci uvedli, druhý řádek Opakovaná část by byl nerušeně zapisován do výstupního souboru až do zaplnění diskové kapacity. Naštěstí máme k dispozici dvě možnosti, jak opakování řídit:

  1. V opakované části můžeme použít příkaz #break pro ukončení celého opakování, nebo příkaz #continue pro ukončení právě běžícího cyklu a skok na další cyklus. Oba tyto příkazy se většinou používají ve spojitosti s příkazem #if a rexx proměnnými.
  2. Na prvním řádku, za příkazem #{, můžete použít rexx příkazy for() a case(). Upozorňuji, že zde nejde o příkazy PPWizardu, ale o přímé volání rexx interpretu.

Dále se zaměříme na druhou možnost, přičemž po prostudování tohoto článku byste neměli mít problém ani s bodem jedna.

V předchozím článku jsme načítali data z CSV souborů do datového pole, které jsme pak postupně zpracovávali právě cykly. Zde je příslušný kus kódu:

#{ FOR @@Record = 1 to <?Data:TmpCsv.?>
  #if @@Record // 2 = 0
    #RexxVar class = „sr“
  #else
    #RexxVar class = „lr“
  #endif
  <tr class=“<??class>“>
    <td><?Data:TmpCsv.@@Record.1></td>
    <td class=“num“><?Data:TmpCsv.@@Record.2></td>
    <td class=“num“><?Data:TmpCsv.@@Record.3></td>
  </tr>
#}

Datové pole TmpCsv obsahuje čistě tabulková data, která chceme vypsat do HTML tabulky. Na prvním řádku spouštíme opakování. Funkce for() zde způsobí, že na počátku prvního cyklu je inicializována rexx proměnná @@Record s hodnotou 1 a před každým dalším cyklem je zvýšena o jedničku. Jakmile dosáhne hodnoty počtu řádků datového pole TmpCsv, je celé opakování ukončeno.

Na druhém řádku můžete vidět, že lze rexx funkce vyvolávat i přímo v podmínce. Tady dělíme hodnotu proměnné @@Record dvěma a zároveň vyhodnocujeme, zda je tento podíl roven nule. Pakliže je, přiřazujeme funkcí #RexxVar proměnné class hodnotu „sr“ (sudý řádek), v opačném případě hodnotu „lr“ (lichý řádek).

Poté začneme vypisovat obsah řádku tabulky. Hodnotu proměnné class vyvoláváme standardní definicí <??class>. Při vyvolávání první hodnoty řádku určeném proměnnou @@Record v datovém poli TmpCsv používáme standardní definici <?Data:TmpCsv.@@Record.1>.

Pozn. aut.: V ukázce máme systematickou chybu v pojmenování proměnných. My nevíme, zda není náhodou proměná class některá z výchozích PPWizard proměnných, se kterými bychom se tak mohli dostat do kolize. Proto je vhodné REXX proměnné pojmenovávat s nějakým příznakem na začátku. Typicky @@, jako je tomu u proměnné @@Record. Tím navíc získáme možnost všechny tyto proměnné anulovat příkazem #nextid, aby se nám nevhodně nepřenesly do jiných nezávislých částí kódu.

V příkladu používáme rexx funkce na následujících místech:

  • Za příkazem #{ jsou povolené funkce for() a case().
  • V podmínce #if můžete používat základní matematické operátory (Rexx Expressions) a samozřejmě nesmíte zapomenout na operátor podmínečný (Rexx Conditional Logic).
  • Základní matematické operátory jsou povolené i v zabudovaném příkazu #rexxVar, určeném k definici rexx proměnné.

#defineRexx

Jak asi cítíte, ve výše jmenovaných případech jsem byli v programovacích možnostech omezeni. Pokud chceme ve skriptech použít skutečný komplikovanější rexx kód bez jakýchkoli omezení, použijeme funkci #defineRexx. Jako její parametr můžeme zadat jméno makra, pod kterým má být sada rexx příkazů registrována a později vyvolána. Pokud necháme parametr prázdný, jsou příkazy provedeny ihned.

V našem ukázkovém webu, v souboru mauris.it, používáme příkaz #defineRexx hned na několika místech. Nejprve převedeme příkazem Files4Mask() do datového pole photos seznam fotografií v adresáři určeném makrem photodir:

#DefineRexx “
  call Files4Mask „.<$photodir>*.jpg“, „photos“,,“Y“
#DefineRexx

Poté postupně všechny obrázky do dokumentu vložíme:

#{ for num = 1 to photos.0
  <$image file=“<??photos.num>“>
#}

Samotnému vkládání samozřejmě předchází definice makra pro vložení jednoho obrázku:

#(
#define image
  #defineRexx “
    size = GetImageHeightWidth(‚{$file}‘);
    alt = FilePart(‚name‘, ‚{$file}‘);
    src = alt;
  #defineRexx
  <img src=“<$photodir>/<??src>“ alt=“<??alt>“ <??size>>
#)

V makru image ukládáme do proměnné size řetězec width="x" height="y", který generuje funkce GetImageHeightWidth(), a do proměnné alt jméno souboru. To získáme funkcí FilePart(). Nakonec vložíme samotný HTML kód, přičemž proměnné vyvoláváme standardními definicemi <??promenna>.

Pozn. aut.: Z hlediska použitelnosti je ukázka stupidní, jelikož do atributu „alt“ elementu img není vhodné vypisovat jméno souboru, ale raději popis obrázku. Mohli bychom si tedy pomoci příkazem import, kterým bychom z textového souboru načetli popis obrázku.

#evaluate

Příkazem #evaluate můžeme definovat makro, které provede jeden nebo více rexx příkazů. Pokud necháme jméno prázdné, spustí se příkazy přímo na svém místě (stejně jako u příkazu #defineRexx). Funkce #evaluate je ale omezenější a prakticky se používá spíše pro vyvolání sady příkazů definovaných funkcí #defineRexx.

Pro názornost si prohlédněte následující čtyři příklady, které se liší formou, ale nikoli funkcí:

#DefineRexx “
  call Files4Mask „.<$photodir>*.jpg“, „photos“,,“Y“
#DefineRexx

#evaluate “ ^call Files4Mask „.<$photodir>*.jpg“, „photos“,,“Y“^

#DefineRexx ‚nacti‘
  call Files4Mask „.<$photodir>*.jpg“, „photos“,,“Y“
#DefineRexx
#evaluate “ ‚<$nacti>

#(
#define nacti
  #DefineRexx “
    call Files4Mask „.<$photodir>*.jpg“, „photos“,,“Y“
  #DefineRexx
#)
<$nacti>

Datum a čas

Pěkná praktická kouzla lze v PPWizardu provádět s datem a časem. Časové údaje zapisujeme v implicitním formátu YYYYMMDDHHMMSS, který pak usměrňujeme rexx funkcí FormatTime().

Představte si, že budujeme informační web typu Interval.cz, na kterém budou pravidelně vycházet články, u kterých chceme vypisovat datum a čas vydání. Ve společném souboru pro celý web definujeme makro vydano, zpracovávající datum a čas předávaný jako parametr:

#define CZECH_MONTH_NAMES_LONG ledna února března dubna května června července srpna září října listopadu prosince
#(
  #define vydano
  Vydáno:
   <?=FormatTime(‚%e. %B %Y, %!:%M‘, ‚{$#1}‘, ‚CZECH‘)>
#)

Makro pak vyvoláme v článku na příslušném místě <$vydano "200408280018">.

Na prvním řádku vidíte definici makra CZECH_MONTH_NAMES_LONG. Jméno není náhodné, ale přesně vyhrazené pro seznam jmen měsíců vypisovaných funkcí FormatTime(). (Vyhrazená makra a konfigurační řady byly vysvětleny v článku PPWizard – práce s daty v externích souborech u popisu funkce #import.) K dispozici máme dále vyhrazená makra pro zkrácená jména měsíců, dlouhá i zkrácená jména dnů, rozlišení dopoledních a odpoledních hodin a podobně. V definici makra vydano vidíte další možnost, jak lze dále vyvolat rexx funkci, tentokráte standardní definicí.

Funkce FormatTime() má tři parametry:

  • Výstupní formát data a času (v ukázce %e. %B %Y, %!:%M).
  • Datum a čas v implicitním formátu (v ukázce {$#1}).
  • Konfigurační řada (používá se pak na začátku jména vyhrazených maker).

Tento článek o implementaci rexx programových kódů do skriptů PPWizardu berte spíše jako takový velmi letmý výlet do problematiky, která by sama o sobě vydala na celou knihu. Byl bych rád, kdybyste se v komentářích rozhovořili o konkrétních problémech, se kterými si nevíte ve svých skriptech rady. Budou-li zajímavé a bude-li jejich řešení obecně přínosné, pokusím se je v dalším článku předložit jako praktické ukázky.

Odkazy, zdroje

Žádný příspěvek v diskuzi

Odpovědět