Wiki source for HighlighterAction


Show raw source

=====Generating an Overview of Available Syntax Highlighters=====

>>Other action development pages:{{category page="CategoryDevelopmentActions" compact="1"}}>>===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 [[http://qbnz.com/highlighter/ 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!
~&Actually, I just realized that a table isn't really the best way to present this information - a definition list is structurally more appropriate. I'll create a new version soon. This will be a candidate for inclusion in the next version after 1.1.6.0. --JavaWoman

==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==
""<img align="left" hspace="5" src="http://www.xs4all.nl/~iamback/tests/highlighter_action.png" alt="Output of {{highlighter}} action" width="292" height="872" />"" 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.
~&In version 1.1.6.0 (soon now...) the "built-in" Wikka highlighters will have a proper description as well. --JavaWoman
::c::
===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)
<?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==
%%(php)/**
* Plain text language file for Wikka highlighting (or unknown language).
*/
%%
==/formatters/email.php==
%%(php)/**
* Email quoting file for Wikka highlighting.
*/
%%
==/formatters/ini.hp==
%%(php)/**
* INI language file for Wikka highlighting (configuration file).
*/
%%
==/formatters/php.php==
%%(php)/**
* PHP language file for Wikka highlighting (uses PHP built-in highlighting).
*/
%%

""<img align="left" hspace="5" src="http://www.xs4all.nl/~iamback/tests/highlighter_action_wikka.png" alt="Output of {{highlighter}} action" width="290" height="137" />"" Here's a screenshot of the second part of the action output when these documentation blocks are added to the Wikka language files.::c::


===Comments?===
Comments and suggestions are welcome, as always.

~& it is definitely better when the code is self-documenting, although this means my work on writing the table was useless in the end :-) --NilsLindenberg
~~&Nils, actually your work (and JsnX's work in SyntaxHighlighter) was **very** useful because it gave me the idea for writing this action. :) And, it will eliminate future work when highlighters are updated or extended. --JavaWoman
~~~&Thanx. While you are mentioning the word update: have you read the authors announcements about the 1.2 version? I don't know how much his huge changes in the structure will affect the things you are doing now? And has someone written him that we will use geshi? Would be fair. --NilsLindenberg
~~~~&Yes, I know "oracle" is working on a 1.2 version but I don't expect that to have a huge impact on either integration with Wikka (if done as I proposed in WikkaGeSHiIntegration) or on this little documentation action (I expect the //layout// of the documentation blocks in the language files to stay at least standardized and probably not change at all - as long as the format is standardized an RE can pull out the description).
~~~~&Also, yes, we should inform the author that Wikka is using his code - but not until 1.1.6.0 is released with [[http://qbnz.com/highlighter/ GeSHi]] bundled, IMO.
~~~~&--JavaWoman

~&The only problem that I see is that if this is supposed to be a way to automatically output some kind of Wikka documentation, then the [[IncludeRemote FetchRemote]] plugin - which cannot read out action-generated content - won't display the list of available formatters on fetched pages -- DarTar
~~&It's intended to list information about the **locally installed** highlighters - end user documentation, in other words. That means a WikiAdmin (or any user) could simply add it to any page so users will have a lookup list of what they can use in their code blocks. //But// if it's part of a documentation page on this (a) central Wikka installation, preceded/followed by explanatory text, and this page would be retrieved via [[IncludeRemote FetchRemote]], you'd get the **same** explanatory text with the list of **locally installed** highlighters - wich is exactly what is intended: after all, a list of what's installed on the remote system does not help the user in using syntax highlighting in code blocks on the local system! --JavaWoman.
~~~&Ok, good point. Hadn't thought about this -- DarTar
~~&BTW, the planned action to [[DescribeActions retrieve action documentation]] based on what's installed and embedded documentation blocks should work the same way; I can model it after this one. --JW

----
CategoryDevelopmentActions
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki