#!/usr/bin/perl
# Ikiwiki Sweave-alike plugin
# under the terms of the GPL version 2, or any later version at your
# option.
# Copyright 2012 by Don Armstrong <don@donarmstrong.com>.


package IkiWiki::Plugin::sweavealike;

=head1 NAME

sweavealike -- A Sweave-alike plugin which allows for embedding R code in IkiWiki

=head1 SYNOPSIS


=head1 DESCRIPTION


=head1 BUGS

None known.

=cut

use warnings;
use strict;

use Statistics::R;

use IkiWiki '3.00';

my $id = "sweavealike";
sub import {
    hook(type => "preprocess", id => $id, call => \&preprocess);
    hook(type => "preprocess", id => $id, call => \&preprocess_scan, scan => 1);
    hook(type => "htmlize", id => $id, call => \&htmlize);
    hook(type => "savestate", id => $id, call => \&savestate);
}

sub preprocess_scan {
    my %param = @_;
    # start the R process here for this page
    if (not defined $pagestate{$param{page}}{$id}{R}) {
	$pagestate{$param{page}}{$id}{R} = Statistics::R->new(shared => 1) or error("Unable to create an R process");
    }
}

sub preprocess {
    my %param = @_;

    # we currently don't bother to support anything but outputing the
    # entire segment of code and its R output

    if (not exists $param{code} or not defined $param{code}) {
	error("There wasn't any R code supplied");
    }
    my $code_result;
    eval {
	$code_result = $pagestate{$param{page}}{$id}{R}->run($param{code});
    };
    if ($@) {
	error($@);
    }
    my $output = "sweave output\n\n";
    if (exists $param{verbatim}) {
	$output = $param{code};
	$output =~ s/^/> /mg;
    }
    $output .= $code_result;
    $output =~ s/^/    /mg;
    return($output);
}

# stop any started R processes here
sub htmlize {
    my %param = @_;
    if (exists $pagestate{$param{page}} and
	exists $pagestate{$param{page}}{$id} and
	exists $pagestate{$param{page}}{$id}{R}) {
	if (defined $pagestate{$param{page}}{$id}{R}
	    and $pagestate{$param{page}}{$id}{R}->is_started()) {
	    $pagestate{$param{page}}{$id}{R}->stop();
	}
	delete $pagestate{$param{page}}{$id}{R};
    }
}

sub savestate {
    # make sure we never try to save an R process
    for my $page (keys %pagestate) {
	next unless exists $pagestate{$page}{$id};
	next unless exists $pagestate{$page}{$id}{R};
	if (defined $pagestate{$page}{$id}{R}
	    and $pagestate{$page}{$id}{R}->is_started()) {
	    $pagestate{$page}{$id}{R}->stop;
	}
	delete $pagestate{$page}{$id}{R};
    }
}





1;


__END__








