#!/usr/bin/perl
#
# Core of the plugin to interface Asymptote with TeXmacs.
# Copyright (c) 2005 Yann Dirson <ydirson@altern.org>
# Licenced under version 2 of the GNU GPL.
#
# usage within TeXmacs:
# =====================
# write asymptote commands within the input line, 
# use as many commands as necessary, 
# divide them by the ~ chararacter, because the ENTER key terminates the input and sends it to asymptote.
# output is the graph made by asymptote.
#
# History:
# v0.1 - initial release, heavily based on tm_gnuplot
# v0.2 - remove temporary input file, slight adjustments in example
# v0.3 - catch stderr so that new-style sessions display it (workaround)
#      - rewrite to perl
#      - start of proper temporary-file handling (cleanup not done for
#        some reason when called from texmacs
#      - updated sample file
#
# This software falls under the GNU general public license version 3 or later.
# It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
# in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
#
#################################################################################################

use strict;
use warnings;
use IO::Handle;
use File::Temp qw(tempdir);

my $VERSION = "0.3";

use constant {
  DATA_BEGIN  =>  "\x{2}",
  DATA_END    =>  "\x{5}",
  DATA_ESCAPE => "\x{1B}",
};

my $asy='asy';

####

# defining temporary postscript file directory
my $tempdir=tempdir('texmacsXXXXX',
		    TMPDIR  => 1,
		    CLEANUP => 1
		   ) or
  die "cannot create temporary directory";

# workaround SF bug#1325266
chdir $tempdir;
END { chdir '/'; }

# defining temporary input and output file name
my $infile = 'texmacs.asy';
my $psfile = 'texmacs.eps';
my $errfile = 'texmacs.err';

autoflush STDOUT 1;

sub tm_string($$) {
  my ($type,$str) = @_;
  return DATA_BEGIN . $type . ':' . $str . DATA_END;
}

# startup banner
print tm_string('verbatim', "This is a TeXmacs interface for Asymptote.\n");
print tm_string('verbatim', tm_string('channel', 'prompt') . 'Asymptote] ');

# open the file just once and constantly rewrite it
# this may not work on win32, but will be much faster when it works
open INFILE, ">$tempdir/$infile" or
  die "cannot create $tempdir/$infile";

# prompt-input-asy-output loop
while (<STDIN>) {
  # tm_gnuplot-like support for ~ as newlines
  tr/~/\n/;

  seek (INFILE, 0, 0);
  print INFILE $_;
  truncate INFILE, tell INFILE;
  INFILE->flush();

  #print STDERR "Running: $asy -o $tempdir/$psfile $tempdir/$infile 2> $tempdir/$errfile\n";
  if (system ("$asy -o $tempdir/$psfile $tempdir/$infile 2> $tempdir/$errfile") != 0) {
    print tm_string('verbatim', #tm_string('channel', 'error') .
		    "Error running $asy: $@");
    next;
  }

  if (open EPSDATA, "<$tempdir/$psfile") {
    local $/; my $data=<EPSDATA>; # slurp whole file
    print tm_string('verbatim', tm_string('ps', $data));
    close EPSDATA;
    unlink "$tempdir/$psfile";	# be sure not to catch previous graph on error
    unlink "$tempdir/$errfile";	# better safe than sorry
  } elsif (open ERRMSG, "<$tempdir/$errfile") {
    local $/; my $text=<ERRMSG>; # slurp whole file
    print tm_string('verbatim', #tm_string('channel', 'error') .
		    "$asy produced no graph - error was:\n$text");
    close ERRMSG;
    unlink "$tempdir/$errfile";
    #rename "$tempdir/$errfile", "$tempdir/$errfile.old";
  }

  # new prompt
  print tm_string('verbatim', tm_string('channel', 'prompt') . 'Asymptote] ');
}
