Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/MAFH2/fortuneengine/fortuneengine/pyconsole/pyconsole.py
diff options
context:
space:
mode:
Diffstat (limited to 'MAFH2/fortuneengine/fortuneengine/pyconsole/pyconsole.py')
-rw-r--r--MAFH2/fortuneengine/fortuneengine/pyconsole/pyconsole.py637
1 files changed, 0 insertions, 637 deletions
diff --git a/MAFH2/fortuneengine/fortuneengine/pyconsole/pyconsole.py b/MAFH2/fortuneengine/fortuneengine/pyconsole/pyconsole.py
deleted file mode 100644
index 7bb68e4..0000000
--- a/MAFH2/fortuneengine/fortuneengine/pyconsole/pyconsole.py
+++ /dev/null
@@ -1,637 +0,0 @@
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-# pyconsole - a simple console for pygame based applications
-#
-# Copyright (C) 2006 John Schanck
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-
-
-import pygame, os, sys
-from pygame.locals import *
-
-import re # Python's Regexp library. Used in pyconsole for parsing
-import textwrap # Used for proper word wrapping
-from string import ascii_letters
-from code import InteractiveConsole # Gives us access to the python interpreter
-
-
-__version__ = "0.7"
-
-WIDTH=0
-HEIGHT=1
-
-OUT = 0
-IN = 1
-ERR = 2
-
-PYCONSOLE = 1
-PYTHON = 2
-
-path = os.path.abspath(os.path.dirname(__file__))
-font_path = os.path.join(path, "fonts")
-cfg_path = os.path.join(path, "pyconsole.cfg")
-
-
-re_token = re.compile(r"""[\"].*?[\"]|[\{].*?[\}]|[\(].*?[\)]|[\[].*?[\]]|\S+""")
-re_is_list = re.compile(r'^[{\[(]')
-re_is_number = re.compile(r"""
- (?x)
- [-]?[0][x][0-9a-fA-F]+[lLjJ]? | # Hexadecimal
- [-]?[0][0-7]+[lLjJ]? | # Octal
- [-]?[\d]+(?:[.][\d]*)?[lLjJ]? # Decimal (Int or float)
- """)
-re_is_assign = re.compile(r'[$](?P<name>[a-zA-Z_]+\S*)\s*[=]\s*(?P<value>.+)')
-re_is_comment = re.compile(r'\s*#.*')
-re_is_var = re.compile(r'^[$][a-zA-Z_]+\w*\Z')
-
-
-
-class Writable(list):
- line_pointer = -1
- def write(self, line):
- self.append(str(line))
- def reset(self):
- self.__init__()
- def readline(self, size=-1):
- # Python's interactive help likes to try and call this, which causes the program to crash
- # I see no reason to implement interactive help.
- raise NotImplementedError
-
-class ParseError(Exception):
- def __init__(self, token):
- self.token = token
- def at_token(self):
- return self.token
-
-def balanced(t):
- stack = []
- pairs = {"\'":"\'", '\"':'\"', "{":"}", "[":"]", "(":")"}
- for char in t:
- if stack and char == pairs[stack[-1]]:
- stack.pop()
- elif char in pairs:
- stack.append(char)
- return not bool(stack)
-
-class Console:
- def __init__(self, screen, rect, functions={}, key_calls={}, vars={}, syntax={}):
- if not pygame.display.get_init():
- raise pygame.error, "Display not initialized. Initialize the display before creating a Console"
-
- if not pygame.font.get_init():
- pygame.font.init()
-
- self.parent_screen = screen
- self.rect = pygame.Rect(rect)
- self.size = self.rect.size
-
- self.user_vars = vars
- self.user_syntax = syntax
- self.user_namespace = {}
-
- self.variables = {\
- "bg_alpha":int,\
- "bg_color": list,\
- "txt_color_i": list,\
- "txt_color_o": list,\
- "ps1": str,\
- "ps2": str,\
- "ps3": str,\
- "active": bool,\
- "repeat_rate": list,\
- "preserve_events":bool,\
- "python_mode":bool,\
- "motd":list
- }
-
- self.load_cfg()
-
- self.set_interpreter()
-
- #pygame.key.set_repeat(*self.repeat_rate)
-
- self.bg_layer = pygame.Surface(self.size)
- self.bg_layer.set_alpha(self.bg_alpha)
-
- self.txt_layer = pygame.Surface(self.size)
- self.txt_layer.set_colorkey(self.bg_color)
-
- try:
- self.font = pygame.font.Font(os.path.join(font_path,"default.ttf"), 14)
- except IOError:
- self.font = pygame.font.SysFont("monospace", 14)
-
- self.font_height = self.font.get_linesize()
- self.max_lines = (self.size[HEIGHT] / self.font_height) - 1
-
- self.max_chars = (self.size[WIDTH]/(self.font.size(ascii_letters)[WIDTH]/len(ascii_letters))) - 1
- self.txt_wrapper = textwrap.TextWrapper()
-
- self.c_out = self.motd
- self.c_hist = [""]
- self.c_hist_pos = 0
- self.c_in = ""
- self.c_pos = 0
- self.c_draw_pos = 0
- self.c_scroll = 0
-
-
- self.changed = True
-
- self.func_calls = {}
- self.key_calls = {}
-
- self.add_func_calls({"echo":self.output, "clear": self.clear, "help":self.help})
- self.add_func_calls(functions)
-
- self.add_key_calls({"l":self.clear, "c":self.clear_input, "w":self.set_active})
- self.add_key_calls(key_calls)
-
-
- ##################
- #-Initialization-#
- def load_cfg(self):
- '''\
- Loads the config file path/pygame-console.cfg\
- All variables are initialized to their defaults,\
- then new values will be loaded from the config file if it exists.
- '''
- self.init_default_cfg()
- if os.path.exists(cfg_path):
- for line in file(cfg_path):
- tokens = self.tokenize(line)
- if re_is_comment.match(line):
- continue
- elif len(tokens) != 2:
- continue
- self.safe_set_attr(tokens[0],tokens[1])
-
- def init_default_cfg(self):
- self.bg_alpha = 255
- self.bg_color = [0x0,0x0,0x0]
- self.txt_color_i = [0xFF,0xFF,0xFF]
- self.txt_color_o = [0xCC,0xCC,0xCC]
- self.ps1 = "] "
- self.ps2 = ">>> "
- self.ps3 = "... "
- self.active = False
- self.repeat_rate = [500,30]
- self.python_mode = False
- self.preserve_events = False
- self.motd = ["[PyConsole 0.5]"]
-
- def safe_set_attr(self, name, value):
- '''\
- Safely set the console variables
- '''
- if name in self.variables:
- if isinstance(value, self.variables[name]) or not self.variables[name]:
- self.__dict__[name] = value
-
- def add_func_calls(self, functions):
- '''\
- Add functions to the func_calls dictionary.
- Arguments:
- functions -- dictionary of functions to add.
- '''
- if isinstance(functions,dict):
- self.func_calls.update(functions)
- self.user_namespace.update(self.func_calls)
-
- def add_key_calls(self, functions):
- '''\
- Add functions to the key_calls dictionary.
- Arguments:
- functions -- dictionary of key_calls to add.
- '''
- if isinstance(functions,dict):
- self.key_calls.update(functions)
-
- def output(self, text):
- '''\
- Prepare text to be displayed
- Arguments:
- text -- Text to be displayed
- '''
- if not str(text):
- return;
-
- try:
- self.changed = True
- if not isinstance(text,str):
- text = str(text)
- text = text.expandtabs()
- text = text.splitlines()
- self.txt_wrapper.width = self.max_chars
- for line in text:
- for w in self.txt_wrapper.wrap(line):
- self.c_out.append(w)
- except:
- pass
-
- def set_active(self,b=None):
- '''\
- Activate or Deactivate the console
- Arguments:
- b -- Optional boolean argument, True=Activate False=Deactivate
- '''
- if not b:
- self.active = not self.active
- else:
- self.active = b
-
-
- def format_input_line(self):
- '''\
- Format input line to be displayed
- '''
- # The \v here is sort of a hack, it's just a character that isn't recognized by the font engine
- text = self.c_in[:self.c_pos] + "\v" + self.c_in[self.c_pos+1:]
- n_max = self.max_chars - len(self.c_ps)
- vis_range = self.c_draw_pos, self.c_draw_pos + n_max
- return self.c_ps + text[vis_range[0]:vis_range[1]]
-
- def draw(self):
- '''\
- Draw the console to the parent screen
- '''
- if not self.active:
- return;
-
- if self.changed:
- self.changed = False
- # Draw Output
- self.txt_layer.fill(self.bg_color)
- lines = self.c_out[-(self.max_lines+self.c_scroll):len(self.c_out)-self.c_scroll]
- y_pos = self.size[HEIGHT]-(self.font_height*(len(lines)+1))
-
- for line in lines:
- tmp_surf = self.font.render(line, True, self.txt_color_o)
- self.txt_layer.blit(tmp_surf, (1, y_pos, 0, 0))
- y_pos += self.font_height
- # Draw Input
- tmp_surf = self.font.render(self.format_input_line(), True, self.txt_color_i)
- self.txt_layer.blit(tmp_surf, (1,self.size[HEIGHT]-self.font_height,0,0))
- # Clear background and blit text to it
- self.bg_layer.fill(self.bg_color)
- self.bg_layer.blit(self.txt_layer,(0,0,0,0))
-
- # Draw console to parent screen
- # self.parent_screen.fill(self.txt_color_i, (self.rect.x-1, self.rect.y-1, self.size[WIDTH]+2, self.size[HEIGHT]+2))
- pygame.draw.rect(self.parent_screen, self.txt_color_i, (self.rect.x-1, self.rect.y-1, self.size[WIDTH]+2, self.size[HEIGHT]+2), 1)
- self.parent_screen.blit(self.bg_layer,self.rect)
-
- #######################################################################
- # Functions to communicate with the console and the python interpreter#
- def set_interpreter(self):
- if self.python_mode:
- self.output("Entering Python mode")
- self.python_mode = True
- self.python_interpreter = InteractiveConsole()
- self.tmp_fds = []
- self.py_fds = [Writable() for i in range(3)]
- self.c_ps = self.ps2
- else:
- self.output("Entering Pyconsole mode")
- self.python_mode = False
- self.c_ps = self.ps1
-
- def catch_output(self):
- if not self.tmp_fds:
- self.tmp_fds = [sys.stdout, sys.stdin, sys.stderr]
- sys.stdout, sys.stdin, sys.stderr = self.py_fds
-
- def release_output(self):
- if self.tmp_fds:
- sys.stdout, sys.stdin, sys.stderr = self.tmp_fds
- self.tmp_fds = []
- [fd.reset() for fd in self.py_fds]
-
- def submit_input(self, text):
- '''\
- Submit input
- 1) Move input to output
- 2) Evaluate input
- 3) Clear input line
- '''
-
- self.clear_input()
- self.output(self.c_ps + text)
- self.c_scroll = 0
- if self.python_mode:
- self.send_python(text)
- else:
- self.send_pyconsole(text)
-
- def send_python(self, text):
- '''\
- Sends input the the python interpreter in effect giving the user the ability to do anything python can.
- '''
- self.c_ps = self.ps2
- self.catch_output()
- if text:
- self.add_to_history(text)
- r = self.python_interpreter.push(text)
- if r:
- self.c_ps = self.ps3
- else:
- code = "".join(self.py_fds[OUT])
- self.python_interpreter.push("\n")
- self.python_interpreter.runsource(code)
- for i in self.py_fds[OUT]+self.py_fds[ERR]:
- self.output(i)
- self.release_output()
-
- def send_pyconsole(self, text):
- '''\
- Sends input to pyconsole to be interpreted
- '''
- if not text: # Output a blank row if nothing is entered
- self.output("")
- return;
-
- self.add_to_history(text)
-
- #Determine if the statement is an assignment
- assign = re_is_assign.match(text)
- try:
- #If it is tokenize only the "value" part of $name = value
- if assign:
- tokens = self.tokenize(assign.group('value'))
- else:
- tokens = self.tokenize(text)
- except ParseError, e:
- self.output(r'At Token: "%s"' % e.at_token())
- return;
-
- if tokens == None:
- return
-
- #Evaluate
- try:
- out = None
- # A variable alone on a line
- if (len(tokens) is 1) and re_is_var.match(text) and not assign:
- out = tokens[0]
- # Statement in the form $name = value
- elif (len(tokens) is 1) and assign:
- self.setvar(assign.group('name'), tokens[0])
- else:
- # Function
- out = self.func_calls[tokens[0]](*tokens[1:])
- # Assignment from function's return value
- if assign:
- self.setvar(assign.group('name'), out)
-
- if not out == None:
- self.output(out)
- except (KeyError,TypeError):
- self.output("Unknown Command: " + str(tokens[0]))
- self.output(r'Type "help" for a list of commands.')
-
-
-
- ####################################################
- #-Functions for sharing variables with the console-#
- def setvar(self, name, value):
- '''\
- Sets the value of a variable
- '''
- if self.user_vars.has_key(name) or not self.__dict__.has_key(name):
- self.user_vars.update({name:value})
- self.user_namespace.update(self.user_vars)
- elif self.__dict__.has_key(name):
- self.__dict__.update({name:value})
-
- def getvar(self, name):
- '''\
- Gets the value of a variable, this is useful for people that want to access console variables from within their game
- '''
- if self.user_vars.has_key(name) or not self.__dict__.has_key(name):
- return self.user_vars[name]
- elif self.__dict__.has_key(name):
- return self.__dict__[name]
-
- def setvars(self, vars):
- try:
- self.user_vars.update(vars)
- self.user_namespace.update(self.user_vars)
- except TypeError:
- self.output("setvars requires a dictionary")
-
- def getvars(self, opt_dict=None):
- if opt_dict:
- opt_dict.update(self.user_vars)
- else:
- return self.user_vars
-
-
- def add_to_history(self, text):
- '''\
- Add specified text to the history
- '''
- self.c_hist.insert(-1,text)
- self.c_hist_pos = len(self.c_hist)-1
-
- def clear_input(self):
- '''\
- Clear input line and reset cursor position
- '''
- self.c_in = ""
- self.c_pos = 0
- self.c_draw_pos = 0
-
- def set_pos(self, newpos):
- '''\
- Moves cursor safely
- '''
- self.c_pos = newpos
- if (self.c_pos - self.c_draw_pos) >= (self.max_chars - len(self.c_ps)):
- self.c_draw_pos = max(0, self.c_pos - (self.max_chars - len(self.c_ps)))
- elif self.c_draw_pos > self.c_pos:
- self.c_draw_pos = self.c_pos - (self.max_chars/2)
- if self.c_draw_pos < 0:
- self.c_draw_pos = 0
- self.c_pos = 0
-
- def str_insert(self, text, strn):
- '''\
- Insert characters at the current cursor position
- '''
- foo = text[:self.c_pos] + strn + text[self.c_pos:]
- self.set_pos(self.c_pos + len(strn))
- return foo
-
- def process_input(self, event):
- '''\
- Loop through pygame events and evaluate them
- '''
- if not self.active:
- return False;
-
- if event.type == KEYDOWN:
- self.changed = True
- ## Special Character Manipulation
- if event.key == K_TAB:
- self.c_in = self.str_insert(self.c_in, " ")
- elif event.key == K_BACKSPACE:
- if self.c_pos > 0:
- self.c_in = self.c_in[:self.c_pos-1] + self.c_in[self.c_pos:]
- self.set_pos(self.c_pos-1)
- elif event.key == K_DELETE:
- if self.c_pos < len(self.c_in):
- self.c_in = self.c_in[:self.c_pos] + self.c_in[self.c_pos+1:]
- elif event.key == K_RETURN or event.key == 271:
- self.submit_input(self.c_in)
- ## Changing Cursor Position
- elif event.key == K_LEFT:
- if self.c_pos > 0:
- self.set_pos(self.c_pos-1)
- elif event.key == K_RIGHT:
- if self.c_pos < len(self.c_in):
- self.set_pos(self.c_pos+1)
- elif event.key == K_HOME:
- self.set_pos(0)
- elif event.key == K_END:
- self.set_pos(len(self.c_in))
- ## History Navigation
- elif event.key == K_UP:
- if len(self.c_out):
- if self.c_hist_pos > 0:
- self.c_hist_pos -= 1
- self.c_in = self.c_hist[self.c_hist_pos]
- self.set_pos(len(self.c_in))
- elif event.key == K_DOWN:
- if len(self.c_out):
- if self.c_hist_pos < len(self.c_hist)-1:
- self.c_hist_pos += 1
- self.c_in = self.c_hist[self.c_hist_pos]
- self.set_pos(len(self.c_in))
- ## Scrolling
- elif event.key == K_PAGEUP:
- if self.c_scroll < len(self.c_out)-1:
- self.c_scroll += 1
- elif event.key == K_PAGEDOWN:
- if self.c_scroll > 0:
- self.c_scroll -= 1
- ## Normal character printing
- elif event.key >= 32:
- mods = pygame.key.get_mods()
- if mods & KMOD_CTRL:
- if event.key in range(256) and chr(event.key) in self.key_calls:
- self.key_calls[chr(event.key)]()
- else:
- char = str(event.unicode)
- self.c_in = self.str_insert(self.c_in, char)
- return True
-
- def convert_token(self, tok):
- '''\
- Convert a token to its proper type
- '''
- tok = tok.strip("$")
- try:
- tmp = eval(tok, self.__dict__, self.user_namespace)
- except SyntaxError, strerror:
- self.output("SyntaxError: " + str(strerror))
- raise ParseError, tok
- except TypeError, strerror:
- self.output("TypeError: " + str(strerror))
- raise ParseError, tok
- except NameError, strerror:
- self.output("NameError: " + str(strerror))
- except:
- self.output("Error:")
- raise ParseError, tok
- else:
- return tmp
-
- def tokenize(self, s):
- '''\
- Tokenize input line, convert tokens to proper types
- '''
- if re_is_comment.match(s):
- return [s]
-
- for re in self.user_syntax:
- group = re.match(s)
- if group:
- self.user_syntax[re](self, group)
- return
-
- tokens = re_token.findall(s)
- tokens = [i.strip("\"") for i in tokens]
- cmd = []
- i = 0
- while i < len(tokens):
- t_count = 0
- val = tokens[i]
-
- if re_is_number.match(val):
- cmd.append(self.convert_token(val))
- elif re_is_var.match(val):
- cmd.append(self.convert_token(val))
- elif val == "True":
- cmd.append(True)
- elif val == "False":
- cmd.append(False)
- elif re_is_list.match(val):
- while not balanced(val) and (i + t_count) < len(tokens)-1:
- t_count += 1
- val += tokens[i+t_count]
- else:
- if (i + t_count) < len(tokens):
- cmd.append(self.convert_token(val))
- else:
- raise ParseError, val
- else:
- cmd.append(val)
- i += t_count + 1
- return cmd
-
-
- ##########################
- #-Some Builtin functions-#
- def clear(self):
- '''\
- Clear the Screen
- '''
- self.c_out = ["[Screen Cleared]"]
- self.c_scroll = 0
-
- def help(self, *args):
- '''\
- Output information about functions
- Arguments:
- args -- arbitrary argument list of function names
- |- No Args - A list of available functions will be displayed
- |- One or more Args - Docstring of each function will be displayed
- '''
- if args:
- items = [(i,self.func_calls[i]) for i in args if i in self.func_calls]
- for i,v in items:
- out = i + ": Takes %d arguments. " % (v.func_code.co_argcount - (v.func_code.co_varnames[0] is "self"))
- doc = v.func_doc
- if doc:
- out += textwrap.dedent(doc)
- tmp_indent = self.txt_wrapper.subsequent_indent
- self.txt_wrapper.subsequent_indent = " "*(len(i)+2)
- self.output(out)
- self.txt_wrapper.subsequent_indent = tmp_indent
- else:
- out = "Available commands: " + str(self.func_calls.keys()).strip("[]")
- self.output(out)
- self.output(r'Type "help command-name" for more information on that command')