summaryrefslogtreecommitdiff
path: root/doc/todo/automatic_use_of_syntax_plugin_on_source_code_files/discussion.mdwn
blob: 2fad9f19aedbc4112bc67bd259ba816811e65a56 (plain)

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]].

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.

-- [[Will]]


#!/usr/bin/perl
# markup source files
package IkiWiki::Plugin::sourcecode;

use warnings;
use strict;
use IkiWiki 2.00;
use open qw{:utf8 :std};

my %metaheaders;

sub import { #{{{
	hook(type => "getsetup", id => "sourcecode", call => \&getsetup);
	hook(type => "checkconfig", id => "sourcecode", call => \&checkconfig);
	hook(type => "pagetemplate", id => "sourcecode", call => \&pagetemplate);
} # }}}

sub getsetup () { #{{{
	return 
		plugin => {
			safe => 1,
			rebuild => 1, # format plugin
		},
		sourcecode_command => {
			type => "string",
			example => "/usr/bin/source-highlight",
			description => "The command to execute to run source-highlight",
			safe => 0,
			rebuild => 1,
		},
		sourcecode_lang => {
			type => "string",
			example => "c,cpp,h,java",
			description => "Comma separated list of suffixes to recognise as source code",
			safe => 1,
			rebuild => 1,
		},
		sourcecode_linenumbers => {
			type => "boolean",
			example => 1,
			description => "Should we add line numbers to the source code",
			safe => 1,
			rebuild => 1,
		},
		sourcecode_css => {
			type => "string",
			example => "sourcecode_style",
			description => "page to use as css file for source",
			safe => 1,
			rebuild => 1,
		},
} #}}}

sub checkconfig () { #{{{
	if (! $config{sourcecode_lang}) {
		error("The sourcecode plugin requires a list of suffixes in the 'sourcecode_lang' config option");
	}
	
	if (! $config{sourcecode_command}) {
		$config{sourcecode_command} = "source-highlight";
	}
	
	if (! length `which $config{sourcecode_command} 2>/dev/null`) {
		error("The sourcecode plugin is unable to find the $config{sourcecode_command} command");
	}

	if (! $config{sourcecode_css}) {
		$config{sourcecode_css} = "sourcecode_style";
	}
	
	if (! defined $config{sourcecode_linenumbers}) {
		$config{sourcecode_linenumbers} = 1;
	}
	
	my %langs = ();
	
	open(LANGS, "$config{sourcecode_command} --lang-list|");
	while (<LANGS>) {
		if ($_ =~ /(\w+) = .+\.lang/) {
			$langs{$1} = 1;
		}
	}
	close(LANGS);
	
	foreach my $lang (split(/[, ]+/, $config{sourcecode_lang})) {
		if ($langs{$lang}) {
			hook(type => "htmlize", id => $lang, call => \&htmlize);
		} else {
			error("Your installation of source-highlight cannot handle sourcecode language $lang!");
		}
	}
} #}}}

sub htmlize (@) { #{{{
	my %params=@_;

	my $page = $params{page};

	eval q{use FileHandle};
	error($@) if $@;
	eval q{use IPC::Open2};
	error($@) if $@;

	local(*SPS_IN, *SPS_OUT);  # Create local handles

	my @args;

	if ($config{sourcecode_linenumbers}) {
		push @args, '--line-number= ';
	}

	my $pid = open2(*SPS_IN, *SPS_OUT, $config{sourcecode_command},
					'-s', IkiWiki::pagetype($pagesources{$page}),
					'-c', $config{sourcecode_css}, '--no-doc',
					'-f', 'xhtml',
					@args);

	error("Unable to open $config{sourcecode_command}") unless $pid;

	print SPS_OUT $params{content};
	close SPS_OUT;

	my @html = <SPS_IN>;
	close SPS_IN;
	
	waitpid $pid, 0;

	my $stylesheet=bestlink($page, $config{sourcecode_css}.".css");
	if (length $stylesheet) {
		push @{$metaheaders{$page}}, '<link href="'.urlto($stylesheet, $page).'"'.
			' rel="stylesheet"'.
			' type="text/css" />';
	}

	return '<div id="sourcecode">'."\r\n".join("\r\n",@html)."\r\n</div>\n";
} # }}}

sub pagetemplate (@) { #{{{
	my %params=@_;

	my $page=$params{page};
	my $template=$params{template};

	if (exists $metaheaders{$page} && $template->query(name => "meta")) {
		# avoid duplicate meta lines
		my %seen;
		$template->param(meta => join("\n", grep { (! $seen{$_}) && ($seen{$_}=1) } @{$metaheaders{$page}}));
	}
} # }}}

1