PHP-Highlighting-Funktion verbessern

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:

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

  1. dem vorderen Teil: class=",
  2. dem Präfix, welches der Funktion übergeben wurde,
  3. dem eigentlichen Namen, der sich aus dem Array-Element ergibt, welches als Index den ersten Unterausdruck trägt und
  4. 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($contentTRUE) ); ?> 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($contentTRUE) ); } ?> 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
Kapitelnavigation