LaTeX/Algoritmes en broncodes
LaTeX kan goed overweg met het zetten van broncodes, er is zelfs automatische syntax-kleuring, automatische update naar nieuwe code, verwijzing naar regelnummers ... Dit houden we echter even voor later, we gaan eerst de tekstzetting van algoritmes (pseudocode) beschrijven, daarna komt er een korte sectie over letterlijke code zonder opmaak tonen en uiteindelijk de langverwachte sectie over uitgebreide codezetting.
Algoritmes
Als je algoritmes met een mooie lay-out wilt zetten gebruik je best het algorithmic
-pakket (let op de h). Met dit pakket kun je het algoritme op een logische manier opbouwen zoals je de code zou schrijven in een eenvoudige programmeertaal. Het pakket zal dan de code verwerken tot een mooi ogend algoritme.
\usepackage{algorithmic}
Een algoritme moet je maken binnen een algorithmic
-omgeving. We geven een klein voorbeeld:
\begin{algorithmic}
\IF {$i\geq maxval$}
\STATE $i\gets 0$
\ELSE
\IF {$i+k\leq maxval$}
\STATE $i\gets i+k$
\ENDIF
\ENDIF
\end{algorithmic}
Programmeertaal
Natuurlijk moet het algorithmic
-pakket de code zelf ook interpreteren om een degelijke output te krijgen, daarom moet je de algoritmes ook in een gestandaardiseerde manier neerschrijven.
Gewone opdrachten
Onder de gewone opdrachten valt alles wat op één regel komt. Dit zijn bijvoorbeeld oproepen van een andere functie of het toewijzen van een waarde aan een variabele. Een gewone opdracht moet altijd met het \STATE
-commando beginnen (let op de hoofdletters). Na het state-commando volgt dan je opdracht. Het is aan te raden opdrachten altijd in wiskunde-modus te schrijven, dan kun je de uitgebreide verzameling aan wiskundige symbolen gebruiken. Een voorbeeld van een klein algoritme:
\begin{algorithmic}
\STATE $i \gets 10$
\STATE RoepFunctieOp($i$)
\end{algorithmic}
If-Else
De volgende codes spreken voor zich:
\IF{<conditie>} <uit te voeren code> \ENDIF
\IF{<conditie>} <uit te voeren code> \ELSE <uit te voeren code> \ENDIF
\IF{<conditie>} <uit te voeren code> \ELSIF{<conditie>} <uit te voeren code> \ELSE <uit te voeren code> \ENDIF
Het doet er niet toe of je alles nu op een lijn zet of het splitst over verschillende lijnen, het algorithmic
-pakket zorgt voor zijn eigen uitlijning.
Lussen
\FOR{<conditie>} <te herhalen code> \ENDFOR
\FORALL{<conditie>} <te herhalen code> \ENDFOR
\WHILE{<conditie>} <te herhalen code> \ENDWHILE
Een lus die normaal niet in programmeertalen zit is de oneindige lus, te vergelijken met while(true). In het algorithmic
-pakket krijgt deze lus een eigen naam.
\LOOP <te herhalen code> \ENDLOOP
Pre- en postcondities
In het algorithmic
-pakket kun je ook pre- en postcondities invoegen met de volgende commando's:
\REQUIRE <preconditie>
\ENSURE <postconditie>
Andere commando's
De andere commando's spreken ook voor zich aangezien ze gebruikt worden in zowat alle programmeertalen.
\RETURN <te returnen waarde>
\PRINT <een variabele of een vaste tekst>
\COMMENT <commentaar>
Merk op dat het commentaar bij een \COMMENT
-commando altijd op dezelfde regel als het vorige commando verschijnt. Het is dan ook niet toegestaan om het \COMMENT
-commando te gebruiken na een commando zoals \IF
.
Regelnummering
Er is eenvoudig regelnummering toe te voegen aan een algoritme, als je bijvoorbeeld iedere vijf regels een nummer wil plaatsen, dan gebruik je de volgende omgeving:
\begin{algorithmic}[5]
%algoritme code
\end{algorithmic}
Een drijvende omgeving
Net zoals er voor figuren en tabellen een drijvende omgeving bestaat is er ook zo'n omgeving voor algoritmes. Deze omgeving heeft de naam algorithm
gekregen en werkt volledig gelijkaardig aan de figure
-omgeving.
Als je nog meer informatie wilt, kun je nog eens de originele handleiding bekijken ook.
De verbatim
-omgeving
Om de verbatim
-omgeving te gebruiken moet je eerst het verbatim
-pakket laden.
\usepackage{verbatim}
De verbatim
-omgeving zelf werkt zeer eenvoudig. Alles wat je in die omgeving zet wordt rechtstreeks weergegeven, zonder enige opmaak. Je gebruikt de omgeving dus als volgt:
\begin{verbatim}
Hier komt de code die je wil laten zien.
\end{verbatim}
Je kan ook het \verb
-commando gebruiken om iets (b.v. de naam van een veriabele) letterlijk weer te geven binnen een regel. Na het \verb
-commando moet je eerst een teken gebruiken dat nergens in je code vooromt, b.v. een ":" of een "=", daarna typ je de code die je wil weergeven en je sluit weer af met hetzelfde teken als je eerst gebruikt hebt. We geven een voorbeeldje:
In deze tekst vertel ik over de variabele \verb=$var=, deze variabele ...
Het listings
-pakket
Het listings
-pakket is veel geavanceerder dan het verbatim
-pakket. Om listings te gebruiken moet je eerst het listings
-pakket laden:
\usepackage{listings}
Merk even op dat alle commando's van het listings
-pakket beginnen met lst
, dit is om zeker in orde te zijn met de lppl-licentie.
De code zelf zet je in een lstlisting
-omgeving, net zoals bij de verbatim
-omgeving, om inline code te zetten gebruik je het \lstinline
-commando op dezelfde manier als het \verb
-commando. Je kunt ook code van een extern document laden met het commando \lstinputlisting{padNaarHetBestand}
waarbij padNaarHetBestand
de (relatieve) locatie van het bronbestand is. Als je code van een bronbestand laadt, ben je zeker dat de code in je LaTeX-document altijd actueel is en zo hou je je LaTeX-document ook meer overzichtelijk. Als de broncode niet dicht bij je LaTeX-document staat (dus niet in dezelfde map of een submap) of je begint te werken met absolute paden, dan zorg je er wel voor dat je LaTeX-document niet op andere computers gecompileerd kan worden.
Alle opties in het listings
-pakket hebben eenzelfde structuur: iedere optie kan bepaald worden door een sleutel sleutel=waarde
-structuur. De taal waarin je code geschreven is, is ook zo'n optie en wordt dus ook op een dergelijke manier bepaald.
De programmeertaal definiëren
Meestal gebruik je voor het volledige document eenzelfde programmeertaal, dan kun je deze taal in de hoofding definiëren. De taal pascal
voor je volledig document definiëren doe je als volgt:
\lstset{language=Pascal}
De sleutel is hier dus language
en de waarde die je aan de sleutel geeft is Pascal
.
Alles wat je als opties binnen het lstset
-commando zet kun je ook per lstlisting
-omgeving apart definiëren als optie. Dit doe je zoals het voorbeeld hier onder:
\begin{lstlisting}[language=pascal]
for i:=maxint to 0 do
begin
{ do nothing }
end;
Write(’Case insensitive ’);
WritE(’Pascal keywords.’);
\end{lstlisting}
Ook met het commando \lstinputlisting
kun je dezelfde opties gebruiken:
\lstinputlisting[language=pascal]{padVanHetBestand}
Van sommige talen zijn er ook dialecten, deze kun je opvragen als language=[XSC]Pascal
Voorgedefinieerde talen
Hieronder staat een tabel met voorgedefinieerde talen, tussen haakjes zijn mogelijke dialecten aangegeven en de standaard dialecten zijn onderlijnd.
ABAP (R/2 4.3, R/2 5.0, R/3 3.1, R/3 4.6C, R/3 6.10) | ACSL | Ada (2005, 83, 95) | Algol (60, 68) | Ant |
Assembly (Motorola68k, x86masm) | Awk (gnu, POSIX) | bash | Basic (Visual) | C (ANSI, Handel, Objective, Sharp) |
C++ (ANSI, GNU, ISO, Visual) | Caml (light, Objective) | CIL | Clean | Cobol (1974, 1985, ibm) |
COMAL-80 | command.com (WinXP) | COMSOL | csh | Delphi |
Eiffel | Elan | erlang | Euphoria | Fortran (77, 90, 95) |
GCL | Gnuplot | Haskell | HTML | IDL (empty, CORBA) |
inform | Java (empty, AspectJ) | JVMIS | ksh | Lingo |
Lisp (empty, Auto) | Logo | make (empty, gnu) | Mathematica (1.0, 3.0, 5.2) | Matlab |
Mercury | MetaPost | Miranda | Mizar | ML |
Modula-2 | MuPAD | NASTRAN | Oberon-2 | OCL (decorative, OMG) |
Octave | Oz | Pascal (Borland6, Standard, XSC) | Perl | PHP |
PL/I | Plasm | PostScript | POV | Prolog |
Promela | PSTricks | Python | R | Reduce |
Rexx | RSL | Ruby | S (empty, PLUS) | SAS |
Scilab | sh | SHELXL | Simula (67, CII, DEC, IBM) | SPARQL |
SQL | tcl (empty, tk) | XML | XSLT | TeX (AlLaTeX, common, LaTeX, plain, primitive) |
VRML (97) | VBScript | Verilog | VHDL (empty, AMS) |
Regelnummering
In verband met regelnummering zijn er ook heel wat opties in het listings
-pakket. De opties zijn hieronder opgesomd en moeten gebruikt worden zoals je de taal bepaalt.
sleutel | omschrijving |
---|---|
firstline =<Getal>
|
De eerste regel die wordt weergegeven (kun je gebruiken als je enkel een deel code vanuit een extern bestand wilt weergeven) |
lastline =<Getal>
|
De laatste regel die wordt weergegeven (zie firstline )
|
linerange =<begin1>-<einde1>,<begin2>-<einde2>...
|
De vorige twee commando's in één met de mogelijkheid om meer blokken samen te nemen. <begin1>,<einde1> ... zijn allemaal regelnummers. |
numbers=<none/left/right>
|
De plaats waar de regelnummers geplaatst worden. |
numberstyle =<Opmaakstijl>
|
De opmaak voor de regelnummers, je kunt mogelijk \tiny of \color{blue} gebruiken.
|
numbersep =<Afstand>
|
De afstand van de linkerkant van de regelnummers tot de linkermarge van de broncode. |
stepnumber =<Getal>
|
Per hoeveel nummers geteld wordt. |
firstnumber =<auto/last/ <getal>>
|
Bij welk nummer je begint te tellen, auto begint bij 1 voor een nieuwe listing en bij het overeenkomstige regelnummer als je een extern bestand opvraagt. last begint waar de vorige listing gestopt is en je kunt natuurlijk ook een exact getal ingeven.
|
Escapen naar LaTeX en referenties
Escapen kun je vertalen door ontsnappen. We gaan hier dus in onze broncode ontsnappen naar LaTeX. Je kunt dit gebruiken om dynamisch naar regels te verwijzen, om over iets commentaar te geven in wiskunde-modus en om willekeurige, eenmalige opmaak te geven aan je code-documenten.
De eerste optie die je kunt gebruiken is de \texcl=true|flase
-optie. Met deze optie zorg je er voor dat alle commentaar als LaTeX
geïnterpreteerd wordt.
Je kunt ook de optie \mathescape=true|false
gebruiken om naar wiskunde-modus over te schakelen tussen twee $-tekens. Zorg wel dat er dan geen $-tekens gebruikt worden in je code.
Uiteindelijk heb je nog vier commando's om volledig zelf te bepalen wanneer je naar LaTeX modus overschakelt:
\escapechar =<karakter>
|
tussen twee karakters die opgegeven zijn zal er overgegaan worden op LaTeX-modus. Let wel op, als het karakter dat je wilt opgeven een speciale betekenis heeft in LaTeX (zoals het %-teken), dan moet je er een backslash voor zetten (\%). |
escapeinside =<karakter1><karakter2>
|
Hetzelfde zoals hierboven maar voor verschillende begin- en eindkarakters |
escapebegin =<karakters>
|
Hetzelfde als hierboven maar voor de duidelijkheid kun je het over twee commando's splitsen. |
escapeend =<karakters>
|
Hetzelfde als hierboven maar voor de duidelijkheid kun je het over twee commando's splitsen. |
om de kracht van het escapen naar LaTeX te zien kun je eens onderstaande code uitproberen. Als je pdfLaTeX gebruik kun je ook het pakket pdfpages
toevoegen om een hyperlink naar de juiste regel te krijgen.
\documentclass{article}
\usepackage{listings}
\usepackage{color}
\usepackage[dutch]{babel}
\lstset{language=Java,
%alles tussen "//(*" en "*)" wordt als TeX code verwerkt
escapeinside={//(*}{*)}}
\begin{document}
\begin{lstlisting}
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello world!");//(*\label{re:printCommando}*)
int a = 5/3;//(*{\color{blue}\ \ \ \ \ $a=\frac{5}{3}$}*)
}
}
\end{lstlisting}
In regel \ref{re:printCommando} tonen we ``Hello world!''.
\end{document}
Let er op dat de code blijft werken want in Java staat commentaar na een "//" en dit is een deel van het escape begin.
Ik hoop dat de syntax-kleuring van jouw editor iets beter is dan de wiki syntax-kleuring want binnen een listings-omgeving wordt code normaal niet uitgevoerd en moet ze dus ook niet gekleurd worden in verschillende kleuren.
Dynamische regels
Je kunt ook een dergelijke structuur gebruiken om een dynamisch deel van je tekst te selecteren. In de vorige subsectie heb je gezien dat je delen van je code kunt selecteren om in te voegen in je document. Bij dat selecteren moest je echter vaste regelnummers kiezen. Dit is niet aan te raden als de code nog in ontwikkeling is en er dus nog regels kunnen bij komen. De makers van het listings-pakket waarschuwen wel dat het nog om een experimentele optie gaat, het zou dus kunnen dat in latere versies de syntax of de uitvoer licht gewijzigd wordt en je document niet meer 100% compatibel is.
In de uitleg zullen we ook het woord label gebuiken, merk op dat het hier niet gaat om een LaTeX-label maar een label dat enkel binnen het listings
-pakket kan gebruikt worden.
De twee commando's die je nodig hebt zijn:
rangeprefix =<karakters>
|
De karakters die gebruikt worden om het begin van een label aan te geven. |
rangesuffix =<karakters>
|
De karakters die gebruikt worden om het einde van een label aan te geven. |
includerangemarker=true/false
|
Toon of verberg de regels waar het label staat. |
We geven een voorbeeld:
\documentclass{article}
\usepackage{listings}
\usepackage{color}
\usepackage[dutch]{babel}
\lstset{language=Java,
escapeinside={//(*}{*)},
%een listings label komt tussen "//{" en "}"
rangeprefix=//\{,
rangesuffix=\},
includerangemarker=false}
\begin{document}
\begin{lstlisting}[linerange=mainBegin-mainEnd]
public class HelloWorld{
//{mainBegin}
public static void main(String[] args){
System.out.println("Hello world!");//(*\label{ru:printCommando}*)
int a = 5/3;//(*{\color{blue}\ \ \ \ \ $a=\frac{5}{3}$}*)
}
//{mainEnd}
}
\end{lstlisting}
In regel \ref{ru:printCommando} tonen we ``Hello world!''.
\end{document}
Let wel even op het regelnummer in je document. Het listings
-pakket begint standaard te tellen bij 1 aan het begin van de code, maar nu geef je die code niet meer weer. Je kunt mogelijk het pakket instellen om regelnummers weer te geven of je kunt instellen om te beginnen tellen bij de eerste regen van de weergegeven code, dit is al behandeld in een vroegere subsectie.
Kaders en lijnen rond je code
Het eenvoudigste om een kader rond je code te zetten is met de optie frame=type
waarbij het type een van de volgende tabel is:
none
|
Geen lijnen. |
leftline
|
Een enkele lijn langs de linkerkant. |
topline
|
Een enkele lijn langs de bovenkant. |
bottomline
|
Een enkele lijn langs de onderkant. |
lines
|
Twee enkele lijnen langs de boven en onderkant. |
single
|
Een enkel kader. |
shadowbox
|
Een schaduw aan je kader geven. |
Het is ook mogelijk zelf te bepalen welke lijnen je toont i.p.v. een van de vorige keuzes te nemen. Dit is mogelijk door als argument aan de frame
-optie enkele van de letters tbrlTBRL te geven. De hoofdletters stellen dubbele lijnen voor en de kleine letters enkele lijnen. De karakters zelf staan voor waar welke lijn moet getekend worden:
t,T | boven (top) |
b,B | onder (bottom) |
r,R | rechts |
l,L | links |
Zo zal de code
\begin{lstlisting}[frame=BTrl]
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello world!");
int a = 5/3;
}
}
\end{lstlisting}
een kader rond de java code weergeven met onder en boven een dubbele lijn. Het is het best deze optie met het \lstset
-commando te definiëren omdat dan voor alle omgevingen hetzelfde kader gebruikt wordt.
Ronde hoeken
Het is ook mogelijk om ronde hoeken aan je kaders te geven. Dit wordt met de optie frameround
gegeven. Als argument bij deze optie horen vier letters. De eerste letter stelt de ronding van de rechter bovenhoek voor, de tweede de rechter benedenhoek, de derde de linker benedenhoek en de vierde en laatste de linker bovenhoek. Ze beginnen dus te tellen bij de rechter bovenhoek en gaan verder in wijzerzin. De letters die je kunt gebruiken zijn t
en f
. t
stelt een afgeronde hoek voor en f
een vierkante hoek. De opties frame=RBtl,frameround=ftft
stellen dus een kader voor met de onderste en de rechtse lijn dubbel, de andere lijnen enkel en met de linker bovenhoek en de rechter benedenhoek afgerond.
Let er wel op dat een viewer zoals adobe wat meer moeite heeft met ronde dan met rechte hoeken. Kijk dus goed of alles correct wordt weergegeven.
Kaders en regelnummering
Standaard staat de regelnummering links van de code. Als er dus een kader getekend wordt, dan valt die nummering buiten het kader. Dit kan de bedoeling zijn maar meestal is het niet zo mooi. Je kunt dit oplossen door het kader iets groter te maken met de framexleftmargin
optie. Waarschijnlijk zal 5mm groot genoeg zijn, gebruik daarvoor de optie framexleftmargin=5mm
.
Achtergrondkleur
Het kan duidelijk zijn als je je code in een achtergrondkleur zet. Dit kan eenvoudig gebeuren met de optie backgroundcolor
. Als argument moet je een kleur meegeven zoals uitgelegd in de sectie over kleuren. Als je bijvoorbeeld een grijze achtergrond wilt, kun je de optie backgroundcolor=\color{gray}
gebruiken.
Het is wel aan te raden je eigen grijs te definiëren (zoals onder in de sectie over kleuren uitgelegd) en als je met kleuren werkt, dan werk je beter met eenvoudige of zelfs zonder kaders.