Page 1 of 1

Display Formatted Code Rate Topic: -----

#1 andrewsw  Icon User is online

  • It's just been revoked!
  • member icon

Reputation: 3617
  • View blog
  • Posts: 12,456
  • Joined: 12-December 12

Posted 29 December 2012 - 01:42 PM

There are numerous plugins that can display text as formatted, and colour-coded, code. If you wish to do this in a (relatively) simple fashion, without requiring a large plug-in, then read on.

Attached Image

I am retrieving data from a database and displaying it in a DIV with the correct indentation, and colour-coding of certain keywords. The only requirement is that the original text uses four-spaces to represent a tab or indent. (It can easily be modified to accept a different number of spaces.)

For each line, the multiples of four-spaces (on the left) are removed and the line is then inserted into the DIV, and an OL, in LIs of a certain class: tab0, tab1, etc. These classes use left-padding of a multiple of 30px to indent correctly.

Any spaces to the right are simply removed (trimmed) and any remaining double-spaces are replaced by a single non-breaking space (nbsp). I use a single nbsp as they are generally wider than a single space. [This may be not be perfect, but it works quite well!]

Here is the css that I use:

.shadow {
     -moz-box-shadow: 5px 5px 5px 0px #CCC;
     -webkit-box-shadow: 5px 5px 5px 0px #CCC;
     box-shadow: 5px 5px 5px 0px #CCC;
}

.blogcode {
    margin: 10px 5px 20px 5px; padding: 0 0 0 8px;
    background-color: #F6F3F3;
    font-family: Consolas, 'Courier New', monospace;
    font-size: smaller; color: green;
}
.blogcode ol {
    list-style-position: outside;
    margin: 0; padding: 0 0 0 30px;
}
.blogcode li {
    padding: 3px 5px; margin: 0;
    border-left: thin solid green;
}
.blogcode ol li:nth-child(odd) { background: white; }

.blogcode li.tab0 { padding-left: 5px; }
.blogcode li.tab1 { padding-left: 35px; }
.blogcode li.tab2 { padding-left: 65px; }
.blogcode li.tab3 { padding-left: 95px; }
.blogcode li.tab4 { padding-left: 125px; }
.blogcode li.tab5 { padding-left: 155px; }
.blogcode li.tab6 { padding-left: 185px; }
.blogcode li.tab7 { padding-left: 215px; }
.blogcode li.tab8 { padding-left: 245px; }
.blogcode li.tab9 { padding-left: 275px; }


The text is retrieved while looping through the rows from a query, as $rowh['code']. The main processing (within a loop) is here:

echo "<div class=\"blogcode shadow\">";
echo "<ol start=\"1\">";
$html_lines = '';
// get rid of newlines; each separate line will be inserted into an LI
$code_lines = explode("\n", $rowh['code']);
foreach ($code_lines as $line) {
    $count_fours = strlen($line) - strlen(ltrim($line, ' '));
    // how many mutiples of four-spaces (to the left) are there?
    $count_fours = ceil($count_fours / 4);
    $line = ltrim($line);
    $line = codeWords($line);       // blue keywords
    // replace any remaining two-spaces with nbsp
    $line = str_replace('  ', '', $line);
    // Use @ to break-up keywords that shouldn't be colour-coded;
    // use @@ to keep a single @ sign.
    $line = preg_replace('/((\@)(\@)?)/', '$3', $line);
    $html_lines .= "<li class=\"tab$count_fours\">$line</li>";
}
echo $html_lines;
echo "</ol></div>";


The functions that follow are used to colour-code a list of keywords, defaulting to blue. The function onlyWholeWords() will only colour-code full-words, but it also excludes any that appear after // comment-delimiters. It could be extended to look for other delimiters, such as #, but it will quickly become complicated - especially if multi-line comments are to be parsed. So, instead, I took a simpler approach. Any (key)words that I do not wish to colour-blue I split by inserting an at-sign @ within the word. This @-sign will be removed. If, however, I wish to include the @-sign I can use @@.

The functions that do the colour-coding are these:

function onlyWholeWords(&$value, $key) {
    // Only whole (full) keywords should be coloured.
    // Ignores words after // comment delimiters.
    //$value = "/\b(" . $value . ")\b/";    // doesn't handle comments
    //$value = "/^(?:(/>/>/>?!\/\/).)*\K\b(" . $value . ")\b/"; 
    // \K lookbehind alternative is not supported in PHP < 5.2.4, so use:
    $value = "/^((?:(/>/>/>?!\/\/).)*)\b" . $value . "\b/";
}
function addSpan(&$value, $key, $color='blue') {
    // Each keyword is surrounded by a span, styled with $color.
    $value = "$1<span style='color:$color'>" . $value . "</span>";
}
function codeWords($code) {
    $keywords = array('as', 'break', 'case', 'class', 'continue', 'default', 
        'do', 'elif', 'else', 'elseif', 'for', 'foreach', 'function', 'if', 
        'new', 'null', 'return', 'self', 'switch', 'this', 'to', 'typeof', 
        'until', 'var', 'void', 'while', 'with');
    $keywords2 = $keywords;

    array_walk($keywords, 'onlyWholeWords');
    array_walk($keywords2, 'addSpan', 'blue');
    $code = preg_replace($keywords, $keywords2, $code);
    return $code;
}


These three functions work in combination to look for the keywords, surround these with spans with style='color:$color'. array_walk() is the important function that does the donkey-work. It applies a function to all the elements of an array, and allows an additional argument to be supplied.

It should be relatively straight-forward to add additional keywords and use different colours. I hope that this will prove useful to someone or, at least, interesting! Andy.

This post has been edited by andrewsw: 29 December 2012 - 02:30 PM


Is This A Good Question/Topic? 2
  • +

Replies To: Display Formatted Code

#2 creativecoding  Icon User is offline

  • Hash != Encryption
  • member icon


Reputation: 927
  • View blog
  • Posts: 3,209
  • Joined: 19-January 10

Posted 29 December 2012 - 10:09 PM

This is great for a professional solution. Nice tutorial too. However if you want a quick and easy solution, you can use highlight_string or highlight_file and PHP will take care of it for you. No need for extra work if only your teacher is going to see it.
Was This Post Helpful? 0
  • +
  • -

#3 andrewsw  Icon User is online

  • It's just been revoked!
  • member icon

Reputation: 3617
  • View blog
  • Posts: 12,456
  • Joined: 12-December 12

Posted 30 December 2012 - 06:37 AM

View Postcreativecoding, on 29 December 2012 - 10:09 PM, said:

This is great for a professional solution. Nice tutorial too. However if you want a quick and easy solution, you can use highlight_string or highlight_file and PHP will take care of it for you. No need for extra work if only your teacher is going to see it.


Thank you.
highlight_string and highlight_file are intended for PHP code, although their display will probably be acceptable with other, similar, languages. (My screenshot is JS.)

This post has been edited by andrewsw: 30 December 2012 - 06:38 AM

Was This Post Helpful? 0
  • +
  • -

#4 DoxramosPS  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 174
  • Joined: 07-October 12

Posted 29 March 2013 - 10:07 PM

Hey Andrew; Great little bit of code here. I was just wondering; is there any way to make it compatible with file contents? I attempted to simply be modifying it just a little bit.
<?php
echo "<div class=\"blogcode shadow\">";
echo "<ol start=\"1\">";
$html_lines = '';
// get rid of newlines; each separate line will be inserted into an LI
$file1="test.txt";
if (file_exists($file1)) 
{
$file = fopen("test.txt", "r");
 while (!feof($file)) 
 {
  $code_lines = fgets($file, filesize("test.txt"));
 }

foreach ($code_lines as $line) {
    $count_fours = strlen($line) - strlen(ltrim($line, ' '));
    // how many mutiples of four-spaces (to the left) are there?
    $count_fours = ceil($count_fours / 4);
    $line = ltrim($line);
    $line = codeWords($line);       // blue keywords
    // replace any remaining two-spaces with nbsp
    $line = str_replace('  ', '&nbsp;', $line);
    // Use @ to break-up keywords that shouldn't be colour-coded;
    // use @@ to keep a single @ sign.
    $line = preg_replace('/((\@)(\@)?)/', '$3', $line);
    $html_lines .= "<li class=\"tab$count_fours\">$line</li>";
}
echo $html_lines;
echo "</ol></div>";
?>


I was hoping to see it working, but it decided it would be more fun to give me a 500 internal server error. :)
Was This Post Helpful? 0
  • +
  • -

#5 andrewsw  Icon User is online

  • It's just been revoked!
  • member icon

Reputation: 3617
  • View blog
  • Posts: 12,456
  • Joined: 12-December 12

Posted 30 March 2013 - 02:09 AM

Hello. Yes. The first problem is that DIC has put extra /> symbols in my definition for onlyWholeWords() which I cannot edit.

Your code is missing a final closing bracket } and its current use of fgets() would only retrieve a single line. The full code-page below uses file_get_contents() to get the full file-content, and then explode() to split it into lines.

<?php
function onlyWholeWords(&$value, $key) {
    // Ignores words after // comment delimiters.
    //$value = "/\b(" . $value . ")\b/";    // doesn't handle comments
    //$value = "/^(?:(?!\/\/).)*\K\b(" . $value . ")\b/"; 
    // \K lookbehind alternative is not supported in PHP < 5.2.4, so use:
    $value = "/^((?:(?!\/\/).)*)\b" . $value . "\b/";
}
function addSpan(&$value, $key, $color='blue') {
    // Each keyword is surrounded by a span, styled with $color.
    $value = "$1<span style='color:$color'>" . $value . "</span>";
}
function codeWords($code) {
    $keywords = array('as', 'break', 'case', 'class', 'continue', 'default', 
        'do', 'elif', 'else', 'elseif', 'for', 'foreach', 'function', 'if', 
        'new', 'null', 'return', 'self', 'switch', 'this', 'to', 'typeof', 
        'until', 'var', 'void', 'while', 'with');
    $keywords2 = $keywords;

    array_walk($keywords, 'onlyWholeWords');
    array_walk($keywords2, 'addSpan', 'blue');
    $code = preg_replace($keywords, $keywords2, $code);
    return $code;
}
?>

<!DOCTYPE html>
<html lang="en-GB">
<head>
    <meta charset="utf-8">
    <meta name="keywords" content="key, words">
    <meta name="description" content="description">
    <style type="text/css">
.shadow {
     -moz-box-shadow: 5px 5px 5px 0px #CCC;
     -webkit-box-shadow: 5px 5px 5px 0px #CCC;
     box-shadow: 5px 5px 5px 0px #CCC;
}

.blogcode {
    margin: 10px 5px 20px 5px; padding: 0 0 0 8px;
    background-color: #F6F3F3;
    font-family: Consolas, 'Courier New', monospace;
    font-size: smaller; color: green;
}
.blogcode ol {
    list-style-position: outside;
    margin: 0; padding: 0 0 0 30px;
}
.blogcode li {
    padding: 3px 5px; margin: 0;
    border-left: thin solid green;
}
.blogcode ol li:nth-child(odd) { background: white; }

.blogcode li.tab0 { padding-left: 5px; }
.blogcode li.tab1 { padding-left: 35px; }
.blogcode li.tab2 { padding-left: 65px; }
.blogcode li.tab3 { padding-left: 95px; }
.blogcode li.tab4 { padding-left: 125px; }
.blogcode li.tab5 { padding-left: 155px; }
.blogcode li.tab6 { padding-left: 185px; }
.blogcode li.tab7 { padding-left: 215px; }
.blogcode li.tab8 { padding-left: 245px; }
.blogcode li.tab9 { padding-left: 275px; }

    </style>
</head>
<body>
<?php
echo "<div class=\"blogcode shadow\">";
echo "<ol start=\"1\">";
$html_lines = '';
// get rid of newlines; each separate line will be inserted into an LI
$file1="test.txt";
if (file_exists($file1)) {
    /*$file = fopen("test.txt", "r");
     while (!feof($file)) 
     {
      $code_lines = fgets($file, filesize("test.txt"));
     }*/
     $file = file_get_contents($file1);
     $code_lines = explode("\n", $file);

    foreach ($code_lines as $line) {
        $count_fours = strlen($line) - strlen(ltrim($line, ' '));
        // how many mutiples of four-spaces (to the left) are there?
        $count_fours = ceil($count_fours / 4);
        $line = ltrim($line);
        $line = codeWords($line);       // blue keywords
        // replace any remaining two-spaces with nbsp
        $line = str_replace('  ', '&nbsp;', $line);
        // Use @ to break-up keywords that shouldn't be colour-coded;
        // use @@ to keep a single @ sign.
        $line = preg_replace('/((\@)(\@)?)/', '$3', $line);
        $html_lines .= "<li class=\"tab$count_fours\">$line</li>";
    }
    echo $html_lines;
    echo "</ol></div>";
}
?>
</body>
</html>

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1