
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





MultiQuote






|