]> sipb.mit.edu Git - ikiwiki.git/blob - doc/todo/automatic_use_of_syntax_plugin_on_source_code_files/discussion.mdwn
2fad9f19aedbc4112bc67bd259ba816811e65a56
[ikiwiki.git] / doc / todo / automatic_use_of_syntax_plugin_on_source_code_files / discussion.mdwn
1 Here is another [[patch]] for this.  It is more up to date than either of the patches linked on the previous page.  It is most similar to [[plugins/contrib/sourcehighlight]].
2
3 Note that if this is being used with `c` or `c++` then you'll probably want to wait until [[bugs/multiple_pages_with_same_name]] is fixed.
4
5 -- [[Will]]
6
7 ----
8
9     #!/usr/bin/perl
10     # markup source files
11     package IkiWiki::Plugin::sourcecode;
12     
13     use warnings;
14     use strict;
15     use IkiWiki 2.00;
16     use open qw{:utf8 :std};
17     
18     my %metaheaders;
19     
20     sub import { #{{{
21         hook(type => "getsetup", id => "sourcecode", call => \&getsetup);
22         hook(type => "checkconfig", id => "sourcecode", call => \&checkconfig);
23         hook(type => "pagetemplate", id => "sourcecode", call => \&pagetemplate);
24     } # }}}
25     
26     sub getsetup () { #{{{
27         return 
28                 plugin => {
29                         safe => 1,
30                         rebuild => 1, # format plugin
31                 },
32                 sourcecode_command => {
33                         type => "string",
34                         example => "/usr/bin/source-highlight",
35                         description => "The command to execute to run source-highlight",
36                         safe => 0,
37                         rebuild => 1,
38                 },
39                 sourcecode_lang => {
40                         type => "string",
41                         example => "c,cpp,h,java",
42                         description => "Comma separated list of suffixes to recognise as source code",
43                         safe => 1,
44                         rebuild => 1,
45                 },
46                 sourcecode_linenumbers => {
47                         type => "boolean",
48                         example => 1,
49                         description => "Should we add line numbers to the source code",
50                         safe => 1,
51                         rebuild => 1,
52                 },
53                 sourcecode_css => {
54                         type => "string",
55                         example => "sourcecode_style",
56                         description => "page to use as css file for source",
57                         safe => 1,
58                         rebuild => 1,
59                 },
60     } #}}}
61     
62     sub checkconfig () { #{{{
63         if (! $config{sourcecode_lang}) {
64                 error("The sourcecode plugin requires a list of suffixes in the 'sourcecode_lang' config option");
65         }
66         
67         if (! $config{sourcecode_command}) {
68                 $config{sourcecode_command} = "source-highlight";
69         }
70         
71         if (! length `which $config{sourcecode_command} 2>/dev/null`) {
72                 error("The sourcecode plugin is unable to find the $config{sourcecode_command} command");
73         }
74     
75         if (! $config{sourcecode_css}) {
76                 $config{sourcecode_css} = "sourcecode_style";
77         }
78         
79         if (! defined $config{sourcecode_linenumbers}) {
80                 $config{sourcecode_linenumbers} = 1;
81         }
82         
83         my %langs = ();
84         
85         open(LANGS, "$config{sourcecode_command} --lang-list|");
86         while (<LANGS>) {
87                 if ($_ =~ /(\w+) = .+\.lang/) {
88                         $langs{$1} = 1;
89                 }
90         }
91         close(LANGS);
92         
93         foreach my $lang (split(/[, ]+/, $config{sourcecode_lang})) {
94                 if ($langs{$lang}) {
95                         hook(type => "htmlize", id => $lang, call => \&htmlize);
96                 } else {
97                         error("Your installation of source-highlight cannot handle sourcecode language $lang!");
98                 }
99         }
100     } #}}}
101     
102     sub htmlize (@) { #{{{
103         my %params=@_;
104     
105         my $page = $params{page};
106     
107         eval q{use FileHandle};
108         error($@) if $@;
109         eval q{use IPC::Open2};
110         error($@) if $@;
111     
112         local(*SPS_IN, *SPS_OUT);  # Create local handles
113     
114         my @args;
115     
116         if ($config{sourcecode_linenumbers}) {
117                 push @args, '--line-number= ';
118         }
119     
120         my $pid = open2(*SPS_IN, *SPS_OUT, $config{sourcecode_command},
121                                         '-s', IkiWiki::pagetype($pagesources{$page}),
122                                         '-c', $config{sourcecode_css}, '--no-doc',
123                                         '-f', 'xhtml',
124                                         @args);
125     
126         error("Unable to open $config{sourcecode_command}") unless $pid;
127     
128         print SPS_OUT $params{content};
129         close SPS_OUT;
130     
131         my @html = <SPS_IN>;
132         close SPS_IN;
133         
134         waitpid $pid, 0;
135     
136         my $stylesheet=bestlink($page, $config{sourcecode_css}.".css");
137         if (length $stylesheet) {
138                 push @{$metaheaders{$page}}, '<link href="'.urlto($stylesheet, $page).'"'.
139                         ' rel="stylesheet"'.
140                         ' type="text/css" />';
141         }
142     
143         return '<div id="sourcecode">'."\r\n".join("\r\n",@html)."\r\n</div>\n";
144     } # }}}
145     
146     sub pagetemplate (@) { #{{{
147         my %params=@_;
148     
149         my $page=$params{page};
150         my $template=$params{template};
151     
152         if (exists $metaheaders{$page} && $template->query(name => "meta")) {
153                 # avoid duplicate meta lines
154                 my %seen;
155                 $template->param(meta => join("\n", grep { (! $seen{$_}) && ($seen{$_}=1) } @{$metaheaders{$page}}));
156         }
157     } # }}}
158     
159     1