#!/usr/bin/env python
# rlwrap.py
# Copyright 2008 David Wolever
# 
from popen2 import popen2
from sys import stdout, exit, argv
from thread import start_new_thread, allocate_lock
import atexit
import cmd
import os
import readline

class ReadlineWrapper(cmd.Cmd):
    prompt = ""

    def __init__(self, command):
        cmd.Cmd.__init__(self)
        (self._child_stdout, self._child_stdin) = popen2(command)
        start_new_thread(self._child_reader, (42, ))

    def _child_reader(self, dummy):
        while True:
            data = self._child_stdout.read(1)
            if not data:
                print "rl: got EOF from child"
                exit(0)
            self._child_data(data)

    def _child_data(self, data):
        stdout.write(data)

    def do_help(self, input):
        self.default(input)

    def default(self, input):
        self._child_stdin.write(input + "\n")
        self._child_stdin.flush()

    def emptyline(self):
        self.default("")

    def run(self):
        self.cmdloop()

import time
class camllight(ReadlineWrapper):
    last = None
    prompt = '# '
    # Is caml ready to accept our input?
    caml_ready = False

    def wait_caml(self):
        # Use a busy loop instead of a lock because NOTHING can stop
        # a lock while it's waiting... Not EVEN A KEYBOARDINTERRUPT!
        while not self.caml_ready:
            time.sleep(0.01)
        return

    def run(self):
        # Wait for the caml prompt before showing our prompt
        self.wait_caml()
        ReadlineWrapper.run(self)

    def _child_data(self, data):
        if self.last == '\n' and data == '#':
            # Once caml has given us a '#', we can start reading
            self.caml_ready = True
            return
        self.last = data
        stdout.write(data)

    def default(self, input):
        if input.endswith(';;'):
            self.caml_ready = False
            self.prompt = '# '
        else:
            self.prompt = '. '
        ReadlineWrapper.default(self, input)
        self.wait_caml()

if len(argv) == 1:
    print "Usage: %s PROGRAM [arguments for program]" %(argv[0])
    if argv[0].endswith('.py'):
        print "Hint: ln -s %s /usr/bin/rl" %(os.path.abspath(__file__))
    exit(1)

    
### Setup readline
hist_path = os.path.expanduser('~/.rl_%s' %(argv[1]))
if not os.path.exists(hist_path):
    # Create an empty file
    open(hist_path, "w").close()
readline.read_history_file(hist_path)
atexit.register(readline.write_history_file, hist_path)

### Start the program
wrapper = globals().get(argv[1], ReadlineWrapper)
r = wrapper(" ".join(argv[1:]))
try: r.run()
except KeyboardInterrupt:
    # KeyboardInterrupts can be safely ignored.
    pass
