Code snippet formatting with GeSHi

In this snippet I will show you how to format code using a combination of the Generic String Highlighter (GeSHi) class and custom PHP and CSS. The first objective is to figure out the best way to include code in an HTML document. I decided the best way was to put the code in a seperate text file and read its contents with PHP. This way we can parse it line by line, and also link to the file on the page for people who want to access it.

The function returns an HTML list and puts each line of the code text in a list item. Then, using the GeSHi class it highlights the code according to the language specified. For more information on using GeSHi, check out their website. At the end of the list, it adds another list item with a link to the source text file.

The function: codify()

  1. // GeSHi class - http://qbnz.com/highlighter
  2. require_once('geshi/geshi.php');
  3.  
  4. // formats code from file $uri and highlights according to language $lang (using the GeSHi)
  5. function codify($htmlid,$uri,$lang,$line_numbers=true,$show_uri=true) {
  6. $dir = "/sourcecode/"; // default dir
  7. $lines = file(ABSDIR.$dir.$uri); // put lines of file into array
  8. $list = ($line_numbers)? 'ol' : 'ul'; // ordered or unordered list, whether or not you want line numbers
  9. $ret = "<pre><$list id=\"$htmlid\" class=\"code-list $lang\">";
  10. if (!empty($lines)) {
  11. foreach ($lines as $line) {
  12. $line = rtrim($line); // get rid of whitespace at the end of each line
  13. $line = str_replace("\t"," ",$line); // replace tabs with 4 spaces
  14. $geshi =& new GeSHi($line, $lang); // create GeSHi code highlighting object
  15. $geshi->enable_classes();
  16. $line = $geshi->parse_code(); // apply GeSHi highlighting
  17. $line = preg_replace("@</?pre.*>@U","",$line); // remove <pre>s created by GeSHi
  18. $ret .= "<li><span>$line</span></li>\n";
  19. }
  20. if ($show_uri) $ret .= "<li class=\"code-list-source\"><span>source file: <a href=\"$dir$uri\" title=\"$uri\">$uri</a></span></li>\n";
  21. } else $ret .= "<li class=\"error tc\">Cannot read contents of $uri</li>\n";
  22. $ret .= "</$list></pre>\n";
  23. return $ret;
  24. }
  25. source file: code-highlighting.txt

codify() takes 5 arguments (2 of which are optional):

It returns an HTML unordered or ordered list, depending on whether or not you wanted line numbers.

Below is an example of using codify(). The result of this call is exactly what you see.

Styling the list

To make the code presentable (besides the GeSHi CSS, which you must remember to include), we will also have to style the list with our own CSS. In codify() we gave the list a class of code-list for this purpose. Here's the CSS zakness.com uses to style codify'd lists:

  1. .code-list {
  2. padding: 0.5em;
  3. background: #fafafa;
  4. }
  5. ol.code-list {
  6. border-left: 2.8em solid #111;
  7. padding-bottom: 0.2em;
  8. }
  9. .code-list li {
  10. margin: 0 0 -2.1em 0;
  11. padding: 0;
  12. line-height: 1.4em;
  13. color: #fff;
  14. font-size: 0.8em;
  15. }
  16. .code-list li>span {
  17. color: #484340;
  18. font-size: 1.2em;
  19. }
  20. .code-list li>span span {
  21. font-size: 1em;
  22. }
  23. li.code-list-source {
  24. color: #111;
  25. }
  26. li.code-list-source span {
  27. padding: 0.2em 1em 0.5em 0;
  28. color: #a0a0a0 !important;
  29. text-align: right;
  30. display: block;
  31. font: 1.2em "Lucida Grande", Verdana, Tahoma, Arial, sans-serif;
  32. }
  33. pre {
  34. white-space: -moz-pre-wrap; /* Mozilla */
  35. white-space: -o-pre-wrap; /* Opera 7 */
  36. word-wrap: break-word; /* IE */
  37. }
  38. source file: code-highlighting-css.txt

In order to style the line numbers of the ordered list, we have to wrap the contents of each list item in their own <span> and give the <li> and <span> different font colors. It was also necessary to use proprietary style rules on the pre tag to fix line breaks. This has been tested in IE7, Firefox 2.0+, Camino, and Safari.