# This software carries the following license:
#
# Modified BSD license
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# 
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Steinar Knutsen

"""LineInterpreter 1.3
"""
import readline, string, re, os, DCLMatcher, sys

def GetTermSize():
	# Frankly, I don't know the proper way of doing this.
	try:
		co = string.atoi(os.environ['COLUMNS'])
		li = string.atoi(os.environ['LINES'])
	except:
		try:
			tc = filter(lambda x: x[:3] == 'co#' or x[:3] == 'li#',
				string.split(os.environ['TERMCAP'], ':'))
			li = string.atoi(filter(lambda x: x[:3] == 'li#', tc)[0][3:])
			co = string.atoi(filter(lambda x: x[:3] == 'co#', tc)[0][3:])
		except:
			co, li = 80, 24
	return co, li

def KeyPressWait():
	raw_input("[RETURN]")

class LineInterpreter:
	arguments = re.compile('([^ "\']+|".*?"|\'.*?\')')

	def __init__(self, functiontable, prompt='> '):
	# Mapping types with strings as keys are suited as function tables.
		self.prompt = prompt
		self.functiontable = functiontable
		self.columns, self.lines = GetTermSize()
	
	def mainloop(self):
		line = self.getline()
		while line != None:
			if len(line) == 0:
				line = self.getline()
				continue
			self.functiontable[line[0]](self, line[1:])
			line = self.getline()
		
	def getline(self):
		def strip_apo(word):
			if word[0] == '"' and word[-1] == '"':
				return word[1:-1]
			elif word[0] == "'" and word[-1] == "'":
				return word[1:-1]
			else:
				return word
		try:
			line = re.findall(self.arguments, raw_input(self.prompt))
			return map(strip_apo, line)
		except:
			return None
	
	def writeline(self, line, linecount = 0):
	# Does not add linefeed at the end of the line.
		if len(line) <= self.columns:
			sys.stdout.write(line)
			return linecount+1
		tmpline = line
		while len(tmpline) > 0:
			if len(tmpline) > self.columns:
				l = string.rfind(tmpline, ' ', 0, self.columns+1)
				if l == -1:
					sys.stdout.write(tmpline[:self.columns])
					tmpline = tmpline[self.columns:]
				else:
					sys.stdout.write(tmpline[:l]+'\n')
					tmpline = tmpline[l+1:]
			else:
				sys.stdout.write(tmpline)
				tmpline = ''
			linecount = linecount + 1
			if linecount == self.lines - 2:
				KeyPressWait()
				linecount = 0
		return linecount

	def writelines(self, lines, linecount = 0):
		for line in lines:
			linecount = self.writeline(line, linecount)
			if linecount == self.lines - 2:
				KeyPressWait()
				linecount = 0
		
	def formatlines(self, lines):
		new_lines = []
		tmp_line, curr_len = [], 0
		for line in lines:
			words = string.split(line)
			for word in words:
				if len(word)+1+curr_len <= self.columns:
					tmp_line.append(word)
					if len(tmp_line) == 1:
						curr_len = curr_len + len(word)
					else:
						curr_len = curr_len + len(word) + 1
				else:
					tmp_line[-1] = tmp_line[-1] + '\n'
					new_lines.append(string.join(tmp_line, ' '))
					tmp_line = [word]
					curr_len = len(word)
		if len(tmp_line) > 0:
			tmp_line[-1] = tmp_line[-1] + '\n'
			new_lines.append(string.join(tmp_line, ' '))
		return new_lines
