]> sipb.mit.edu Git - ikiwiki.git/blob - IkiWiki/Plugin/highlight.pm
add a missing chomp
[ikiwiki.git] / IkiWiki / Plugin / highlight.pm
1 #!/usr/bin/perl
2 package IkiWiki::Plugin::highlight;
3
4 use warnings;
5 use strict;
6 use IkiWiki 3.00;
7 use Encode;
8
9 sub import {
10         hook(type => "getsetup", id => "highlight",  call => \&getsetup);
11         hook(type => "checkconfig", id => "highlight", call => \&checkconfig);
12         # this hook is used by the format plugin
13         hook(type => "htmlizefallback", id => "highlight", call =>
14                 \&htmlizefallback);
15 }
16
17 sub getsetup () {
18         return
19                 plugin => {
20                         safe => 1,
21                         rebuild => 1, # format plugin
22                         section => "format",
23                 },
24                 tohighlight => {
25                         type => "string",
26                         example => ".c .h .cpp .pl .py Makefile:make",
27                         description => "types of source files to syntax highlight",
28                         safe => 1,
29                         rebuild => 1,
30                 },
31                 filetypes_conf => {
32                         type => "string",
33                         example => "/etc/highlight/filetypes.conf",
34                         description => "location of highlight's filetypes.conf",
35                         safe => 0,
36                         rebuild => undef,
37                 },
38                 langdefdir => {
39                         type => "string",
40                         example => "/usr/share/highlight/langDefs",
41                         description => "location of highlight's langDefs directory",
42                         safe => 0,
43                         rebuild => undef,
44                 },
45 }
46
47 sub checkconfig () {
48         if (! exists $config{filetypes_conf}) {
49                 $config{filetypes_conf}="/etc/highlight/filetypes.conf";
50         }
51         if (! exists $config{langdefdir}) {
52                 $config{langdefdir}="/usr/share/highlight/langDefs";
53         }
54         if (exists $config{tohighlight}) {
55                 foreach my $file (split ' ', $config{tohighlight}) {
56                         my @opts = $file=~s/^\.// ?
57                                 (keepextension => 1) :
58                                 (noextension => 1);
59                         my $ext = $file=~s/:(.*)// ? $1 : $file;
60                 
61                         my $langfile=ext2langfile($ext);
62                         if (! defined $langfile) {
63                                 error(sprintf(gettext(
64                                         "tohighlight contains unknown file type '%s'"),
65                                         $ext));
66                         }
67         
68                         hook(
69                                 type => "htmlize",
70                                 id => $file,
71                                 call => sub {
72                                         my %params=@_;
73                                         highlight($langfile, $params{content});
74                                 },
75                                 longname => sprintf(gettext("Source code: %s"), $file),
76                                 @opts,
77                         );
78                 }
79         }
80 }
81
82 sub htmlizefallback {
83         my $format=lc shift;
84         my $langfile=ext2langfile($format);
85
86         if (! defined $langfile) {
87                 return;
88         }
89
90         return Encode::decode_utf8(highlight($langfile, shift));
91 }
92
93 my %ext2lang;
94 my $filetypes_read=0;
95 my %highlighters;
96
97 # Parse highlight's config file to get extension => language mappings.
98 sub read_filetypes () {
99         open (IN, $config{filetypes_conf}) || error("$config{filetypes_conf}: $!");
100         while (<IN>) {
101                 chomp;
102                 if (/^\$ext\((.*)\)=(.*)$/) {
103                         $ext2lang{$_}=$1 foreach $1, split ' ', $2;
104                 }
105         }
106         close IN;
107         $filetypes_read=1;
108 }
109
110
111 # Given a filename extension, determines the language definition to
112 # use to highlight it.
113 sub ext2langfile ($) {
114         my $ext=shift;
115
116         my $langfile="$config{langdefdir}/$ext.lang";
117         return $langfile if exists $highlighters{$langfile};
118
119         read_filetypes() unless $filetypes_read;
120         if (exists $ext2lang{$ext}) {
121                 return "$config{langdefdir}/$ext2lang{$ext}.lang";
122         }
123         # If a language only has one common extension, it will not
124         # be listed in filetypes, so check the langfile.
125         elsif (-e $langfile) {
126                 return $langfile;
127         }
128         else {
129                 return undef;
130         }
131 }
132
133 # Interface to the highlight C library.
134 sub highlight ($$) {
135         my $langfile=shift;
136         my $input=shift;
137
138         eval q{use highlight};
139         if ($@) {
140                 print STDERR gettext("warning: highlight perl module not available; falling back to pass through");
141                 return $input;
142         }
143
144         my $gen;
145         if (! exists $highlighters{$langfile}) {
146                 $gen = highlightc::CodeGenerator_getInstance($highlightc::XHTML);
147                 $gen->setFragmentCode(1); # generate html fragment
148                 $gen->setHTMLEnclosePreTag(1); # include stylish <pre>
149                 $gen->initTheme("/dev/null"); # theme is not needed because CSS is not emitted
150                 $gen->initLanguage($langfile); # must come after initTheme
151                 $gen->setEncoding("utf-8");
152                 $highlighters{$langfile}=$gen;
153         }
154         else {          
155                 $gen=$highlighters{$langfile};
156         }
157
158         return $gen->generateString($input);
159 }
160
161 1