Esempio n. 1
0
class ClassicPythonShell(Shell, ConsoleProgressBarMixin):
    """Classic Python shell interface.

    This class allows igraph to be embedded in Python's shell."""
    
    def __init__(self):
        """Constructor.

        Imports Python's classic shell"""
        Shell.__init__(self)
        self._shell = None

        try:
            self.__class__.progress_bar = ProgressBar(TerminalController())
        except ValueError:
            # Terminal is not capable enough, disable progress handler
            del self.__class__._progress_handler

    def __call__(self):
        """Starts the embedded shell."""
        if self._shell is None:
            from code import InteractiveConsole
            self._shell = InteractiveConsole()
            print >> sys.stderr, "igraph %s running inside " % __version__,
            self._shell.runsource("from igraph import *")

        self._shell.interact()
Esempio n. 2
0
def interactive_client(file, address, cache_size, readonly, repair,
                       startup):
    if file:
        storage = FileStorage(file, readonly=readonly, repair=repair)
        description = file
    else:
        socket_address = SocketAddress.new(address)
        wait_for_server(address=socket_address)
        storage = ClientStorage(address=socket_address)
        description = socket_address
    connection = Connection(storage, cache_size=cache_size)
    console_module = ModuleType('__console__')
    sys.modules['__console__'] = console_module
    namespace = {'connection': connection,
                 'root': connection.get_root(),
                 'get': connection.get,
                 'sys': sys,
                 'os': os,
                 'int8_to_str': int8_to_str,
                 'str_to_int8': str_to_int8,
                 'pp': pprint}
    vars(console_module).update(namespace)
    configure_readline(
        vars(console_module), os.path.expanduser("~/.durushistory"))
    console = InteractiveConsole(vars(console_module))
    if startup:
        src = '''with open('{fn}', 'rb') as _:
                     _ = compile(_.read(), '{fn}', 'exec')
                     exec(globals().pop('_'))
        '''.format(fn = os.path.expanduser(startup)).rstrip()
        console.runsource(src, '-stub-', 'exec')
    help = ('    connection -> the Connection\n'
            '    root       -> the root instance')
    console.interact('Durus %s\n%s' % (description, help))
Esempio n. 3
0
def interactive_client(file, host, port, cache_size, readonly, repair,
                       startup):
    if file:
        storage = FileStorage(file, readonly=readonly, repair=repair)
        description = file
    else:
        wait_for_server(host, port)
        storage = ClientStorage(host=host, port=port)
        description = "%s:%s" % (host, port)
    connection = Connection(storage, cache_size=cache_size)
    namespace = {'connection': connection,
                 'root': connection.get(0),
                 'get': connection.get,
                 'sys': sys,
                 'os': os,
                 'p64': p64,
                 'u64': u64,
                 'pp': pprint}
    configure_readline(namespace, os.path.expanduser("~/.durushistory"))
    console = InteractiveConsole(namespace)
    if startup:
        console.runsource('execfile("%s")' % os.path.expanduser(startup))
    help = ('    connection -> the connection\n'
            '    root       -> get(0)\n'
            '    get(oid)   -> get an object\n'
            '    pp(object) -> pretty-print')
    console.interact('Durus (%s)\n%s' % (description, help))
Esempio n. 4
0
def interactive_client(file, address, cache_size, readonly, repair,
                       startup, storage_class=None):
    if file:
        storage = get_storage(file, storage_class=storage_class,
                readonly=readonly, repair=repair)
        description = file
    else:
        socket_address = SocketAddress.new(address)
        wait_for_server(address=socket_address)
        storage = ClientStorage(address=socket_address)
        description = socket_address
    connection = Connection(storage, cache_size=cache_size)
    console_module = ModuleType('__console__')
    sys.modules['__console__'] = console_module
    namespace = {'connection': connection,
                 'root': connection.get_root(),
                 'get': connection.get,
                 'sys': sys,
                 'os': os,
                 'int8_to_str': int8_to_str,
                 'str_to_int8': str_to_int8,
                 'pp': pprint}
    vars(console_module).update(namespace)
    configure_readline(
        vars(console_module), os.path.expanduser("~/.durushistory"))
    console = InteractiveConsole(vars(console_module))
    if startup:
        console.runsource('execfile("%s")' % os.path.expanduser(startup))
    help = ('    connection -> the Connection\n'
            '    root       -> the root instance')
    console.interact('Durus %s\n%s' % (description, help))
Esempio n. 5
0
class ClassicPythonShell(Shell, ConsoleProgressBarMixin):
    """Classic Python shell interface.

    This class allows igraph to be embedded in Python's shell."""
    def __init__(self):
        """Constructor.

        Imports Python's classic shell"""
        Shell.__init__(self)
        self._shell = None

        try:
            self.__class__.progress_bar = ProgressBar(TerminalController())
        except ValueError:
            # Terminal is not capable enough, disable progress handler
            del self.__class__._progress_handler

    def __call__(self):
        """Starts the embedded shell."""
        if self._shell is None:
            from code import InteractiveConsole
            self._shell = InteractiveConsole()
            print >> sys.stderr, "igraph %s running inside " % __version__,
            self._shell.runsource("from igraph import *")

        self._shell.interact()
Esempio n. 6
0
File: console.py Progetto: zain/pyr
    def runsource(self, source, filename="<input>", symbol="single"):
        try:
            # do some special pretty printing if the source is an expression
            code = self.compile(source, filename, "eval")
            eval_expression = True
        except (OverflowError, SyntaxError, ValueError):
            eval_expression = False

        if eval_expression:
            if code is None:
                return True

            try:
                result = eval(code, self.locals)
                self.pretty_print(result)
            except SystemExit:
                raise
            except:
                self.showtraceback()
            else:
                if softspace(sys.stdout, 0):
                    print

            return False
        else:
            # fall back to default behavior
            return InteractiveConsole.runsource(self, source, filename, symbol)
Esempio n. 7
0
 def push(self,line, mode='single', name='auto'):
     self.last_op = datetime.now()
     self.accept_output()
     signal.setitimer(signal.ITIMER_VIRTUAL,10)
     ret = InteractiveConsole.runsource(self,line,'<'+name+'>',mode)
     signal.setitimer(signal.ITIMER_VIRTUAL,0)
     self.return_output()
     return ret
Esempio n. 8
0
    def runsource(self, source, filename="<stdin>", symbol="single"):
        if not self.compiler:
            from pysoc import compiler
            self.compiler = compiler

        source = self.compiler.compile(source)
        try:
            return InteractiveConsole.runsource(self, source, filename, symbol)
        except SystemExit, e:
            sys.exit(0)
Esempio n. 9
0
    def runsource(self, source, filename="<stdin>", symbol="single"):
        if not self.compiler:
            from pysoc import compiler
            self.compiler = compiler

        source = self.compiler.compile(source)
        try :
            return InteractiveConsole.runsource(self, source, filename, symbol)
        except SystemExit, e:
            sys.exit(0)
Esempio n. 10
0
    def runsource(self, source, filename="<input>", symbol="single"):
        """
        THis function ...
        :param source:
        :param filename:
        :param symbol:
        :return:
        """

        #if self.remote is not None:
        #if self.remote_session is not None:
        if self.locals["session"] is not None:

            if "Frame.from_file" in source:

                variable_name = source.split("=")[0].strip()

                #print(variable_name)

                #print(source.split("Frame(")[1])

                arguments = source.split("from_file(")[1].split(")")[0].split(
                    ",")

                path = arguments[0]

                #print(arguments)

                source = variable_name + " = RemoteFrame.from_file(" + path + ", session)"

                #print(source)

            #source = source.replace("Image.from_file(", "RemoteImage")
            #source = source.replace("DataCube.from_file", "RemoteDataCube")
            #print(source)

        # Run the code
        InteractiveConsole.runsource(self,
                                     source,
                                     filename=filename,
                                     symbol=symbol)
Esempio n. 11
0
class ClassicPythonShell(Shell, ConsoleProgressBarMixin):
    """Classic Python shell interface.

    This class allows igraph to be embedded in Python's shell."""
    def __init__(self):
        """Constructor.

        Imports Python's classic shell"""
        Shell.__init__(self)
        ConsoleProgressBarMixin.__init__(self)
        self._shell = None

    def __call__(self):
        """Starts the embedded shell."""
        if self._shell is None:
            from code import InteractiveConsole
            self._shell = InteractiveConsole()
            print >> sys.stderr, "igraph %s running inside " % __version__,
            self._shell.runsource("from igraph import *")

        self._shell.interact()
Esempio n. 12
0
def simple_repl(user_ns={}):
    if iswindows:
        setup_pyreadline()
    else:
        try:
            import rlcompleter  # noqa
            import readline  # noqa
            readline.parse_and_bind("tab: complete")
        except ImportError:
            pass

    user_ns = user_ns or {}
    import sys, re  # noqa
    for x in ('os', 'sys', 're'):
        user_ns[x] = user_ns.get(x, globals().get(x, locals().get(x)))
    user_ns['exit'] = Exit()
    user_ns['help'] = Helper()
    from code import InteractiveConsole
    console = InteractiveConsole(user_ns)
    console.runsource('from __future__ import (unicode_literals, division, absolute_import, print_function)')
    console.interact(BANNER + 'Use exit to quit')
Esempio n. 13
0
 def runsource(self,source,filename="<input>",symbol="single"):
     old_stdout = sys.stdout
     old_stderr = sys.stderr
     sys.stdout = sys.stderr = collector = MyStringIO(self)
     try:
         more = _InteractiveConsole.runsource(self,source,filename,symbol)
     finally:
         if sys.stdout is collector:
             sys.stdout = old_stdout
         if sys.stderr is collector:
             sys.stderr = old_stderr
     return more
Esempio n. 14
0
def simple_repl(user_ns={}):
    if iswindows:
        setup_pyreadline()
    else:
        try:
            import rlcompleter  # noqa
            import readline  # noqa
            readline.parse_and_bind("tab: complete")
        except ImportError:
            pass

    user_ns = user_ns or {}
    import sys, re  # noqa
    for x in ('os', 'sys', 're'):
        user_ns[x] = user_ns.get(x, globals().get(x, locals().get(x)))
    user_ns['exit'] = Exit()
    user_ns['help'] = Helper()
    from code import InteractiveConsole
    console = InteractiveConsole(user_ns)
    console.runsource('from __future__ import (unicode_literals, division, absolute_import, print_function)')
    console.interact(BANNER + 'Use exit to quit')
Esempio n. 15
0
class ClassicPythonShell(Shell, ConsoleProgressBarMixin):
    """Classic Python shell interface.

    This class allows igraph to be embedded in Python's shell."""

    def __init__(self):
        """Constructor.

        Imports Python's classic shell"""
        Shell.__init__(self)
        ConsoleProgressBarMixin.__init__(self)
        self._shell = None

    def __call__(self):
        """Starts the embedded shell."""
        if self._shell is None:
            from code import InteractiveConsole
            self._shell = InteractiveConsole()
            print >> sys.stderr, "igraph %s running inside " % __version__,
            self._shell.runsource("from igraph import *")

        self._shell.interact()
Esempio n. 16
0
 def runsource(self,source,filename="<input>",symbol="single"):
     old_stdout = sys.stdout
     old_stderr = sys.stderr
     sys.stdout = sys.stderr = collector = StringIO()
     try:
         more = _InteractiveConsole.runsource(self,source,filename,symbol)
     finally:
         if sys.stdout is collector:
             sys.stdout = old_stdout
         if sys.stderr is collector:
             sys.stderr = old_stderr
     self.write(collector.getvalue())
     return more
Esempio n. 17
0
class ClassicPythonShell(Shell):
    """Classic Python shell interface.

    This class allows igraph to be embedded in Python's shell."""
    
    def __init__(self):
        """Constructor.

        Imports Python's classic shell"""
        from code import InteractiveConsole
        try:
            self.__class__.progress_bar = ProgressBar(TerminalController())
        except ValueError:
            # Terminal is not capable enough, disable progress handler
            del self.__class__._progress_handler

    def __call__(self, namespace=None):
        """Starts the embedded shell.
        
        @param namespace: global namespace to use"""
        from code import InteractiveConsole
        self._shell = InteractiveConsole(locals=namespace)
        print >>sys.stderr, "igraph %s running inside " % __version__,
        self._shell.runsource("from igraph import *")
        self._shell.interact()

    def _progress_handler(message, percentage):
        """Progress bar handler, called when C{igraph} reports the progress
        of an operation

        @param message: message provided by C{igraph}
        @param percentage: percentage provided by C{igraph}
        """
        if percentage >= 100:
            ClassicPythonShell.progress_bar.clear()
        else:
            ClassicPythonShell.progress_bar.update(percentage, message)
    _progress_handler = staticmethod(_progress_handler)
Esempio n. 18
0
		def runsource(self, source, *args):
			# load the source
			# if there is Vivaldi function definition
			# function_code_dict will be updated
			new_function_code_dict = load_common(code=source)
			function_code_dict.update(new_function_code_dict)

			from Vivaldi_translator_layer import read_as_main
			source = read_as_main(source)

			#MARK : debug
			#print "source :"
			#print repr(source)

			src_list = source.split('\n')
			src_body = '\n'.join(src_list[:-1])
			src_tail = src_list[-1]
			
			# 2-1. block input
			if InteractiveConsole.runsource(self,src_body,*args):
				return  InteractiveConsole.runsource(self,source,*args)
			# 2-2. single line
			else : 
				return InteractiveConsole.runsource(self,src_tail,*args)
Esempio n. 19
0
 def runsource(self, source, filename="<input>", symbol="single"):
     """Do the same thing as any InteractiveConsole, except if we run into a
     completed statement, we first run the decoration code for envdraw on it
     before passing it off to the execute part of the REPL.
     """
     try:
         if compile_command(source, filename, symbol):
             tree = ast.parse(source, filename, symbol)
             new_tree = ast.fix_missing_locations(AddFuncCall().visit(
                                                     AddFuncReturn().visit(
                                                         AddFuncDef().visit(tree))))
             compiled_code = compile(new_tree, filename, symbol)
             self.runcode(compiled_code)
             TRACKER.insert_global_bindings(self.locals)
             return False
         else:
             return InteractiveConsole.runsource(self, source, filename, symbol)
     except (SyntaxError, OverflowError):
         self.showsyntaxerror(filename)
         return False
Esempio n. 20
0
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.')
Esempio n. 21
0
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 BaseException:
            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 as e:
            self.output(r'At Token: "%s"' % e.at_token())
            return

        if tokens is None:
            return

        # Evaluate
        try:
            out = None
            # A variable alone on a line
            if (len(tokens) == 1) and re_is_var.match(text) and not assign:
                out = tokens[0]
            # Statement in the form $name = value
            elif (len(tokens) == 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 out is not 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 name in self.user_vars or name not in self.__dict__:
            self.user_vars.update({name: value})
            self.user_namespace.update(self.user_vars)
        elif name in self.__dict__:
            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 name in self.user_vars or name not in self.__dict__:
            return self.user_vars[name]
        elif name in self.__dict__:
            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.str)
                    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 as strerror:
            self.output("SyntaxError: " + str(strerror))
            raise ParseError(tok)
        except TypeError as strerror:
            self.output("TypeError: " + str(strerror))
            raise ParseError(tok)
        except NameError as strerror:
            self.output("NameError: " + str(strerror))
        except BaseException:
            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 x in self.user_syntax:
            group = x.match(s)
            if group:
                self.user_syntax[x](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.__code__.co_argcount -
                    (v.__code__.co_varnames[0] == "self"))
                doc = v.__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(list(self.func_calls.keys())).strip("[]")
            self.output(out)
            self.output(r'Type "help command-name" for more\
                information on that command')
Esempio n. 22
0
 def runsource(self, source, *args):
     self.last_buffer = [source.encode('utf-8')]
     return InteractiveConsole.runsource(self, source, *args)
Esempio n. 23
0
class Console(object):
     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 toggle_active(self):
         self.active = not self.active

     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.')
Esempio n. 24
0
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.init_default_cfg()
        
        
        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)
        
        self.font = pygame.font.Font('views/DroidSansMono.ttf', 12)
        
        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)
        self.set_interpreter()

    ##################
    #-Initialization-#
    def init_default_cfg(self):
        self.bg_alpha = 175
        self.bg_color = [0x0,0x44,0xAA]
        self.txt_color_i = [0xFF,0xFF,0xFF]
        self.txt_color_o = [0xEE,0xEE,0xEE]
        self.ps1 = "] "
        self.ps2 = ">>> "
        self.ps3 = "... "
        self.active = True
        self.repeat_rate = [500,30]
        self.python_mode = False
        self.preserve_events = False
        self.motd = ["Press Ctrl_w to hide the console","One day this will have more to say"]

    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:
            raise
    
    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
        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):
        #self.output("Entering Python mode")
        self.python_interpreter = InteractiveConsole()
        self.tmp_fds = []
        self.py_fds = [Writable() for i in range(3)]
        self.c_ps = self.ps2
    
    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
        self.send_python(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()
    
    
    ####################################################
    #-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):
        '''\
        Loop through pygame events and evaluate them
        '''
        if not self.active:
            return;
        
        if self.preserve_events:
            eventlist = pygame.event.get(KEYDOWN)
        else:
            eventlist = pygame.event.get()
        
        for event in eventlist:
            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)

    ##########################
    #-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')
Esempio n. 25
0
class Console:
	def __init__(self, screen, rect, functions={}, key_calls={}, vars={}):
		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.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)

		self.font = pygame.font.Font("../gfx/fixed_width.ttf",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("#")[WIDTH]) - 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
	#	if self.python_mode:
	#		self.c_ps = self.ps2
	#	else:
	#		self.c_ps = self.ps1
		
		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)
	
	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.
		   functions -- dictionary of functions to add"""
		if isinstance(functions,dict):
			self.func_calls.update(functions)
	
	def add_key_calls(self, functions):
		"""Add functions to the key_calls dictionary.
		   functions -- dictionary of key_calls to add"""
		if isinstance(functions,dict):
			self.key_calls.update(functions)
	
	def clear(self):
		"""Clear the Screen"""
		self.c_out = ["[Screen Cleared]"]
		self.c_scroll = 0
	
	def help(self, *args):
		"""Output information about functions
		   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"))
				# TODO: function doc get funny formatting, so need to fiddle here
				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')
	
	def output(self, text):
		"""Prepare text to be displayed
		   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:
			print text
	
	def set_active(self,b=None):
		"""Activate or Deactivate the console. Pass with b-
		   Optional boolean argument, True=Activate False=Deactivate"""
		if not b:
			self.active = not self.active
		else:
			self.active = b
	
	def set_interpreter(self):
		if self.python_mode:
			# spqr tries to reduce console ouput,but we can still
			# have some debugging info
			if(SPQR.DEBUG_MODE==True):
				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:
			if(SPQR.DEBUG_MODE==True):
				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 format_input_line(self):
		'''\
		Format input line to be displayed
		'''
		text = self.c_in[:self.c_pos] + "|" + self.c_in[self.c_pos:]
		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)

			
	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 to the python interpreter 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"""
		# Output a blank row if nothing is entered
		if not text:
			self.output("")
			return;
		
		self.add_to_history(text)
		# Check if the text is in the form: name = value
		assign = re_is_assign.match(text)
		try:
			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;
		
		try:
			if (len(tokens) is 1) and re_is_var.match(text) and not assign:
				out = tokens[0]
			else:
				out = self.func_calls[tokens[0]](*tokens[1:])
		except (KeyError,TypeError):
			if (len(tokens) is 1) and assign:
				self.setvar(assign.group('name'), tokens[0])
			else:
				self.output("Unknown Command: " + str(tokens[0]))
				self.output(r'Type "help" for a list of commands.')
		else:
			self.output(out)
Esempio n. 26
0
		def runsource(self, source, *args):
			from Vivaldi_translator_layer import line_translator
			source = line_translator(source, data_package_list)
	
			self.last_buffer = [ source.encode('latin-1') ]
			return InteractiveConsole.runsource(self, source, *args)
Esempio n. 27
0
class Console:
    def __init__(self, screen, rect, functions={}, key_calls={}, vars={}, syntax={}):
        if not pygame.display.get_init():
            raise pygame.error
        
        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 open(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 = 200
        self.bg_color = [0x0,0x44,0xAA]
        self.txt_color_i = [0xFF,0xFF,0xFF]
        self.txt_color_o = [0xEE,0xEE,0xEE]
        self.ps1 = "] "
        self.ps2 = ">>> "
        self.ps3 = "... "
        self.active = True
        self.repeat_rate = [500,30]
        self.python_mode = False
        self.preserve_events = True
        self.motd = ["|DarkNet|", "Type help for a list of commands","Press Ctrl_w to hide the console"]
    
    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]:int(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[-(int(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:
            self.output(r'At Token: "%s"')
            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):
        '''\
        Loop through pygame events and evaluate them
        '''
        if not self.active:
            return;
        
        if self.preserve_events:
            eventlist = pygame.event.get(KEYDOWN)
        else:
            eventlist = pygame.event.get()
        
        for event in eventlist:
            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)

    
    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:
            self.output("SyntaxError: ")
            raise ParseError
        except TypeError:
            self.output("TypeError: ")
            raise ParseError
        except NameError:
            self.output("NameError: ")
        except:
            self.output("Error:")
            raise ParseError
        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
            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')
Esempio n. 28
0
 def runsource(self, source, *args):
     self.last_buffer = [source]
     return InteractiveConsole.runsource(self, source, *args)
Esempio n. 29
0
class PyREPLTextView(NSTextView):

    def init(self):
        self = super(PyREPLTextView, self).init()
        self.setDelegate_(self)

        self.setDrawsBackground_(True)

        paragraphStyle = NSMutableParagraphStyle.alloc().init()
        paragraphStyle.setLineHeightMultiple_(1.2)
        self.setDefaultParagraphStyle_(paragraphStyle)

        self.setUsesFindBar_(True)

        self.setAutomaticQuoteSubstitutionEnabled_(False)
        self.setAutomaticLinkDetectionEnabled_(False)
        self.setContinuousSpellCheckingEnabled_(False)
        self.setGrammarCheckingEnabled_(False)
        self.setAutomaticDashSubstitutionEnabled_(False)
        self.setAutomaticDataDetectionEnabled_(False)
        self.setAutomaticSpellingCorrectionEnabled_(False)
        self.setAutomaticTextReplacementEnabled_(False)

        self._codeColor = NSColor.blackColor()
        self._stderrColor = NSColor.blackColor()
        self._stdoutColor = NSColor.blackColor()
        self._glyphWidth = 1

        self._console = InteractiveConsole(locals=namespaceInjections)
        self._stderr = PseudoUTF8Output(self.writeStderr_)
        self._stdout = PseudoUTF8Output(self.writeStdout_)
        self._prompt = sys.ps1
        self.previousOutput = ""

        self._tabString = "  "

        self._minInsertionPoint = 0

        self._history = []
        self._historyIndex = 1

        return self

    # Settings

    def setTabString_(self, value):
        self._tabString = value

    def setFont_(self, value):
        super(PyREPLTextView, self).setFont_(value)
        self.getCharacterBox()

    def getCharacterBox(self):
        font = self.font()
        glyph = font.glyphWithName_("space")
        glyphWidth = font.advancementForGlyph_(glyph).width
        glyphHeight = font.pointSize() * self.defaultParagraphStyle().lineHeightMultiple()
        self._glyphWidth = glyphWidth
        self._glyphHeight = glyphHeight
        return glyphWidth, glyphHeight

    def setCodeColor_(self, color):
        self._codeColor = color
        self.setTextColor_(color)
        self.setInsertionPointColor_(color)

    def setStdoutColor_(self, color):
        self._stdoutColor = color

    def setStderrColor_(self, color):
        self._stderrColor = color

    def setShowInvisibles_(self, value):
        self.layoutManager().setShowsInvisibleCharacters_(value)

    # Raw Text

    def rawText(self):
        return self.textStorage().mutableString()

    def textLength(self):
        return len(self.rawText())

    # Input

    def scrollToEnd(self):
        index = self.textLength()
        self.scrollRangeToVisible_((index, 0))
        self.setSelectedRange_((index, 0))

    def keyDown_(self, event):
        if event.modifierFlags() & NSCommandKeyMask and event.characters() == "k":
            self.clear()
        elif event.modifierFlags() & NSCommandKeyMask and event.characters() == "c":
            pb = NSPasteboard.generalPasteboard()
            pb.clearContents()
            a = NSArray.arrayWithObject_(self.previousOutput)
            pb.writeObjects_(a)
        else:
            return super(PyREPLTextView, self).keyDown_(event)

    def insertNewline_(self, sender):
        line = self.currentLine()
        self.writeCode_("\n")
        self.executeLine_(line)
        self.writePrompt()

    insertNewlineIgnoringFieldEditor_ = insertNewline_

    def insertTab_(self, sender):
        self.writeLine_withColor_(self._tabString, self._codeColor)

    def insertBacktab_(self, sender):
        if self.currentLine().endswith(self._tabString):
            length = len(self._tabString)
            begin = self.textLength() - length
            textStorage = self.textStorage()
            textStorage.deleteCharactersInRange_((begin, length))

    def moveDown_(self, sender):
        self._historyIndex += 1
        if self._historyIndex > len(self._history):
            self._historyIndex = len(self._history)
            NSBeep()
        self._insertHistoryLine()

    def moveUp_(self, sender):
        self._historyIndex -= 1
        if self._historyIndex < 0:
            self._historyIndex = 0
            NSBeep()
        self._insertHistoryLine()

    def _insertHistoryLine(self):
        if self._historyIndex == len(self._history):
            text = ""
        else:
            text = self._history[self._historyIndex]
        text = self.makeAttributedString_withColor_(text, self._codeColor)
        begin = self._minInsertionPoint
        length = self.textLength() - begin
        textStorage = self.textStorage()
        textStorage.replaceCharactersInRange_withAttributedString_((begin, length), text)

    # Output

    def makeAttributedString_withColor_(self, text, color):
        attrs = {
            NSForegroundColorAttributeName : color,
            NSFontAttributeName : self.font(),
            NSParagraphStyleAttributeName : self.defaultParagraphStyle()
        }
        text = NSAttributedString.alloc().initWithString_attributes_(
            text,
            attrs
        )
        return text

    def writeLine_withColor_(self, line, color):
        line = self.makeAttributedString_withColor_(line, color)
        self.textStorage().appendAttributedString_(line)
        self.scrollToEnd()

    def writePrompt(self):
        self.writeCode_(self._prompt)
        self._minInsertionPoint = self.textLength()

    def writeCode_(self, text):
        self.writeLine_withColor_(text, self._codeColor)

    def writeStderr_(self, text):
        self.writeLine_withColor_(text, self._stderrColor)

    def writeStdout_(self, text):
        self.writeLine_withColor_(text, self._stdoutColor)

    def clear(self):
        self._minInsertionPoint = 0
        self.setString_("")
        self.writePrompt()

    # Execution

    def runSource_(self, source):
        save = (sys.stdout, sys.stderr)
        sys.stdout = self._stdout
        sys.stderr = self._stderr
        try:
            self._console.runsource(source)
        finally:
            sys.stdout, sys.stderr = save

    def currentLine(self):
        line = self.rawText().splitlines()[-1]
        line = line[len(self._prompt):]
        return line

    def executeLine_(self, line):
        if line == "help":
            self.writeStdout_(documentation)
            self.writeCode_("\n")
            return
        self._history.append(line)
        self._historyIndex = len(self._history)
        save = (sys.stdout, sys.stderr, self.rawText())
        sys.stdout = self._stdout
        sys.stderr = self._stderr
        more = False
        try:
            more = self._console.push(line)
            if more:
                self._prompt = sys.ps2
            else:
                self._prompt = sys.ps1
        except:
            self._prompt = sys.ps1
        finally:
            sys.stdout, sys.stderr, previousRawText = save
            self.previousOutput = self.rawText()[len(previousRawText):-1]

    # Selection, Insertion Point

    def textView_willChangeSelectionFromCharacterRange_toCharacterRange_(self, textView, fromRange, toRange):
        begin, length = toRange
        if length == 0:
            if begin < self._minInsertionPoint:
                NSBeep()
                begin = self._minInsertionPoint
            toRange = (begin, length)
        return toRange

    def textView_shouldChangeTextInRange_replacementString_(self, textView, aRange, newString):
        begin, length = aRange
        if begin < self._minInsertionPoint:
            return False
        return True

    def drawInsertionPointInRect_color_turnedOn_(self, rect, color, turnedOn):
        if hasattr(self, "_glyphWidth"):
            rect.size.width = self._glyphWidth
        super(PyREPLTextView, self).drawInsertionPointInRect_color_turnedOn_(rect, color, turnedOn)

    def setNeedsDisplayInRect_(self, rect):
        # Ugh: https://gist.github.com/koenbok/a1b8d942977f69ff102b
        if hasattr(self, "_glyphWidth"):
            rect.size.width += self._glyphWidth - 1
        super(PyREPLTextView, self).setNeedsDisplayInRect_(rect)

    # Auto Completion (adapted from DrawBot)

    def rangeForUserCompletion(self):
        charRange = super(PyREPLTextView, self).rangeForUserCompletion()
        text = self.string()
        partialString = text.substringWithRange_(charRange)
        if "." in partialString:
            dotSplit = partialString.split(".")
            partialString = dotSplit.pop()
            move = len(".".join(dotSplit))
            charRange.location += move + 1
            charRange.length = len(partialString)
        for c in partialString:
            if c not in variableChars:
                return (NSNotFound, 0)
        return charRange

    def completionsForPartialWordRange_indexOfSelectedItem_(self, charRange, index):
        if not haveJedi:
            return [], 0
        text = self.string()
        partialString = text.substringWithRange_(charRange)
        source = "\n".join(self._history + [self.currentLine()])
        namespace = self._console.locals
        script = jedi.Interpreter(source=source, namespaces=[namespace])
        completions = []
        for completion in script.completions():
            name = completion.name
            completions.append(name)
        return completions, 0

    def selectionRangeForProposedRange_granularity_(self, proposedRange, granularity):
        location = proposedRange.location
        if granularity == NSSelectByWord and proposedRange.length == 0 and location != 0:
            text = self.string()
            lenText = len(text)
            length = 1
            found = False
            while not found:
                location -= 1
                length += 1
                if location <= 0:
                    found = True
                else:
                    c = text.substringWithRange_((location, 1))[0]
                    if c not in variableChars:
                        location += 1
                        found = True
            found = False
            while not found:
                length += 1
                if location + length >= lenText:
                    found = True
                else:
                    c = text.substringWithRange_((location, length))[-1]
                    if c not in variableChars:
                        length -= 1
                        found = True
            return location, length
        else:
            return super(PyREPLTextView, self).selectionRangeForProposedRange_granularity_(proposedRange, granularity)

    # Drop

    def readSelectionFromPasteboard_type_(self, pboard, pbType):
        if pbType == NSFilenamesPboardType:
            paths = pboard.propertyListForType_(NSFilenamesPboardType)
            dropText = ""
            if len(paths) == 1:
                dropText = 'u"%s"' % paths[0]
            else:
                formattedPaths = []
                for path in paths:
                    formattedPaths.append('u"%s"' % path)
                dropText = "[%s]" % ", ".join(formattedPaths)
            if dropText:
                self.insertText_(dropText)
                return True
        return super(PyREPLTextView, self).readSelectionFromPasteboard_type_(pboard, pbType)
Esempio n. 30
0
class Console:
    """Console object"""
    def __init__(self, font, toggle_key=None):
        """Console constructor

		Arguments:
			font - path to font file
			toggle_key - keycode to enable/disable console"""
        global SCROLLBACK, WRAP
        self.toggle_key = toggle_key

        self.active = False

        # GUI
        view_buf = Buffer(GL_INT, 4)
        glGetIntegerv(GL_VIEWPORT, view_buf)
        view = view_buf.to_list()

        self.text_size = [None] * 2

        self.text_fontid = blf.load(font) if font else 0
        blf.size(self.text_fontid, 14, 72)
        self.text_size[0], self.text_size[1] = blf.dimensions(
            self.text_fontid, "W")
        self._text = ''

        SCROLLBACK = int(SCROLLBACK / (2 * self.text_size[1]))
        WRAP = int(WRAP / (self.text_size[0]))

        # Console
        self.namespace = default_namespace()
        self.console = InteractiveConsole(self.namespace)
        self.cursor = 0
        self.edit_text = ''
        self.scrollback = []
        self.history = ['']
        self.is_multiline = False

        message = """Interactive Console"""
        self.add_scrollback(message)

    def _get_text(self):
        return self._text

    def set_text(self, value):
        self.text_size[0], self.text_size[1] = blf.dimensions(
            self.text_fontid, value)

        #self._update_position(size, self._base_pos)

        self._text = value

    def render(self):
        """Renders the GUI system"""
        ww = bge.render.getWindowWidth()
        wh = bge.render.getWindowHeight()
        # Get some viewport info
        view_buf = Buffer(GL_INT, 4)
        glGetIntegerv(GL_VIEWPORT, view_buf)
        view = view_buf.to_list()

        # Save the state
        glPushMatrix()
        glPushAttrib(GL_ALL_ATTRIB_BITS)

        # Diable depth test so we always draw over things
        glDisable(GL_DEPTH_TEST)

        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        # Setup the matrices
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(0, view[2], 0, view[3])
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

        # Render the windows
        glColor4f(0.3, 0.3, 0.3, 0.5)
        glBegin(GL_QUADS)
        glVertex2f(0, 2 * wh / 3)
        glVertex2f(ww, 2 * wh / 3)
        glVertex2f(ww, wh)
        glVertex2f(0, wh)
        glEnd()

        glColor4f(0.0, 0.0, 0.0, 1.0)
        glBegin(GL_LINE_STRIP)
        glVertex2f(0, 2 * wh / 3)
        glVertex2f(ww, 2 * wh / 3)
        glEnd()

        blf.size(self.text_fontid, 14, 72)

        glColor4f(1, 1, 1, 1)

        for i, txt in enumerate([i for i in self._text.split('\n')]):
            blf.position(self.text_fontid, 20,
                         wh + 20 - (self.text_size[1] * (i - 1)), 0)
            blf.draw(self.text_fontid, txt.replace('\t', '    '))

        # Reset the state
        glPopAttrib()
        glPopMatrix()

    def prev_char(self):
        cursor = self.cursor - 1
        if cursor < 0:
            return None

        try:
            return self.edit_text[cursor]
        except:
            return None

    def next_char(self):
        try:
            return self.edit_text[self.cursor]
        except:
            return None

    def fill_scrollback(self):
        sb = self.scrollback
        while len(sb) < SCROLLBACK:
            sb.append('')

        while len(sb) > SCROLLBACK:
            sb.pop(0)

    def add_scrollback(self, data):
        sb = self.scrollback

        if isinstance(data, str):
            data = data.split("\n")

        for line in data:
            while len(line) > WRAP:
                sb.append(line[:WRAP])
                line = line[WRAP:]
            sb.append(line)

        self.fill_scrollback()

    def cursor_left_step(self):
        self.cursor = max(0, self.cursor - 1)

    def cursor_right_step(self):
        self.cursor = min(len(self.edit_text), self.cursor + 1)

    def cursor_right_jump(self):
        if self.cursor >= len(self.edit_text):
            return

        cursor_prev = self.cursor
        while (not is_delimiter(self.edit_text[self.cursor])):
            self.cursor_right_step()
            if cursor_prev == self.cursor:
                break
            cursor_prev = self.cursor
            if self.cursor >= len(self.edit_text):
                return

        if self.cursor >= len(self.edit_text):
            return

        cursor_prev = self.cursor
        while is_delimiter(self.edit_text[self.cursor]):
            self.cursor_right_step()
            if cursor_prev == self.cursor:
                break
            cursor_prev = self.cursor
            if self.cursor >= len(self.edit_text):
                return

    def cursor_left_jump(self):
        if self.cursor == 0:
            return

        cursor_prev = self.cursor
        while (not is_delimiter(self.edit_text[self.cursor - 1])):
            self.cursor_left_step()
            if cursor_prev == self.cursor:
                break
            cursor_prev = self.cursor
            if self.cursor == 0:
                return

        cursor_prev = self.cursor
        while (is_delimiter(self.edit_text[self.cursor - 1])):
            self.cursor_left_step()
            if cursor_prev == self.cursor:
                break
            cursor_prev = self.cursor

    def cursor_backspace_step(self):
        if self.cursor == 0:
            pass
        elif self.cursor == len(self.edit_text):
            self.edit_text = self.edit_text[:-1]
        else:
            self.edit_text = self.edit_text[:self.cursor -
                                            1] + self.edit_text[self.cursor:]

        self.cursor_left_step()

    def cursor_backspace_jump(self):
        cursor_prev = self.cursor
        self.cursor_left_jump()
        if cursor_prev != self.cursor:
            self.edit_text = self.edit_text[:self.cursor] + self.edit_text[
                cursor_prev:]

    def cursor_delete_step(self):
        if self.cursor == 0:
            self.edit_text = self.edit_text[1:]
        elif self.cursor == len(self.edit_text):
            pass
        else:
            self.edit_text = self.edit_text[:self.cursor] + self.edit_text[
                self.cursor + 1:]

    def cursor_delete_jump(self):
        cursor_prev = self.cursor
        self.cursor_right_jump()
        if cursor_prev != self.cursor:
            self.edit_text = self.edit_text[:cursor_prev] + self.edit_text[
                self.cursor:]
        self.cursor = cursor_prev

    def cursor_insert_char(self, ch):
        if self.cursor == 0:
            self.edit_text = ch + self.edit_text
        elif self.cursor == len(self.edit_text):
            self.edit_text = self.edit_text + ch
        else:
            self.edit_text = self.edit_text[:self.
                                            cursor] + ch + self.edit_text[
                                                self.cursor:]

        if self.cursor > len(self.edit_text):
            self.cursor = len(self.edit_text)
        self.cursor_right_step()

    def cursor_home(self):
        self.cursor = 0

    def cursor_end(self):
        self.cursor = len(self.edit_text)

    def history_up(self):
        hs = self.history

        hs[0] = self.edit_text
        hs.append(hs.pop(0))
        self.edit_text = hs[0]
        self.cursor_end()

    def history_down(self):
        hs = self.history

        hs[0] = self.edit_text
        hs.insert(0, hs.pop())
        self.edit_text = hs[0]
        self.cursor_end()

    def execute(self):
        self.add_scrollback(self.get_text_commandline())
        stdout_redir = fileRedirect(False)
        stderr_redir = fileRedirect(True)

        sys.stdout = stdout_redir
        sys.stderr = stderr_redir

        if not self.edit_text.strip():
            pytext = '\n'  # executes a multiline statement
        else:
            pytext = self.edit_text

        self.is_multiline = self.console.push(pytext)

        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__
        sys.last_trackback = None

        output = stdout_redir.read()
        stdout_redir.close()

        if output:
            self.add_scrollback(output)  # could be stderr_redit too
        # Avoid double ups, add the new one at the front
        if pytext != '\n':
            if self.edit_text in self.history:
                self.history.remove(self.edit_text)

            self.history.insert(0, self.edit_text)

            if '' in self.history:
                self.history[:] = [v for v in self.history if v]

            self.history.insert(0, '')
            self.edit_text = ''

        self.cursor_end()

    def autocomp(self):
        def do_autocomp(autocomp_prefix, autocomp_members):
            '''
			return text to insert and a list of options
			'''
            autocomp_members = [
                v for v in autocomp_members if v.startswith(autocomp_prefix)
            ]

            if not autocomp_prefix:
                return '', autocomp_members
            elif len(autocomp_members) > 1:
                # find a common string between all members after the prefix
                # 'ge' [getA, getB, getC] --> 'get'

                # get the shortest member
                min_len = min([len(v) for v in autocomp_members])

                autocomp_prefix_ret = ''

                for i in xrange(len(autocomp_prefix), min_len):
                    char_soup = set()
                    for v in autocomp_members:
                        char_soup.add(v[i])

                    if len(char_soup) > 1:
                        break
                    else:
                        autocomp_prefix_ret += char_soup.pop()

                return autocomp_prefix_ret, autocomp_members
            elif len(autocomp_members) == 1:
                return autocomp_members[0][len(autocomp_prefix):], []
            else:
                return '', []

        TEMP_NAME = '___tempname___'

        cursor_orig = self.cursor

        ch = self.prev_char()
        while ch != None and (not is_delimiter(ch)):
            ch = self.prev_char()
            self.cursor_left_step()

        if ch != None:
            self.cursor_right_step()

        cursor_base = self.cursor

        autocomp_prefix = self.edit_text[cursor_base:cursor_orig]

        # Get the previous word
        if self.prev_char == '.':
            self.cursor_left_step()
            ch = self.prev_char()
            while ch != None and is_delimiter_autocomp(ch) == False:
                ch = self.prev_char()
                self.cursor_left_step()

            cursor_new = self.cursor

            if ch != None:
                cursor_new += 1

            pytxt = self.edit_text[cursor_new:cursor_base - 1]
            if pytxt:
                self.console.runsource(TEMP_NAME + '=' + pytxt, '<input>',
                                       'single')
            else:
                val = None

            try:
                val = self.namespace[TEMP_NAME]
                del self.namespace[TEMP_NAME]
            except:
                val = None

            if val:
                autocomp_members = dir(val)

                autocomp_prefix_ret, autocomp_members = do_autocomp(
                    autocomp_prefix, autocomp_members)

                self.cursor = cursor_orig
                for v in autocomp_prefix_ret:
                    self.cursor_insert_char(v)
                cursor_orig = self.cusor

                if autocomp_members:
                    self.add_scrollback(', '.join(autocomp_members))

            del val

        else:
            # Autocomp global namespace
            autocomp_members = self.namespace.keys()

            if autocomp_prefix:
                autocomp_members = [
                    v for v in autocomp_members
                    if v.startswith(autocomp_prefix)
                ]

            autocomp_prefix_ret, autocomp_members = do_autocomp(
                autocomp_prefix, autocomp_members)

            self.cursor = cursor_orig
            for v in autocomp_prefix_ret:
                self.cursor_insert_char(v)
            cursor_orig = self.cursor

            if autocomp_members:
                self.add_scrollback(', '.join(autocomp_members))

        self.cursor = cursor_orig

    def get_text_commandline(self):
        self.fill_scrollback()

        if self.is_multiline:
            prefix = PROMPT_MULTI
        else:
            prefix = PROMPT

        return prefix + self.edit_text

    def get_text(self):
        self.fill_scrollback()
        return '\n'.join(self.scrollback) + '\n' + self.get_text_commandline()

    def handle_input(self):
        keyboard = bge.logic.keyboard

        key_events = keyboard.events

        is_shift = key_events[bge.events.LEFTSHIFTKEY] == bge.logic.KX_INPUT_ACTIVE or \
           key_events[bge.events.RIGHTSHIFTKEY] == bge.logic.KX_INPUT_ACTIVE
        is_ctrl = key_events[bge.events.LEFTCTRLKEY] == bge.logic.KX_INPUT_ACTIVE or \
           key_events[bge.events.RIGHTCTRLKEY] == bge.logic.KX_INPUT_ACTIVE

        # First deal with important keys
        if key_events[
                bge.events.LEFTARROWKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.cursor_left_jump() if is_ctrl else self.cursor_left_step()
            return
        if key_events[
                bge.events.RIGHTARROWKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.cursor_right_jump() if is_ctrl else self.cursor_right_step()
            return
        if key_events[
                bge.events.BACKSPACEKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.cursor_backspace_jump(
            ) if is_ctrl else self.cursor_backspace_step()
            return
        if key_events[bge.events.DELKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.cursor_delete_jump() if is_ctrl else self.cursor_delete_step()
            return
        if key_events[bge.events.HOMEKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.cursor_home()
            return
        if key_events[bge.events.ENDKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.cursor_end()
            return
        if key_events[bge.events.RETKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.execute()
            return
        if key_events[
                bge.events.UPARROWKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.history_up()
            return
        if key_events[
                bge.events.DOWNARROWKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.history_down()
            return
        if key_events[bge.events.TABKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            self.autocomp()
            return

        # Deal with characters
        for evt, val in keyboard.events.items():
            if val == bge.logic.KX_INPUT_JUST_ACTIVATED and evt != self.toggle_key:
                ch = bge.events.EventToCharacter(evt, is_shift)
                if ch:
                    self.cursor_insert_char(ch)

    def main(self):
        if self.toggle_key:
            if bge.logic.keyboard.events[
                    self.toggle_key] == bge.logic.KX_INPUT_JUST_ACTIVATED:
                self.active = not self.active

        if self.active == True:
            self.handle_input()

            text = self.get_text()
            n = len(text) - len(self.edit_text)
            text = text[:n + self.cursor] + "_" + text[n + self.cursor:]
            self.text = text

            if self.render not in bge.logic.getCurrentScene().post_draw:
                bge.logic.getCurrentScene().post_draw.append(self.render)
        else:
            if self.render in bge.logic.getCurrentScene().post_draw:
                bge.logic.getCurrentScene().post_draw.remove(self.render)

    text = property(_get_text, set_text)
Esempio n. 31
0
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.init_default_cfg()

        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)

        self.font = pygame.font.Font('views/DroidSansMono.ttf', 12)

        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)
        self.set_interpreter()

    ##################
    #-Initialization-#
    def init_default_cfg(self):
        self.bg_alpha = 175
        self.bg_color = [0x0, 0x44, 0xAA]
        self.txt_color_i = [0xFF, 0xFF, 0xFF]
        self.txt_color_o = [0xEE, 0xEE, 0xEE]
        self.ps1 = "] "
        self.ps2 = ">>> "
        self.ps3 = "... "
        self.active = True
        self.repeat_rate = [500, 30]
        self.python_mode = False
        self.preserve_events = False
        self.motd = [
            "Press Ctrl_w to hide the console",
            "One day this will have more to say"
        ]

    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:
            raise

    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
        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):
        #self.output("Entering Python mode")
        self.python_interpreter = InteractiveConsole()
        self.tmp_fds = []
        self.py_fds = [Writable() for i in range(3)]
        self.c_ps = self.ps2

    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
        self.send_python(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()

    ####################################################
    #-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):
        '''\
        Loop through pygame events and evaluate them
        '''
        if not self.active:
            return

        if self.preserve_events:
            eventlist = pygame.event.get(KEYDOWN)
        else:
            eventlist = pygame.event.get()

        for event in eventlist:
            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)

    ##########################
    #-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'
            )
Esempio n. 32
0
 def runsource(self, source, *args):
     self.last_buffer = [source.encode("utf-8")]
     return InteractiveConsole.runsource(self, source, *args)
Esempio n. 33
0
		def runsource(self, source, *args):
			from Vivaldi_translator_layer import line_translator
			source = line_translator(source, data_package_list)
	
			self.last_buffer = [ source.encode('latin-1') ]
			return InteractiveConsole.runsource(self, source, *args)
Esempio n. 34
0
class Console:
    def __init__(self, screen, rect, functions={}, key_calls={}, vars={}):
        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.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)

        self.font = pygame.font.Font("../gfx/fixed_width.ttf", 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("#")[WIDTH]) - 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
        #	if self.python_mode:
        #		self.c_ps = self.ps2
        #	else:
        #		self.c_ps = self.ps1

        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)

    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.
		   functions -- dictionary of functions to add"""
        if isinstance(functions, dict):
            self.func_calls.update(functions)

    def add_key_calls(self, functions):
        """Add functions to the key_calls dictionary.
		   functions -- dictionary of key_calls to add"""
        if isinstance(functions, dict):
            self.key_calls.update(functions)

    def clear(self):
        """Clear the Screen"""
        self.c_out = ["[Screen Cleared]"]
        self.c_scroll = 0

    def help(self, *args):
        """Output information about functions
		   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"))
                # TODO: function doc get funny formatting, so need to fiddle here
                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'
            )

    def output(self, text):
        """Prepare text to be displayed
		   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:
            print text

    def set_active(self, b=None):
        """Activate or Deactivate the console. Pass with b-
		   Optional boolean argument, True=Activate False=Deactivate"""
        if not b:
            self.active = not self.active
        else:
            self.active = b

    def set_interpreter(self):
        if self.python_mode:
            # spqr tries to reduce console ouput,but we can still
            # have some debugging info
            if (SPQR.DEBUG_MODE == True):
                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:
            if (SPQR.DEBUG_MODE == True):
                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 format_input_line(self):
        '''\
		Format input line to be displayed
		'''
        text = self.c_in[:self.c_pos] + "|" + self.c_in[self.c_pos:]
        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)

    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 to the python interpreter 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"""
        # Output a blank row if nothing is entered
        if not text:
            self.output("")
            return

        self.add_to_history(text)
        # Check if the text is in the form: name = value
        assign = re_is_assign.match(text)
        try:
            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

        try:
            if (len(tokens) is 1) and re_is_var.match(text) and not assign:
                out = tokens[0]
            else:
                out = self.func_calls[tokens[0]](*tokens[1:])
        except (KeyError, TypeError):
            if (len(tokens) is 1) and assign:
                self.setvar(assign.group('name'), tokens[0])
            else:
                self.output("Unknown Command: " + str(tokens[0]))
                self.output(r'Type "help" for a list of commands.')
        else:
            self.output(out)
Esempio n. 35
0
 def runsource(self, source, *args):
     self.last_buffer = [ source.encode('latin-1') ]
     return InteractiveConsole.runsource(self, source, *args)
Esempio n. 36
0
#! /usr/bin/env python

import os.path

from code import InteractiveConsole
from deployment import Deployment

D = Deployment()

console = InteractiveConsole(locals={"D": D, "ec2": D.ec2})
pyrc = os.path.expanduser(os.path.join("~", ".pythonrc.py"))
if os.path.exists(pyrc):
    console.runsource(open(pyrc).read())
console.interact()