Generating an Overview of Available Syntax Highlighters


Other action development pages:The following 46 page(s) belong to CategoryDevelopmentActions

The problem

In various places here I've seen some overviews of which syntax highlighters are available in Wikka - first the built-in Wikka highlighters, and now a bunch of languages via integration of GeSHi. Of course, it's quite tedious to create such a list, and even more tedious to keep it up-to-date when new langauge files become available.

The solution

The solution is, what else, an action that automatically finds the available language files and produces a nice table with the result. Well, here it is!
Hint
If you want to copy this code, do not copy it from the highlighted code, but go into edit mode and copy from the page source: only that way will you get properly formatted code with tabs instead of loads of spaces...

Screen shot
Output of {{highlighter}} action Here's a screen shot of the output it produces now.

Note that there are no descriptions for the "built-in" Wikka highlighters; that's because they don't have a standardized documentation block yet - once this is added the action can pull out their descriptions, too.
 

The code

Naturally, this action assumes that the paths where the GeSHi and Wikka language parser files are located are defined in the configuration file (see also WikkaGeSHiIntegration). However, this can be overridden by specifying an alternative path in the action - this would be useful for an "experimental" installation that may have extra or fewer language files available, allowing the action to retrieve the files from a "release" version.
Save as /actions/highlighter.php:
<?php
/**
 * Lists available language parsers, both GeSHi and (internal) Wikka parsers.
 *
 * This action goes through the directories containing the GeSHi language parsers and Wikka
 * language parsers and constructs a table containing language name (to be used in code blocks)
 * and a "human-readable" description parsed from the documentation header of the file.
 *
 * @package     Actions
 * @subpackage  Documentation
 * @name        HighLighters
 *
 * @author      {@link http://wikka.jsnx.com/JavaWoman JavaWoman}
 * @copyright   Copyright © 2004, Marjolein Katsma
 * @license     http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
 * @version     1.0
 *
 * @input       string $geshipath - optional: alternate location of GeSHi language files
 * @input       string $wikkapath - optional: alternate location of Wikka language files
 * @output      tables with language code and description for each language parser found
 */


/**#@+
 * Defines for UI internationalization
 */

define('ERR_DIR', "Sorry, the directory %s could not be opened - please check the configuration.")# dir path
define('ERR_PATH', "Could not open %s");                                                            # file path
define('TABLE_HDR1', "language code");
define('TABLE_HDR2', "description");
define('TABLE_SUM', "%1\$s Parsers: %2\$s, %3\$s");                                                 # app, TABLE_HDR1, TABLE_HDR2
define('TABLE_CAP', "%s language parsers");                                                         # app
/**#@-*/
/**#@+
 * Patterns (regular expressions) to find language descriptions in the files
 */

define('PATTERN_GESHI_LANGDESC', '\* ((\w[^\n]*?)( language)??) file for GeSHi(.*?)\.');
define('PATTERN_WIKKA_LANGDESC', '\* ((\w[^\n]*?)( language)??) file for Wikka highlighting(.*?)\.');   # @@@ no documentation yet
/**#@-*/

/**
 * Displays data for all language parsers in a given directory.
 *
 * Given a directory and an array with the names of the language files in that directory,
 * this function parses teh language descriptor from each file, and builds a table with
 * language code and description side by side.
 *
 * @access      private
 * @param       string  $dir  required: location of language parser files
 * @param       array   $aLangs  required: language codes (corresponding to file names)
 * @param       string  $app  required: highlighter app using these files
 * @return      string  table with language parser data
 */

function GetParsers($dir,$aLangs,$app)
{
    // sort by language code
    asort($aLangs);
    // collect parser data
    $count = count($aLangs);
    for ($i=0; $i < $count; $i++)
    {
        $filestart = '';
        $path = $dir.'/'.$aLangs[$i].'.php';
        if ($fh = @fopen($path, 'rb'))
        {
            $filestart = fread($fh, 1024);
            fclose($fh);
        }
        else
        {
            $mess = '<p class="error">'.sprintf(ERR_PATH,$path).'</p>'."\n";
            trigger_error($mess, E_USER_WARNING);
            echo '<br />';
        }
        switch ($app)
        {
            case 'GeSHi':
                $pattern = '/'.PATTERN_GESHI_LANGDESC.'/s';
                break;
            case 'Wikka':
                $pattern = '/'.PATTERN_WIKKA_LANGDESC.'/s';
                break;
            default:
                $pattern = '';
        }
        preg_match($pattern, $filestart, $matches);
        $aParsers[$i]['code'] = $aLangs[$i];
        $aParsers[$i]['desc'] = $matches[2];
        if (isset($matches[4])) $aParsers[$i]['desc'] .= ' '.trim($matches[4]);
    }

    // build output table
    $count = count($aParsers);
    $id = strtolower($app).'languages';
    $table  = '<table cellspacing="1" cellpadding="2" border="1" id="'.$id.'" summary="'.sprintf(TABLE_SUM,$app,TABLE_HDR1, TABLE_HDR2).'">'."\n";
    $table .= '<caption style="font-weight: bold;">'.sprintf(TABLE_CAP,$app).'</caption>'."\n";
    $table .= '<thead>'."\n";
    $table .= '<tr><th scope="col">'.TABLE_HDR1.'</th><th scope="col">'.TABLE_HDR2.'</th>'."\n";
    $table .= '</thead>'."\n";
    $table .= '<tbody>'."\n";
    for ($i=0; $i < $count; $i++)
    {
        $table .= '<tr><td>'.$aParsers[$i]['code'].'</td><td>'.$aParsers[$i]['desc'].'</td></tr>'."\n";
    }
    $table .= '</tbody>'."\n";
    $table .= '</table><br />'."\n";

    //return result
    return $table;
}

// set defaults
$geshipath = $this->config['geshi_lang_path'];
$wikkapath = $this->config['wikka_lang_path'];

// get and interpret action parameters (override config values)
if (is_array($vars))
{
    foreach ($vars as $param => $value)
    {
        switch ($param)
        {
            case 'geshipath':
                if (file_exists($value) && is_dir($value)) $geshipath = $value;
                break;
            case 'wikkapath':
                if (file_exists($value) && is_dir($value)) $wikkapath = $value;
                break;
            default:
                // ignore all other parameters
                break;
        }
    }
}


// open GeSHi dir and retrieve file names
if ($geshidir = ($dh = @opendir($geshipath)))
#if ($geshidir = ($dh = @opendir('dummy')))                             # @@@ TEST error handling
{
    while (false !== ($file = readdir($dh)))
    {
        if ($file != basename($file, '.php'))
        {
            $aGeshiLangs[] = basename($file, '.php');
        }
    }
    closedir($dh);
}
else
{
    $mess = '<span class="error">'.sprintf(ERR_DIR,$this->config['geshi_lang_path']).'</span>'."\n";
    trigger_error($mess, E_USER_WARNING);
    echo '<br />';
}
// open Wikka dir and retrieve file names
if ($wikkadir = ($dh = @opendir($wikkapath)))
{
    while (false !== ($file = readdir($dh)))
    {
        if ($file != ($name = basename($file, '.php')))
        {
            if ('wakka' != $name) $aWikkaLangs[] = $name;
        }
    }
    closedir($dh);
}
else
{
    $mess = '<span class="error">'.sprintf(ERR_DIR,$this->config['wikka_lang_path']).'</span>'."\n";
    trigger_error($mess, E_USER_WARNING);
    echo '<br />';
}

if (FALSE !== $geshidir) echo getParsers($geshipath,$aGeshiLangs,'GeSHi');
if (FALSE !== $wikkadir) echo getParsers($wikkapath,$aWikkaLangs,'Wikka');
?>


Documenting the Wikka language parsers

By adding a small documentation block to each of the Wikka language parsers with a (language) description in a standardized format, the {{highlighter}} action can retrieve descriptions for these as well. Listing just the documentation blocks below:
/formatters/code.php
/**
 * Plain text language file for Wikka highlighting (or unknown language).
 */

/formatters/email.php
/**
 * Email quoting file for Wikka highlighting.
 */

/formatters/ini.hp
/**
 * INI language file for Wikka highlighting (configuration file).
 */

/formatters/php.php
/**
 * PHP language file for Wikka highlighting (uses PHP built-in highlighting).
 */


Output of {{highlighter}} action Here's a screenshot of the second part of the action output when these documentation blocks are added to the Wikka language files.
 



Comments?

Comments and suggestions are welcome, as always.


CategoryDevelopmentActions
There are no comments on this page.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki