#!/usr/bin/python # MOLE CONSOLE (c) 2004 Tom Schouten # This program is free software covered under Version 2 # of the GNU General Public Licence. See the file COPYING for details # A minimalistic mole console # This sets up a (one way) network connection to a mole object # (through a netreceive object in the pd patch) # Each input line is terminated with ";\n" # Tab completion is available for all visible commands import socket import readline import time import re import os import sys class console: def __init__(self, host, port, command): print "\nMOLE Console. (c) 2004 Tom Schouten " readline.parse_and_bind("tab: complete") readline.set_completer(self.rl_completer) # this is not rl_basic_word_break_characters ... readline.set_completer_delims(' \t\n') self.words = [] self.target = (host, port) self.command = command self.dictfile = "/tmp/dictionary.txt" self.historyfile = "~/.mole-history" try: readline.read_history_file( os.path.expanduser(self.historyfile)) except IOError: print "using history file %s" % (self.historyfile) def cleanup(self): print "\nClosing console...", readline.write_history_file( os.path.expanduser(self.historyfile)) self.sockobj.close() print "Bye.\n" def remove_dictionary_file(self): try: os.remove (self.dictfile) except OSError: pass def send_command(self, command): try: self.sockobj.send(command) except socket.error: self.sock_recover() def get_wordlist(self): # wait for reply file to appear # it would be much cleaner to do this with a socket # but that's a bit overkill.. just need this wordlist retries = 30 # give it 3 seconds while retries: try: f = open(self.dictfile, 'r') break except IOError: if retries == 20: sys.stdout.write('Waiting for wordlist.') if retries <= 20: sys.stdout.write('.') sys.stdout.flush() time.sleep(.1) # don't wait too long retries = retries - 1 if retries: line = f.readline() self.words = line.split() f.close() else: sys.stdout.write(' timeout. Mole not responding.\n') def get_words(self): self.remove_dictionary_file() self.send_command(" %s save-words;\n" % self.dictfile) self.get_wordlist() self.remove_dictionary_file() def rl_completer(self, text, state): if state == 0: self.get_words() self.matcher = re.compile(text) while 1: try: word = self.words.pop() except IndexError: return 0 if self.matcher.match(word) != None : return word def sock_recover(self): print "Connection closed." self.sockobj.close() self.sockobj = None self.connect() def mainloop(self): while 1: try: line = raw_input("mole> ") except EOFError: break except KeyboardInterrupt: break self.send_command("%s;\n" % line) def connect(self): # create a new socket object for each connection self.sockobj = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print "\nConnecting to pd://%s:%d " % self.target, sys.stdout.flush() while 1: try: self.sockobj.connect(self.target) print "\nConnection established.\n" break except socket.error: try: if (self.command): os.system(self.command) # start server time.sleep(1) except KeyboardInterrupt: c.cleanup() sys.exit(1) sys.stdout.write('.') sys.stdout.flush() def getarg(n, default): if len(sys.argv) > n: return sys.argv[n] else: return default # get arguments host = getarg(1, "localhost") port = eval(getarg(2, "6666")) command = getarg(3, "") # start c = console(host, port, command) c.connect() c.mainloop() c.cleanup()