<?php
/*
Plugin Name: Illudium PU-36 Explosive Codeolulator
Version: 1.0.2
Plugin URI: http://rephrase.net/box/word/codeolulator/
Description: Converts <pre><code> blocks into pretty ordered lists
Author: Sam Angove
Author URI: http://rephrase.net/
*/
/*
Changelog:
1.0.2:
* wrap in a class
* use proper wp query methods
* look for code.php in templates
1.0.1:
* rewrite rules generated better
* don't add "view/download" link for really short code blocks
* code without a number means show all code snippets
Credits:
As far as I know, the original idea was Simon Willison's:
<http://simon.incutio.com/archive/2002/07/10/numberedCodeListing>
Part of this plugin's code -- an irritatingly small amount, actually; just
the stuff for counting whitespace. I'd have had to reinvent the wheel less
if I'd found it earlier -- was taken straight from Aaron Schaefer's Code Viewer.
If you want code samples kept in a separate location, use that instead.
<http://elasticdog.com/2004/09/code-viewer/>
*/
/******
Options
******/
/* Show a "View/Download" link to plaintext version? */
$codeolulator['show_download_link'] = true;
/* Code snippets less than this many lines long will not
get a "View/Download" link attached to them. */
$codeolulator['download_link_minimum_length'] = 4;
/* How many spaces makes one tab in your code samples? */
$codeolulator['tab_length'] = 4;
/* "View/Download" link.
Is passed through sprintf(), with %s replaced by the link. */
$codeolulator['download_link_text'] = '<a href="%s">View/Download</a>';
class Codeolulator {
function register_query_var($vars) {
$vars[] = 'code';
return $vars;
}
function post_filter($text) {
$code = get_query_var('code');
if (empty($code) && strpos($text, '<pre>') !== false) {
$text = preg_replace_callback("#<pre>\\s*<code>(.*?)</code>\\s*</pre>#ms", array('Codeolulator', 'post_filter_callback'), $text);
}
return $text;
}
function post_filter_callback($matches) {
global $codeolulator;
static $code_snippet_number = 0;
$code_snippet_number++;
$list = '<ol class="codelist">';
$lines = preg_split("#\n(?!\\z)#", $matches[1]);
foreach ($lines as $number => $line) {
$type = ($number % 2 == 1) ? 'even' : 'odd';
// convert spaces to tabs
$line = str_replace(str_repeat(' ', $codeolulator['tab_length']), "\t", $line);
// If the line is blank, insert a space to prevent collapsing,
// otherwise insert the line.
if (ltrim($line) == "") {
$list .= "\t" . '<li class="' . $type . '"> </li>' . "\n";
} else {
$numtabs = strlen($line) - strlen(ltrim($line)); // determine the number of tabs
$line = trim($line); // trim leading/trailing whitespace
$list .= "\t" . '<li class="tab' . $numtabs . ' ' . $type . '"><code>' . $line . '</code></li>' . "\n";
}
}
$list .= "</ol>\n";
if ($codeolulator['show_download_link'] && count($lines) > $codeolulator['download_link_minimum_length']) {
$link = get_permalink();
if (false === strpos($link, '?'))
$link = trailingslashit($link) . 'code/' . $code_snippet_number;
else
$link .= '&code=' . $code_snippet_number;
$list .= '<div class="sourcelink">' . sprintf($codeolulator['download_link_text'], $link) . "</div>\n";
}
$list = apply_filters('codeolulator_list', $list);
return $list;
}
function show_code_snippets() {
$code = get_query_var('code');
if (!empty($code)) {
if ( file_exists( TEMPLATEPATH . '/code.php') ) {
load_template( TEMPLATEPATH . '/code.php');
exit;
}
@header('Content-type: text/plain; charset=utf-8');
$snippets = array();
// This is overly elaborate for single posts, but I figured I might as well
// make it support multiple posts from the start.
if (have_posts()) :
while (have_posts()) : the_post();
ob_start();
the_content();
$content = ob_get_contents();
ob_end_clean();
preg_match_all("#<pre>\\s*<code>(.*?)</code>\\s*</pre>#s", html_entity_decode($content), $matches, PREG_PATTERN_ORDER);
if (isset($matches[1])) $snippets = array_merge($snippets, $matches[1]);
endwhile;
endif;
if ($code == 0)
// don't use implode, sometimes there's only one
foreach ($snippets as $snippet) {
echo "$snippet\n\n";
}
else
echo $snippets[$code-1];
exit;
}
}
function generate_rewrite($wp_rewrite) {
// (?:code/)?(code/?|\d+) doesn't work on apache 1.3?
// Make the regex stupid.
$wp_rewrite->add_rewrite_tag('%code%', 'code/([0-9]+)', "code=");
$structure = trailingslashit($wp_rewrite->permalink_structure) . "%code%";
$rules = $wp_rewrite->generate_rewrite_rule($structure);
foreach ($rules as $match => $redirect) {
$match = str_replace(array('(/[0-9]+)?/?$', '/trackback/?$'), '$', $match);
$redirect = preg_replace(array("#&tb=1#", "#&page=.[0-9]+#"), '', $redirect);
$newrules[$match] = $redirect;
}
$wp_rewrite->rules += $newrules;
}
}
add_action('generate_rewrite_rules', array('Codeolulator', 'generate_rewrite'));
add_action('template_redirect', array('Codeolulator', 'show_code_snippets'));
add_filter('query_vars', array('Codeolulator', 'register_query_var'));
add_filter('the_content', array('Codeolulator', 'post_filter'), 9);
?>