177 lines
4.1 KiB
Perl
177 lines
4.1 KiB
Perl
#!/usr/bin/perl
|
|
package IkiWiki::Plugin::highlight;
|
|
|
|
use warnings;
|
|
use strict;
|
|
use IkiWiki 3.00;
|
|
use Encode;
|
|
|
|
sub import {
|
|
hook(type => "getsetup", id => "highlight", call => \&getsetup);
|
|
hook(type => "checkconfig", id => "highlight", call => \&checkconfig);
|
|
# this hook is used by the format plugin
|
|
hook(type => "htmlizeformat", id => "highlight",
|
|
call => \&htmlizeformat, last => 1);
|
|
}
|
|
|
|
sub getsetup () {
|
|
return
|
|
plugin => {
|
|
safe => 1,
|
|
rebuild => 1, # format plugin
|
|
section => "format",
|
|
},
|
|
tohighlight => {
|
|
type => "string",
|
|
example => ".c .h .cpp .pl .py Makefile:make",
|
|
description => "types of source files to syntax highlight",
|
|
safe => 1,
|
|
rebuild => 1,
|
|
},
|
|
filetypes_conf => {
|
|
type => "string",
|
|
example => "/etc/highlight/filetypes.conf",
|
|
description => "location of highlight's filetypes.conf",
|
|
safe => 0,
|
|
rebuild => undef,
|
|
},
|
|
langdefdir => {
|
|
type => "string",
|
|
example => "/usr/share/highlight/langDefs",
|
|
description => "location of highlight's langDefs directory",
|
|
safe => 0,
|
|
rebuild => undef,
|
|
},
|
|
}
|
|
|
|
sub checkconfig () {
|
|
if (! exists $config{filetypes_conf}) {
|
|
$config{filetypes_conf}="/etc/highlight/filetypes.conf";
|
|
}
|
|
if (! exists $config{langdefdir}) {
|
|
$config{langdefdir}="/usr/share/highlight/langDefs";
|
|
}
|
|
if (exists $config{tohighlight}) {
|
|
foreach my $file (split ' ', $config{tohighlight}) {
|
|
my @opts = $file=~s/^\.// ?
|
|
(keepextension => 1) :
|
|
(noextension => 1);
|
|
my $ext = $file=~s/:(.*)// ? $1 : $file;
|
|
|
|
my $langfile=ext2langfile($ext);
|
|
if (! defined $langfile) {
|
|
error(sprintf(gettext(
|
|
"tohighlight contains unknown file type '%s'"),
|
|
$ext));
|
|
}
|
|
|
|
hook(
|
|
type => "htmlize",
|
|
id => $file,
|
|
call => sub {
|
|
my %params=@_;
|
|
highlight($langfile, $params{content});
|
|
},
|
|
longname => sprintf(gettext("Source code: %s"), $file),
|
|
@opts,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
sub htmlizeformat {
|
|
my $format=lc shift;
|
|
my $langfile=ext2langfile($format);
|
|
|
|
if (! defined $langfile) {
|
|
return;
|
|
}
|
|
|
|
return Encode::decode_utf8(highlight($langfile, shift));
|
|
}
|
|
|
|
my %ext2lang;
|
|
my $filetypes_read=0;
|
|
my %highlighters;
|
|
|
|
# Parse highlight's config file to get extension => language mappings.
|
|
sub read_filetypes () {
|
|
open (my $f, $config{filetypes_conf}) || error("$config{filetypes_conf}: $!");
|
|
local $/=undef;
|
|
my $config=<$f>;
|
|
close $f;
|
|
|
|
# highlight >= 3.2 format (bind-style)
|
|
while ($config=~m/Lang\s*=\s*\"([^"]+)\"[,\s]+Extensions\s*=\s*{([^}]+)}/sg) {
|
|
my $lang=$1;
|
|
foreach my $bit (split ',', $2) {
|
|
$bit=~s/.*"(.*)".*/$1/s;
|
|
$ext2lang{$bit}=$lang;
|
|
}
|
|
}
|
|
|
|
# highlight < 3.2 format
|
|
if (! keys %ext2lang) {
|
|
foreach (split("\n", $config)) {
|
|
if (/^\$ext\((.*)\)=(.*)$/) {
|
|
$ext2lang{$_}=$1 foreach $1, split ' ', $2;
|
|
}
|
|
}
|
|
}
|
|
|
|
$filetypes_read=1;
|
|
}
|
|
|
|
|
|
# Given a filename extension, determines the language definition to
|
|
# use to highlight it.
|
|
sub ext2langfile ($) {
|
|
my $ext=shift;
|
|
|
|
my $langfile="$config{langdefdir}/$ext.lang";
|
|
return $langfile if exists $highlighters{$langfile};
|
|
|
|
read_filetypes() unless $filetypes_read;
|
|
if (exists $ext2lang{$ext}) {
|
|
return "$config{langdefdir}/$ext2lang{$ext}.lang";
|
|
}
|
|
# If a language only has one common extension, it will not
|
|
# be listed in filetypes, so check the langfile.
|
|
elsif (-e $langfile) {
|
|
return $langfile;
|
|
}
|
|
else {
|
|
return undef;
|
|
}
|
|
}
|
|
|
|
# Interface to the highlight C library.
|
|
sub highlight ($$) {
|
|
my $langfile=shift;
|
|
my $input=shift;
|
|
|
|
eval q{use highlight};
|
|
if ($@) {
|
|
print STDERR gettext("warning: highlight perl module not available; falling back to pass through");
|
|
return $input;
|
|
}
|
|
|
|
my $gen;
|
|
if (! exists $highlighters{$langfile}) {
|
|
$gen = highlightc::CodeGenerator_getInstance($highlightc::XHTML);
|
|
$gen->setFragmentCode(1); # generate html fragment
|
|
$gen->setHTMLEnclosePreTag(1); # include stylish <pre>
|
|
$gen->initTheme("/dev/null"); # theme is not needed because CSS is not emitted
|
|
$gen->initLanguage($langfile); # must come after initTheme
|
|
$gen->setEncoding("utf-8");
|
|
$highlighters{$langfile}=$gen;
|
|
}
|
|
else {
|
|
$gen=$highlighters{$langfile};
|
|
}
|
|
|
|
return $gen->generateString($input);
|
|
}
|
|
|
|
1
|