Um PHP-Code farblich hervorzuheben, bietet PHP einen
eigenen Mechanismus an. Durch den Befehl highlight_string() lässt sich beliebigem
Code Syntax-Hervorhebung hinzufügen. Dazu werden an den relevanten Stellen
Inline-Styles der Form <span style="color: #xxxxxx"> ... </span>
eingefügt. Diese durchaus nützliche Funktion hat nur einen kleinen Makel.
Durch die Inline-Styles kann man das Erscheinungsbild der einzelnen Bereiche
nicht mehr global beeinflussen. Über unterschiedliche Stylesheet-Dateien lässt
sich also das Erscheinungsbild nicht mehr verändern, was sich unter anderem auch
beim Print-Stylesheet negativ bemerkbar macht. Was liegt also näher, als diese
Funktion ein wenig zu verbessern?
Dabei bieten sich zwei Vorgehensweisen an:
- Man könnte sich eine eigene Highlighting-Funktion schreiben, die statt der Inline-Styles CSS-Klassen zur Hervorhebung verwendet. Der Aufwand steht dabei aber (meiner Meinung nach) in keinerlei Verhältnis zum Nutzen.
- Alternativ könnte man die erzeugten Inline-Styles durch Reguläre Ausdrücke mit CSS-Klassen ersetzen. Dies lässt sich einfach und schnell realisieren und sollte auch in der Mehrzahl aller Fälle problemlos funktionieren.
Die zweite Möglichkeit soll in diesem Beispiel umgesetzt werden.
Vorüberlegungen
Da die gestellte Aufgabe keinen all zu hohen Aufwand vermuten lässt, sind auch nur wenige Vorüberlegungen nötig. Wir benötigen eine Funktion, die auf den übergebenen Quellcode die Funktion highlight_string() anwendet, die darin enthaltenen Inline-Styles in CSS-Klassen umwandelt und den so veränderten Text zurückgibt. Der Klassenname sollte dabei den von PHP definierten Namen (siehe weiter unten) entsprechen und eventuell noch um ein Präfix erweitert werden können, um Konflikte mit schon definierten Klassen zu vermeiden.
Mehr ist nicht zu tun. Wie die Funktion möglichst effektiv zu gestalten ist, können wir uns noch während der Entwicklung überlegen.
Vorgehensweise
Als erstes stellen wir den Körper der Funktion auf. Wir geben ihr einen aussagekräftigen Namen, und definieren die erwarteten Parameter. Dies wären der zu verändernde Text und ein optionales Präfix. Kommentare helfen uns dabei, uns in zwei Wochen noch daran zu erinnern, was diese Funktion eigentlich macht.
Die Funktionsdefinition
Wir definieren also folgendes (die Kommentare kann man später noch ergänzen, da
man anfangs für gewöhnlich noch nicht wirklich weiß, was die Funktion später
genau macht):
<?PHP
//
// Ersetzt die durch die PHP-Highlight-Funktion erzeugten Inline-Styles durch
// CSS-Klassen. Funktioniert so nur in den Versionen, die die Farben über
// Inline-CSS und nicht per <font> definieren
//
//
// Die Ersetzungs-Funktion. Erzeugt werden Klassen, die die in dem Array
// definierten Namen tragen. Optional kann ein Präfix angegeben werden
//
function highlight($content, $prefix = '') {
}
?>
Um nachher die vergebenen Style-Definitionen ersetzen zu können, müssen
wir die verwendeten Farben vorher eindeutig festlegen. Die Farben, die standardmäßig
verwendet werden, sind in der Datei php.ini festgelegt:
; Colors for Syntax Highlighting mode. Anything that's acceptable in
; <span style="color: ???????"> would work.
highlight.string = #DD0000
highlight.comment = #FF9900
highlight.keyword = #007700
highlight.bg = #FFFFFF
highlight.default = #0000BB
highlight.html = #000000
Um sie nachher leichter ersetzen zu können, werden wir sie per ini_set() auf
uns bekannte Werte setzen, so müssen wir sie nicht extra auslesen. Dies
soll über eine Schleife und ein Array geschehen, da wir das Array nachher noch
bei der Ersetzung weiter verwenden können.
Das Array mit den Farbwerten
Bevor wir das Array anlegen, denken wir noch ein wenig in die Zukunft. Wenn wir
nachher die Ersetzung durchführen, werden wir den Regulären Ausdruck so gestalten,
dass wir den jeweiligen Farbwert als Unterausdruck erhalten. Wenn wir den dann
als Index des jeweiligen Array-Elementes verwenden, können wir sehr einfach den
entsprechenden Klassennamen bestimmen. Unser Array muss also als Index den
Farbwert und als jeweiligen Wert den Klassennamen tragen. Da in der php.ini
sechs Farbwerte definiert sind, muss unser Array auch genau so viel Werte haben.
Welche Farbwerte wir genau definieren, ist dabei egal.
<?PHP
//
// Ein Dummy-Array mit Dummy-Farben, das lediglich dem Ersetzen dienen
// Angegebene Farbwerte sind nicht relevant
//
$colors = array(
'#111111' => 'string', '#222222' => 'comment', '#333333' => 'keyword',
'#444444' => 'bg', '#555555' => 'default', '#666666' => 'html'
);
?>
Die so definierten Werte müssen wir jetzt nur noch als Farben festsetzen. Dies
geschieht, wie oben schon erwähnt, durch die Funktion ini_set(). Wir durchlaufen
einfach unser Array und setzen dabei für den jeweiligen Wert die entsprechende
Farbe.
<?PHP
//
// INI-Werte manipulieren
//
foreach ($colors as $color => $key)
ini_set('highlight.'.$key, $color);
?>
Damit sind alle Vorbereitungen getroffen, wir können uns jetzt der Ersetzung widmen.
Die Ersetzung
Jetzt können wir den Regulären Ausdruck entwickeln, durch den die Ersetzung
durchgeführt werden soll. Dazu müssen wir uns erst einmal vor Augen führen,
wie PHP den Quellcode verändert hat. Die jeweils zu färbenden Bereiche werden
in <span>-Tags eingefasst, denen über das Style-Attribut eine Farbe
zugewiesen wird, ungefähr so:
<span style="color: #xxxxxx"> ... </span>
Wir müssen jetzt lediglich die entsprechende Style-Angabe durch eine Class-Angabe
ersetzen. Um die Style-Bereiche zu finden, verwenden wir folgenden Regulären
Ausdruck:
!style="color: (#\d{6})"!
Im ersten Unterausdruck definieren wir allgemein den sechstelligen Farbcode.
Jetzt müssen wir den Ersatz-String aufstellen. Da wir dabei auf die oben
definierten Array-Elemente zugreifen wollen und dabei eine Backreference
als Schlüssel verwenden wollen, müssen wir entweder eine Callback-Funktion
zum Ersetzen verwenden, oder den Modifier e verwenden.
Wir entscheiden und für letzteres und stellen unseren Ersatzstring auf. Der
soll nachher in der Form class="prefix_name" vorliegen.
Da wir den Namen aus dem Array beziehen, besteht der Ersatzstring insgesamt aus vier Teilen,
und zwar aus
- dem vorderen Teil:
class=", - dem Präfix, welches der Funktion übergeben wurde,
- dem eigentlichen Namen, der sich aus dem Array-Element ergibt, welches als Index den ersten Unterausdruck trägt und
- dem hinteren Teil, welcher lediglich aus dem
"besteht.
Diese vier Teile müssen mittels Stringverkettung verbunden werden, so dass
sich dann folgender Code ergibt.
"class=\"".$prefix.$colors["\1"]."\""
Wie man sieht, wurden die " jeweils maskiert, da
sie innerhalb von " stehen.
Diesen Text müssen wir jetzt PHP übergeben. Zur Erinnerung: Der übergebene
String muss sich als PHP-Code ausführen lassen. Obenstehender Code
ist zwar PHP-Code, sogar eine Stringverkettung, aber noch kein eigentlicher String.
Das wird er erst, wenn wir ihn in ' einfassen, so dass
sich als Ersatz folgendes ergibt:
'"class=\"".$prefix.$colors["\1"]."\""'
Der komplizierteste Teil liegt jetzt hinter uns, wir können jetzt die Funktion
aufstellen, die als dritten Parameter lediglich noch den von PHP hervorgehobenen
Code erhält. Zusätzlich müssen wir dem Suchmuster noch den Modifier e mitgeben.
Da damit unsere Funktion beendet ist, können wir den Rückgabewert von preg_replace()
gleich noch mit einem return versehen und damit unsere Funktion beenden.
<?PHP
//
// Ersetzen
//
return preg_replace(
'!style="color: (#\d{6})"!e',
'"class=\"".$prefix.$colors["\1"]."\""',
highlight_string($content, TRUE)
);
?>
Hier noch ein Beispiel, wie die Funktion eingesetzt werden kann:
<?PHP
//
// Anwendungsbeispiel
//
echo '<textarea cols="80" rows="15">'.
htmlspecialchars(highlight(file_get_contents('dummy.php'))).
'</textarea>';
?>
Die Ausgabe erfolgt mittels htmlspecialchars() innerhalb einer Textarea, um den
Code dann gleich weiter verwenden zu können.
Anmerkungen
Falls Ihnen die Verwendung des Modifiers e zu kompliziert erscheint, können Sie natürlich auch die Funktion preg_replace_callback() verwenden. In der dann zu definierenden Callback-Funktion muss dann das jeweilige Element des Arrays als Rückgabe verwendet werden. Das Array wiederum muss dafür außerhalb der Funktion definiert werden und dann zum Beispiel über das $GLOBALS-Array referenziert werden.
Vollständiger Quellcode
Hier fnden Sie den vollständigen Quellcode für dieses Beispiel:
<?PHP
//
// Ersetzt die durch die PHP-Highlight-Funktion erzeugten Inline-Styles durch
// CSS-Klassen. Funktioniert so nur in den Versionen, die die Farben über
// Inline-CSS und nicht per <font> definieren
//
//
// Die Ersetzungs-Funktion, erzeugt werden Klassen, die die in obigen Array
// definierten Namen tragen. Optional kann ein Präfix angegeben werden
//
function highlight($content, $prefix = '') {
//
// Ein Dummy-Array mit Dummy-Farben, das lediglich dem Ersetzen dienen
// Angegebene Farbwerte sind nicht relevant
//
$colors = array(
'#111111' => 'string', '#222222' => 'comment', '#333333' => 'keyword',
'#444444' => 'bg', '#555555' => 'default', '#666666' => 'html'
);
//
// INI-Werte manipulieren
//
foreach ($colors as $color => $key)
ini_set('highlight.'.$key, $color);
//
// Ersetzen
//
return $highlighted = preg_replace(
'!style="color: (#\d{6})"!e',
'"class=\"".$prefix.$colors["\1"]."\""',
highlight_string($content, TRUE)
);
}
?>
Sie können den Quellcode auch als Datei herunterladen.
Um die Datei verwenden zu können, müssen sie die Dateiendung .txt entfernen - sie
wurde hier lediglich angehängt, um einen Download zu ermöglichen.
Verwandte Themen
- Anwendungsbeispiele
- Aufbau von Regulären Ausdrücken
- Backreferences
- Der Backslash
- Einfache Texte finden
- Fehlermeldungen
- Metazeichen
- Modifier
- PHP-Funktionen
- preg_replace()
- preg_replace_callback()
- Quantifier
- Unterausdrücke
Kapitelnavigation
- Letzte Änderung: 05.04.2012, 16:11:10
- © 2003 - 2012 nophia web