class CommandCompleter(object):
  
  def __init__(self, local_vars):
    super(CommandCompleter, self).__init__()
    self._locals = local_vars
    self._make_completer()
    self._n = 0
    self._text = ''
    
  def _make_completer(self):
    l = {}
    l.update(builtins.__dict__)
    l.update(locals())
    l.update(self._locals)
    self._completer = Completer(l)
    
  def complete_start(self, text):
    self._make_completer()
    self._text = text
    self._n = -1
    return self.complete()
    
  def complete(self):
    self._n += 1
    suggest = self._completer.complete(self._text, self._n)
    return suggest
    
  def complete_back(self):
    self._n -= 1
    if self._n < 0:
      self._n = 0
      return None
    suggest = self._completer.complete(self._text, self._n)
    return suggest
Пример #2
0
        def handle_TAB(self):
            """
            Trap the TAB keystroke.
            """
            necessarypart = "".join(self.lineBuffer).split(" ")[-1]
            completer = Completer(globals())
            if completer.complete(necessarypart, 0):
                matches = list(set(completer.matches))  # has multiples

                if len(matches) == 1:
                    length = len(necessarypart)
                    self.lineBuffer = self.lineBuffer[:-length]
                    self.lineBuffer.extend(matches[0])
                    self.lineBufferIndex = len(self.lineBuffer)
                else:
                    matches.sort()
                    commons = self.find_common(matches)
                    if commons:
                        length = len(necessarypart)
                        self.lineBuffer = self.lineBuffer[:-length]
                        self.lineBuffer.extend(commons)
                        self.lineBufferIndex = len(self.lineBuffer)

                    self.terminal.nextLine()
                    while matches:
                        matches, part = matches[4:], matches[:4]
                        for item in part:
                            self.terminal.write("%s" % item.ljust(30))
                            self.terminal.write("\n")
                            self.terminal.nextLine()

                self.terminal.eraseLine()
                self.terminal.cursorBackward(self.lineBufferIndex + 5)
                self.terminal.write("%s %s" % (self.ps[self.pn], "".join(self.lineBuffer)))
Пример #3
0
    def handle_TAB(self):
        necessarypart = "".join(self.lineBuffer).split(' ')[-1]

        completer = Completer(globals())
        if completer.complete(necessarypart, 0):
            matches = list(set(completer.matches))  # has multiples
            if len(matches) == 1:
                length = len(necessarypart)
                self.lineBuffer = self.lineBuffer[:-length]
                self.lineBuffer.extend(matches[0])
                self.lineBufferIndex = len(self.lineBuffer)
            else:
                matches.sort()
                commons = self.find_common(matches)
                if commons:
                    length = len(necessarypart)
                    self.lineBuffer = self.lineBuffer[:-length]
                    self.lineBuffer.extend(commons)
                    self.lineBufferIndex = len(self.lineBuffer)
                self.terminal.nextLine()
                while matches:
                    matches, part = matches[4:], matches[:4]
                    for item in part:
                        self.terminal.write('%s' % item.ljust(30))
                    self.terminal.write('\n')
                self.terminal.nextLine()
            self.terminal.eraseLine()
            self.terminal.cursorBackward(self.lineBufferIndex + 5)
            self.terminal.write("%s %s" %
                                (self.ps[self.pn], "".join(self.lineBuffer)))
Пример #4
0
	def complete(self,text,state):
		if text.endswith(".__doc__"):
			new_text = text.replace(".__doc__","")
			help(eval(new_text))
			readline.redisplay()
			readline.insert_text(new_text)
		else:
			value = Completer.complete(self,text,state)
		return value
Пример #5
0
    def keyPressEvent(self, event):
        qt = QtCore.Qt
        if event.key() == qt.Key_Tab:
            line = str(self.document().lastBlock().text())[4:]
            completer = Completer(self.interpreter.locals)
            suggestion = completer.complete(line, 0)
            if suggestion is not None:
                self.insertPlainText(suggestion[len(line):])
            return None

        if event.key() == qt.Key_Down:
            if self.historyIndex == len(self.history):
                self.historyIndex -= 1
            try:
                if self.historyIndex > -1:
                    self.historyIndex -= 1
                    self.recallHistory()
                else:
                    self.clearCurrentBlock()
            except Exception:
                pass
            return None

        if event.key() == qt.Key_Up:
            try:
                if len(self.history) - 1 > self.historyIndex:
                    self.historyIndex += 1
                    self.recallHistory()
                else:
                    self.historyIndex = len(self.history)
            except Exception:
                pass
            return None

        if event.key() == qt.Key_Home:
            # set cursor to position 4 in current block. 4 because that's where
            # the marker stops
            blockLength = len(self.document().lastBlock().text()[4:])
            lineLength = len(self.document().toPlainText())
            position = lineLength - blockLength
            textCursor = self.textCursor()
            textCursor.setPosition(position)
            self.setTextCursor(textCursor)
            return None

        if event.key() in [qt.Key_Left, qt.Key_Backspace]:
            # don't allow deletion of marker
            if self.textCursor().positionInBlock() == 4:
                return None

        if event.key() in [qt.Key_Return, qt.Key_Enter]:
            self.doEnter(event)
            return None

        # allow all other key events
        super(PyInterp, self).keyPressEvent(event)
Пример #6
0
        def keyPressEvent(self, event):
            qt = QtCore.Qt
            if event.key() == qt.Key_Tab:
                line = str(self.document().lastBlock().text())[4:]
                completer = Completer(self.interpreter.locals)
                suggestion = completer.complete(line, 0)
                if suggestion is not None:
                    self.insertPlainText(suggestion[len(line):])
                return None

            if event.key() == qt.Key_Down:
                if self.historyIndex == len(self.history):
                    self.historyIndex -= 1
                try:
                    if self.historyIndex > -1:
                        self.historyIndex -= 1
                        self.recallHistory()
                    else:
                        self.clearCurrentBlock()
                except Exception:
                    pass
                return None

            if event.key() == qt.Key_Up:
                try:
                    if len(self.history) - 1 > self.historyIndex:
                        self.historyIndex += 1
                        self.recallHistory()
                    else:
                        self.historyIndex = len(self.history)
                except Exception:
                    pass
                return None

            if event.key() == qt.Key_Home:
                # set cursor to position 4 in current block. 4 because that's where
                # the marker stops
                blockLength = len(self.document().lastBlock().text()[4:])
                lineLength  = len(self.document().toPlainText())
                position = lineLength - blockLength
                textCursor  = self.textCursor()
                textCursor.setPosition(position)
                self.setTextCursor(textCursor)
                return None

            if event.key() in [qt.Key_Left, qt.Key_Backspace]:
                # don't allow deletion of marker
                if self.textCursor().positionInBlock() == 4:
                    return None

            if event.key() in [qt.Key_Return, qt.Key_Enter]:
                self.doEnter(event)
                return None
                
            # allow all other key events
            super(PyInterp, self).keyPressEvent(event)
Пример #7
0
    def complete(self, text, state):
        # Don't show all objects if we're typing in code
        if self.current_prompt == sys.ps2:
            if state == 0:
                if text == '':
                    return '    '
            else:
                return None

        return Completer.complete(self, text, state)
Пример #8
0
class CommandCompleter(object):
    def __init__(self, local_vars):
        super(CommandCompleter, self).__init__()
        self._locals = local_vars
        self._make_completer()
        self._n = 0
        self._text = ''

    def _make_completer(self):
        l = {}
        l.update(builtins.__dict__)
        l.update(locals())
        l.update(self._locals)
        self._completer = Completer(l)

    def complete_start(self, text):
        self._make_completer()
        self._text = text
        self._n = -1

        return self.complete()

    def complete(self):
        self._n += 1
        suggest = self._completer.complete(self._text, self._n)

        return suggest

    def complete_back(self):
        self._n -= 1

        if self._n < 0:
            self._n = 0
            return None

        suggest = self._completer.complete(self._text, self._n)

        return suggest
Пример #9
0
    def handle_TAB(self):
        text = "".join(self.lineBuffer).split(' ')[-1]
        if len(text) == 0:
            # Bell character
            self.terminal.write("\a")
            return

        completer = Completer(self.namespace)

        if completer.complete(text, 0):
            allMatches = list(set(completer.matches))

            # Get rid of a bunch of cruft
            builtins = __builtin__.keys()
            matches = [
                x for x in allMatches
                if x.strip('(') not in builtins and "__" not in x
            ]
            matches.sort()

            # If there are no matches, ring the terminal bell
            # If there's only one match, autocomplete it
            # If there's more than one match, print a list of matches
            if len(matches) == 0:
                self.terminal.write("\a")
                return
            elif len(matches) == 1:
                length = len(text)
                self.lineBuffer = self.lineBuffer[:-length]
                self.lineBuffer.extend(matches[0])
                self.lineBufferIndex = len(self.lineBuffer)
            else:
                # Remove text before the last dot, for brevity
                if "." in matches[0]:
                    matches = [x[x.rfind(".") + 1:] for x in matches]
                self.terminal.nextLine()
                self.terminal.write(repr(matches))
                self.terminal.nextLine()
                self.terminal.write("%s%s" % (self.ps[self.pn], ""))

            self.terminal.eraseLine()
            self.terminal.cursorBackward(self.lineBufferIndex + 5)
            self.terminal.write("%s%s" %
                                (self.ps[self.pn], "".join(self.lineBuffer)))

        else:
            self.terminal.write("\a")
Пример #10
0
def _complete(text, globals_):
    """
    Gets the completions for text from the exec globals.  Returns a sorted
    list.
    """
    from rlcompleter import Completer

    ctr = Completer(globals_)
    i = 0
    comps = []
    while 1:
        c = ctr.complete(text, i)
        if c is None:
            break
        comps.append(c)
        i += 1
    comps = tuple(sorted(frozenset(comps)))
    return comps
Пример #11
0
class InteractiveConsole(BaseInteractiveConsole):
    def __init__(self, ls):
        BaseInteractiveConsole.__init__(self, ls)
        self.stdout = sys.stdout = sys.stderr = Stdout()
        self.completer = Completer(dict(self.locals))
    def push(self, line):
        result = BaseInteractiveConsole.push(self, line)
        return (result, self.stdout.get_buffer())
    def complete(self, text):
        state = 0
        comps = []
        while True:
            self.completer.namespace = dict(self.locals)
            result = self.completer.complete(text, state)
            if result is None:
                break
            comps.append(result)
            state += 1
        return comps
Пример #12
0
 def complete(self, text, state):
     if text == '':
         # you could replace '    ' to \t if you indent via tab
         return ['    ', None][state]
     elif text.count("'") == 1:
         if not state:
             self.file_matches(text, "'")
         try:
             return self.matches[state]
         except IndexError:
             return None
     elif text.count('"') == 1:
         if not state:
             self.file_matches(text, '"')
         try:
             return self.matches[state]
         except IndexError:
             return None
     else:
         return Completer.complete(self, text, state)
Пример #13
0
 def complete(self, text, state):
     if text == '':
         # you could replace '    ' to \t if you indent via tab                                                                                                             
         return ['    ', None][state]
     elif text.count("'") == 1:
         if not state:
             self.file_matches(text, "'")
         try:
             return self.matches[state]
         except IndexError:
             return None
     elif text.count('"') == 1:
         if not state:
             self.file_matches(text, '"')
         try:
             return self.matches[state]
         except IndexError:
             return None
     else:
         return Completer.complete(self, text, state)
Пример #14
0
 def getSuggestions(self, line):
     from rlcompleter import Completer
     def _inRange(i):
         if MAX_COMPLETIONS <= 0:
             # No limit
             return True
         else:
             return i <= MAX_COMPLETIONS
     result = []
     completer = Completer(self.globals)
     i = 0
     suggestion = True
     while suggestion and _inRange(i):
         suggestion = completer.complete(line, i)
         if suggestion:
             if i == MAX_COMPLETIONS and MAX_COMPLETIONS != 0:
                 result.append('...')
             else:
                 if suggestion not in result:
                     result.append(suggestion)
         i += 1
     return result
Пример #15
0
 def getSuggestions(self, line):
     from rlcompleter import Completer
     def _inRange(i):
         if MAX_COMPLETIONS <= 0:
             # No limit
             return True
         else:
             return i <= MAX_COMPLETIONS
     result = []
     completer = Completer(self.globals)
     i = 0
     suggestion = True
     while suggestion and _inRange(i):
         suggestion = completer.complete(line, i)
         if suggestion:
             if i == MAX_COMPLETIONS and MAX_COMPLETIONS != 0:
                 result.append('...')
             else:
                 if suggestion not in result:
                     result.append(suggestion)
         i += 1
     return result
Пример #16
0
class GTKInterpreterConsole(Gtk.ScrolledWindow):
    """
    An InteractiveConsole for GTK. It's an actual widget,
    so it can be dropped in just about anywhere.
    """

    __gtype_name__ = "GTKInterpreterConsole"

    def __init__(self, locals: Dict[str, object], banner=banner):
        Gtk.ScrolledWindow.__init__(self)
        self.locals = locals
        locals["help"] = Help()

        self.set_min_content_width(640)
        self.set_min_content_height(480)
        self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)

        self.text = Gtk.TextView()
        self.text.set_wrap_mode(True)
        self.text.set_monospace(True)
        self.text.set_border_width(4)

        self.interpreter = code.InteractiveInterpreter(locals)

        self.completer = Completer(locals)
        self.buffer: List[str] = []
        self.history: List[str] = []
        self.banner = banner
        self.ps1 = ">>> "
        self.ps2 = "... "

        self.text.add_events(Gdk.EventMask.KEY_PRESS_MASK)
        self.text.connect("key_press_event", self.key_pressed)

        self.current_history = -1

        self.mark = self.text.get_buffer().create_mark(
            "End", self.text.get_buffer().get_end_iter(), False
        )

        # setup colors
        self.style_banner = Gtk.TextTag.new("banner")
        self.style_banner.set_property("foreground", "saddle brown")

        self.style_ps1 = Gtk.TextTag.new("ps1")
        self.style_ps1.set_property("foreground", "DarkOrchid4")
        self.style_ps1.set_property("editable", False)

        self.style_ps2 = Gtk.TextTag.new("ps2")
        self.style_ps2.set_property("foreground", "DarkOliveGreen")
        self.style_ps2.set_property("editable", False)

        self.style_out = Gtk.TextTag.new("stdout")
        self.style_out.set_property("foreground", "midnight blue")
        self.style_out.set_property("editable", False)
        self.style_err = Gtk.TextTag.new("stderr")
        self.style_err.set_property("style", Pango.Style.ITALIC)
        self.style_err.set_property("foreground", "red")
        self.style_err.set_property("editable", False)

        self.text.get_buffer().get_tag_table().add(self.style_banner)
        self.text.get_buffer().get_tag_table().add(self.style_ps1)
        self.text.get_buffer().get_tag_table().add(self.style_ps2)
        self.text.get_buffer().get_tag_table().add(self.style_out)
        self.text.get_buffer().get_tag_table().add(self.style_err)

        self.stdout = TextViewWriter("stdout", self.text, self.style_out)
        self.stderr = TextViewWriter("stderr", self.text, self.style_err)

        self.current_prompt = lambda: ""

        self.add(self.text)
        self.text.show()

        self.write_line(self.banner, self.style_banner)
        self.prompt_ps1()

    def reset_history(self):
        self.history = []

    def reset_buffer(self):
        self.buffer = []

    def prompt_ps1(self):
        self.current_prompt = self.prompt_ps1
        self.write_line(self.ps1, self.style_ps1)

    def prompt_ps2(self):
        self.current_prompt = self.prompt_ps2
        self.write_line(self.ps2, self.style_ps2)

    def write_line(self, text, style=None):
        start, end = self.text.get_buffer().get_bounds()
        if style:
            self.text.get_buffer().insert_with_tags(end, text, style)
        else:
            self.text.get_buffer().insert(end, text)

        self.text.scroll_to_mark(self.mark, 0, True, 1, 1)

    def push(self, line):
        self.buffer.append(line)
        if len(line) > 0:
            self.history.append(line)

        source = "\n".join(self.buffer)

        with self.stdout, self.stderr:
            more = self.interpreter.runsource(source, "<<console>>")

        if not more:
            self.reset_buffer()

        return more

    def key_pressed(self, widget, event):
        if event.keyval == Gdk.keyval_from_name("Return"):
            return self.execute_line()
        if event.keyval == Gdk.keyval_from_name("Tab"):
            return self.complete_line()

        if event.keyval == Gdk.keyval_from_name("Up"):
            self.current_history = self.current_history - 1
            if self.current_history < -len(self.history):
                self.current_history = -len(self.history)
            return self.show_history()
        if event.keyval == Gdk.keyval_from_name("Down"):
            self.current_history = self.current_history + 1
            if self.current_history > 0:
                self.current_history = 0
            return self.show_history()

        ctrl = event.state & Gdk.ModifierType.CONTROL_MASK
        if (event.keyval == Gdk.keyval_from_name("Home")) or (
            ctrl and event.keyval == Gdk.KEY_a
        ):
            line_count = self.text.get_buffer().get_line_count() - 1
            start = self.text.get_buffer().get_iter_at_line_offset(line_count, 4)
            self.text.get_buffer().place_cursor(start)
            return True

        if ctrl and event.keyval == Gdk.KEY_e:
            end = self.text.get_buffer().get_end_iter()
            self.text.get_buffer().place_cursor(end)
            return True

        return False

    def show_history(self):
        if self.current_history != 0:
            self.replace_line(self.history[self.current_history])

        return True

    def current_line(self):
        start, end = self.current_line_bounds()
        return self.text.get_buffer().get_text(start, end, True)

    def current_line_bounds(self):
        txt_buffer = self.text.get_buffer()
        line_count = txt_buffer.get_line_count() - 1

        start = txt_buffer.get_iter_at_line(line_count)
        if start.get_chars_in_line() >= 4:
            start.forward_chars(4)
        end = txt_buffer.get_end_iter()
        return start, end

    def replace_line(self, txt):
        start, end = self.current_line_bounds()
        self.text.get_buffer().delete(start, end)
        self.write_line(txt)

    def execute_line(self):
        line = self.current_line()

        self.write_line("\n")

        more = self.push(line)

        self.text.get_buffer().place_cursor(self.text.get_buffer().get_end_iter())

        if more:
            self.prompt_ps2()
        else:
            self.prompt_ps1()

        self.current_history = 0

        return True

    def complete_line(self):
        line = self.current_line()
        tokens = line.split()

        if tokens:
            token = tokens[-1]
            completions: List[str] = []
            p = self.completer.complete(token, len(completions))
            while p:
                assert p
                completions.append(p)
                p = self.completer.complete(token, len(completions))
        else:
            completions = list(self.locals.keys())

        if len(completions) > 1:
            max_len = max(map(len, completions)) + 2
            per_line = 80 // max_len
            for i, c in enumerate(completions):
                if i % per_line == 0:
                    self.write_line("\n")
                self.write_line(c, self.style_ps1)
                self.write_line(" " * (max_len - len(c)), self.style_ps1)
            self.write_line("\n")
            self.current_prompt()
            self.write_line(line)
        elif len(completions) == 1:
            i = line.rfind(token)
            line = line[0:i] + completions[0]
            self.replace_line(line)

        return True
Пример #17
0
class GTKInterpreterConsole(Gtk.ScrolledWindow):
    """
    An InteractiveConsole for GTK. It's an actual widget,
    so it can be dropped in just about anywhere.
    """

    __gtype_name__ = "GTKInterpreterConsole"

    def __init__(self, locals=None, banner=banner):
        Gtk.ScrolledWindow.__init__(self)
        self.set_min_content_width(640)
        self.set_min_content_height(480)
        self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)

        self.text = Gtk.TextView()
        self.text.set_wrap_mode(True)
        self.text.set_monospace(True)
        self.text.set_border_width(4)

        self.interpreter = code.InteractiveInterpreter(locals)

        self.interpreter.locals["help"] = Help()
        self.completer = Completer(self.interpreter.locals)
        self.buffer = []
        self.history = []
        self.banner = banner
        self.ps1 = ">>> "
        self.ps2 = "... "

        self.text.add_events(Gdk.EventMask.KEY_PRESS_MASK)
        self.text.connect("key_press_event", self.key_pressed)

        self.current_history = -1

        self.mark = self.text.get_buffer().create_mark(
            "End", self.text.get_buffer().get_end_iter(), False
        )

        # setup colors
        self.style_banner = Gtk.TextTag.new("banner")
        self.style_banner.set_property("foreground", "saddle brown")

        self.style_ps1 = Gtk.TextTag.new("ps1")
        self.style_ps1.set_property("foreground", "DarkOrchid4")
        self.style_ps1.set_property("editable", False)

        self.style_ps2 = Gtk.TextTag.new("ps2")
        self.style_ps2.set_property("foreground", "DarkOliveGreen")
        self.style_ps2.set_property("editable", False)

        self.style_out = Gtk.TextTag.new("stdout")
        self.style_out.set_property("foreground", "midnight blue")
        self.style_out.set_property("editable", False)
        self.style_err = Gtk.TextTag.new("stderr")
        self.style_err.set_property("style", Pango.Style.ITALIC)
        self.style_err.set_property("foreground", "red")
        self.style_err.set_property("editable", False)

        self.text.get_buffer().get_tag_table().add(self.style_banner)
        self.text.get_buffer().get_tag_table().add(self.style_ps1)
        self.text.get_buffer().get_tag_table().add(self.style_ps2)
        self.text.get_buffer().get_tag_table().add(self.style_out)
        self.text.get_buffer().get_tag_table().add(self.style_err)

        self.stdout = TextViewWriter("stdout", self.text, self.style_out)
        self.stderr = TextViewWriter("stderr", self.text, self.style_err)

        self.current_prompt = None

        self.add(self.text)
        self.text.show()

        self.write_line(self.banner, self.style_banner)

        GLib.idle_add(self.prompt_ps1)

    def reset_history(self):
        self.history = []

    def reset_buffer(self):
        self.buffer = []

    def prompt_ps1(self):
        self.current_prompt = self.prompt_ps1
        self.write_line(self.ps1, self.style_ps1)

    def prompt_ps2(self):
        self.current_prompt = self.prompt_ps2
        self.write_line(self.ps2, self.style_ps2)

    def write_line(self, text, style=None):
        start, end = self.text.get_buffer().get_bounds()
        if style:
            self.text.get_buffer().insert_with_tags(end, text, style)
        else:
            self.text.get_buffer().insert(end, text)

        self.text.scroll_to_mark(self.mark, 0, True, 1, 1)

    def push(self, line):
        self.buffer.append(line)
        if len(line) > 0:
            self.history.append(line)

        source = "\n".join(self.buffer)

        with self.stdout, self.stderr:
            more = self.interpreter.runsource(source, "<<console>>")

        if not more:
            self.reset_buffer()

        return more

    def key_pressed(self, widget, event):
        if event.keyval == Gdk.keyval_from_name("Return"):
            return self.execute_line()
        if event.keyval == Gdk.keyval_from_name("Tab"):
            return self.complete_line()

        if event.keyval == Gdk.keyval_from_name("Up"):
            self.current_history = self.current_history - 1
            if self.current_history < -len(self.history):
                self.current_history = -len(self.history)
            return self.show_history()
        if event.keyval == Gdk.keyval_from_name("Down"):
            self.current_history = self.current_history + 1
            if self.current_history > 0:
                self.current_history = 0
            return self.show_history()

        ctrl = event.state & Gdk.ModifierType.CONTROL_MASK
        if (event.keyval == Gdk.keyval_from_name("Home")) or (
            ctrl and event.keyval == Gdk.KEY_a
        ):
            l = self.text.get_buffer().get_line_count() - 1
            start = self.text.get_buffer().get_iter_at_line_offset(l, 4)
            self.text.get_buffer().place_cursor(start)
            return True

        if ctrl and event.keyval == Gdk.KEY_e:
            end = self.text.get_buffer().get_end_iter()
            self.text.get_buffer().place_cursor(end)
            return True

        return False

    def show_history(self):
        if self.current_history == 0:
            return True
        else:
            self.replace_line(self.history[self.current_history])
            return True

    def current_line(self):
        start, end = self.current_line_bounds()
        return self.text.get_buffer().get_text(start, end, True)

    def current_line_bounds(self):
        txt_buffer = self.text.get_buffer()
        l = txt_buffer.get_line_count() - 1

        start = txt_buffer.get_iter_at_line(l)
        if start.get_chars_in_line() >= 4:
            start.forward_chars(4)
        end = txt_buffer.get_end_iter()
        return start, end

    def replace_line(self, txt):
        start, end = self.current_line_bounds()
        self.text.get_buffer().delete(start, end)
        self.write_line(txt)

    def execute_line(self):
        line = self.current_line()

        self.write_line("\n")

        more = self.push(line)

        self.text.get_buffer().place_cursor(self.text.get_buffer().get_end_iter())

        if more:
            self.prompt_ps2()
        else:
            self.prompt_ps1()

        self.current_history = 0

        return True

    def complete_line(self):
        line = self.current_line()
        tokens = line.split()

        if tokens:
            token = tokens[-1]
            completions = []
            p = self.completer.complete(token, len(completions))
            while p != None:
                completions.append(p)
                p = self.completer.complete(token, len(completions))
        else:
            completions = list(self.interpreter.locals.keys())

        if len(completions) > 1:
            max_len = max(map(len, completions)) + 2
            per_line = 80 // max_len
            for i, c in enumerate(completions):
                if i % per_line == 0:
                    self.write_line("\n")
                self.write_line(c, self.style_ps1)
                self.write_line(" " * (max_len - len(c)), self.style_ps1)
            self.write_line("\n")
            self.current_prompt()
            self.write_line(line)
        elif len(completions) == 1:
            i = line.rfind(token)
            line = line[0:i] + completions[0]
            self.replace_line(line)

        return True
Пример #18
0
class PythonConsole(QPlainTextEdit, pytson.Translatable):
    def __init__(self, tabcomplete=True, spaces=True, tabwidth=2,
                 font=defaultFont(), bgcolor=Qt.black, textcolor=Qt.white,
                 startup="", silentStartup=False,
                 parent=None, *, catchstd=False, closeAction):
        super(QPlainTextEdit, self).__init__(parent)

        self.setLineWrapMode(QPlainTextEdit.NoWrap)

        self.setWindowTitle(self._tr("pyTSon Console"))

        self.tabcomplete = tabcomplete
        self.spaces = spaces
        self.tabwidth = tabwidth
        self.setFont(font)

        self.setContextMenuPolicy(Qt.PreventContextMenu)

        p = self.palette
        p.setColor(QPalette.Base, bgcolor)
        p.setColor(QPalette.Text, textcolor)
        self.palette = p

        self.history = []
        self.curhistory = -1
        self.lastinp = ""
        self.locked = False
        self.globals = {}
        self.inmulti = False
        self.multi = ""
        self.incmd = False

        self.comp = Completer(self.globals)

        self.selformat = self.currentCharFormat()
        self.selformat.setBackground(Qt.white)
        self.selformat.setForeground(Qt.black)

        self.norformat = self.currentCharFormat()

        self.closeAction = closeAction

        # we have to make sure, that this runs in the same context as
        # commands run from the console
        self.clearlocals = list(eval("dir()", self.globals))
        self.connect("destroyed()", self._resetdir)

        if catchstd:
            self.redirector = StdRedirector(self.appendLine)
            self.stdout = sys.stdout
            sys.stdout = self.redirector

            self.connect("destroyed()", self._resetStdout)
        else:
            self.redirector = None

        if os.path.isfile(startup):
            with open(startup, "r") as f:
                self.runCommand(f.read(), silentStartup)

        self.writePrompt(self.plainText != "")

    def _resetdir(self):
        curlocals = list(eval("dir()", self.globals))
        for var in curlocals:
            if var not in self.clearlocals:
                try:
                    exec("del %s" % var, self.globals)
                except Exception as e:
                    pass

    def _resetStdout(self):
        sys.stdout = self.stdout

    def setFont(self, f):
        QPlainTextEdit.setFont(self, f)

        fm = QFontMetrics(f)
        self.setCursorWidth(fm.width("X"))
        self.setTabStopWidth(fm.width("X") * self.tabwidth)

    def prompt(self):
        return ">>> " if not self.inmulti else "... "

    def promptLength(self):
        return len(self.prompt())

    def writePrompt(self, newline):
        if newline:
            self.textCursor().insertBlock()

        self.textCursor().insertText(self.prompt())

    def promptCursor(self):
        retcur = QTextCursor(self.textCursor())

        retcur.movePosition(QTextCursor.End)
        retcur.movePosition(QTextCursor.StartOfLine)
        retcur.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor,
                            self.promptLength())

        return retcur

    def keyPressEvent(self, e):
        if self.locked:
            return

        if self.textCursor() < self.promptCursor():
            self.moveCursor(QTextCursor.End)

        key = e.key()
        mods = e.modifiers()

        if key == Qt.Key_C and mods & Qt.ControlModifier:
            self.doKeyboardInterrupt()
        elif key == Qt.Key_D and mods & Qt.ControlModifier:
            self.doEndFile()
        elif key == Qt.Key_Backspace and mods == Qt.NoModifier:
            if self.textCursor() > self.promptCursor():
                QPlainTextEdit.keyPressEvent(self, e)
        elif key in [Qt.Key_Enter, Qt.Key_Return] and mods == Qt.NoModifier:
            self.doExecuteCommand()
        elif key == Qt.Key_Up and mods == Qt.NoModifier:
            self.doHistoryUp()
        elif key == Qt.Key_Down and mods == Qt.NoModifier:
            self.doHistoryDown()
        elif key == Qt.Key_Left and mods == Qt.NoModifier:
            if self.textCursor().positionInBlock() > self.promptLength():
                QPlainTextEdit.keyPressEvent(self, e)
        elif key == Qt.Key_Right:
            QPlainTextEdit.keyPressEvent(self, e)
        elif key == Qt.Key_Delete and mods == Qt.NoModifier:
            QPlainTextEdit.keyPressEvent(self, e)
        elif key == Qt.Key_End and mods == Qt.NoModifier:
            self.moveCursor(QTextCursor.EndOfLine)
        elif key == Qt.Key_Tab and mods == Qt.NoModifier:
            self.doTab()
        elif ((key == Qt.Key_Tab and mods == Qt.ShiftModifier) or
              key == Qt.Key_Backtab):
            self.doUntab()
        elif key == Qt.Key_Home and mods == Qt.NoModifier:
            self.setTextCursor(self.promptCursor())
        else:
            QPlainTextEdit.keyPressEvent(self, e)

        self.ensureCursorVisible()

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.seltext = ""
            cur = QTextCursor(self.document())
            cur.select(QTextCursor.Document)
            cur.setCharFormat(self.norformat)

            self.selcursor = self.textCursor()
            QPlainTextEdit.mousePressEvent(self, e)
        else:
            QPlainTextEdit.mousePressEvent(self, e)
        self.ensureCursorVisible()

    def mouseReleaseEvent(self, e):
        QPlainTextEdit.mouseReleaseEvent(self, e)
        if e.button() == Qt.LeftButton:
            self.textCursor().setCharFormat(self.selformat)
            self.seltext = self.textCursor().selectedText()
            self.setTextCursor(self.selcursor)
        elif e.button() == Qt.RightButton:
            if self.seltext == "":
                self.textCursor().insertText(QApplication.clipboard().text())
            else:
                self.textCursor().insertText(self.seltext)
                QApplication.clipboard().setText(self.seltext)

    def doKeyboardInterrupt(self):
        self.moveCursor(QTextCursor.End)

        self.textCursor().insertBlock()
        self.textCursor().insertText("KeyboardInterrupt")

        self.inmulti = False
        self.multi = ""

        self.writePrompt(True)

    def doEndFile(self):
        cur = self.textCursor()
        self.moveCursor(QTextCursor.Right)

        # delete key to the right if there are
        if cur != self.textCursor():
            self.textCursor().deletePreviousChar()
        elif self.textCursor() == self.promptCursor():
            # if no chars in cur command, close
            self.closeAction()

    def currentLine(self):
        return self.textCursor().block().text()[self.promptLength():]

    def removeCurrentLine(self):
        self.moveCursor(QTextCursor.End, QTextCursor.MoveAnchor)
        self.moveCursor(QTextCursor.StartOfLine, QTextCursor.MoveAnchor)
        self.moveCursor(QTextCursor.End, QTextCursor.KeepAnchor)
        self.textCursor().removeSelectedText()

    def addHistory(self, cmd):
        if len(self.history) > 0:
            if cmd in self.history:
                self.history.pop(self.history.index(cmd))

        self.history.append(cmd)

    def doHistoryUp(self):
        if len(self.history) == 0:
            return

        if self.curhistory == -1:
            self.lastinp = self.currentLine()
            self.curhistory = len(self.history)

        self.removeCurrentLine()
        self.writePrompt(False)

        self.curhistory -= 1

        if self.curhistory == -1:
            self.textCursor().insertText(self.lastinp)
            self.curhistory = -1
        else:
            self.textCursor().insertText(self.history[self.curhistory])

    def doHistoryDown(self):
        if len(self.history) == 0 or self.curhistory == -1:
            return

        self.removeCurrentLine()
        self.writePrompt(False)

        self.curhistory += 1

        if self.curhistory == len(self.history):
            self.textCursor().insertText(self.lastinp)
            self.curhistory = -1
        else:
            self.textCursor().insertText(self.history[self.curhistory])

    def doTab(self):
        if self.tabcomplete:
            cmd = self.currentLine()
            tokens = list(filter(None, re.split("[, \t\-\+\*\[\]\{\}:\(\)]+",
                                 cmd)))
            lasttoken = tokens[-1]
            if lasttoken != "":
                if lasttoken[-1] != cmd[-1]:
                    # operators are filtered out (such as opening braces),
                    # so append the last non-alphanumeric characters back
                    # to the completion token
                    lastalpha = max(cmd.rfind(i)
                                    for i in string.letters + string.digits)
                    lasttoken += cmd[- lastalpha + 1:]

                state = 0
                cur = self.comp.complete(lasttoken, state)

                if cur:
                    l = [cur]

                    while cur:
                        state += 1
                        cur = self.comp.complete(lasttoken, state)

                        if cur:
                            l.append(cur)

                    if len(l) == 1:
                        self.removeCurrentLine()
                        self.writePrompt(False)
                        before = cmd[:-len(lasttoken)]
                        if before == "":
                            self.textCursor().insertText(l[0])
                        else:
                            self.textCursor().insertText(cmd[:-len(lasttoken)]
                                                         + l[0])
                    else:
                        self.appendLine("\t\t".join(l))

                        prefix = ''.join(c[0] for c in takewhile(lambda x:
                                         all(x[0] == y for y in x), zip(*l)))
                        if prefix != '':
                            self.textCursor().insertText(prefix[len(lasttoken):
                                                                ])
                        else:
                            self.textCursor().insertText(cmd)
        else:
            if self.spaces:
                self.textCursor().insertText(" " * self.tabwidth)
            else:
                self.textCursor().insertText("\t")

    def doUntab(self):
        if self.tabcomplete:
            return

        sel = self.textCursor()

        tab = " " * self.tabwidth if self.spaces else "\t"
        sel.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, len(tab))
        if sel >= self.promptCursor() and sel.selectedText() == tab:
            sel.removeSelectedText()
            return

    def appendLine(self, text):
        curline = self.currentLine()
        sel = self.textCursor()

        self.moveCursor(QTextCursor.End)
        self.appendPlainText(text)

        if not self.incmd:
            self.writePrompt(True)

            if curline != "":
                self.textCursor().insertText(curline)

                cur = self.promptCursor()
                cur.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor,
                                 sel.positionInBlock() - self.promptLength())
                self.setTextCursor(cur)

    def runCommand(self, cmd, silent):
        self.incmd = True

        if not self.redirector and not silent:
            tmp = sys.stdout
            sys.stdout = StdRedirector(self.appendLine)

        try:
            try:
                res = eval(cmd, self.globals)
                if res is not None:
                    self.appendLine(repr(res))
            except SyntaxError:
                exec(cmd, self.globals)
        except:
            if not silent:
                self.appendLine(traceback.format_exc(chain=False))

        if not self.redirector and not silent:
            sys.stdout = tmp

        self.incmd = False

    def doExecuteCommand(self):
        cmd = self.currentLine().rstrip()

        if cmd == "":
            if self.inmulti:
                cmd = self.multi
                self.multi = ""
                self.inmulti = False
        else:
            self.addHistory(cmd)
            self.curhistory = -1

            if self.inmulti:
                self.multi += "\n" + cmd
                self.writePrompt(True)
                return

        if cmd.endswith(":"):
            self.inmulti = True
            self.multi = cmd
            self.writePrompt(True)
            return

        self.moveCursor(QTextCursor.End)

        self.runCommand(cmd, False)
        self.writePrompt(True)

        self.ensureCursorVisible()
Пример #19
0
    def keyPressEvent(self, event):
        qt = QtCore.Qt
        if event.key() == qt.Key_Tab:
            line = str(self.document().lastBlock().text())[4:]
            completer = Completer(self.interpreter.locals)
            suggestion = completer.complete(line, 0)
            if suggestion is not None:
                self.insertPlainText(suggestion[len(line):])
            return None

        if event.key() == qt.Key_Down:
            if self.historyIndex == len(self.history):
                self.historyIndex -= 1
            try:
                if self.historyIndex > -1:
                    self.historyIndex -= 1
                    self.recallHistory()
                else:
                    self.clearCurrentBlock()
            except:
                pass
            return None

        if event.key() == qt.Key_Up:
            try:
                if len(self.history) - 1 > self.historyIndex:
                    self.historyIndex += 1
                    self.recallHistory()
                else:
                    self.historyIndex = len(self.history)
            except:
                pass
            return None

        if event.key() == qt.Key_Home:
            # set cursor to position 4 in current block. 4 because that's where
            # the marker stops
            blockLength = len(self.document().lastBlock().text()[4:])
            lineLength  = len(self.document().toPlainText())
            position = lineLength - blockLength
            textCursor  = self.textCursor()
            textCursor.setPosition(position)
            self.setTextCursor(textCursor)
            return None

        if event.key() in [qt.Key_Left, qt.Key_Backspace]:
            # don't allow deletion of marker
            if self.textCursor().positionInBlock() == 4:
                return None

        if event.key() in [qt.Key_Return, qt.Key_Enter]:
            # set cursor to end of line to avoid line splitting
            textCursor = self.textCursor()
            position   = len(self.document().toPlainText())
            textCursor.setPosition(position)
            self.setTextCursor(textCursor)

            line = str(self.document().lastBlock().text())[4:] # remove marker
            line.rstrip()
            self.historyIndex = -1

            if self.customCommands(line):
                return None
            else:
                try:
                    # pylint: disable=pointless-statement
                    line[-1]
                    self.haveLine = True
                    if line[-1] == ':':
                        self.multiLine = True
                    self.history.insert(0, line)
                except:
                    self.haveLine = False

                if self.haveLine and self.multiLine: # multi line command
                    self.command += line + '\n' # + command and line
                    self.append('') # move down one line
                    self.marker() # handle marker style
                    return None

                if self.haveLine and not self.multiLine: # one line command
                    self.command = line # line is the command
                    self.append('') # move down one line
                    self.interpreter.runIt(self.command)
                    self.command = '' # clear command
                    self.marker() # handle marker style
                    return None

                if self.multiLine and not self.haveLine: #  multi line done
                    self.append('') # move down one line
                    self.interpreter.runIt(self.command)
                    self.command = '' # clear command
                    self.multiLine = False # back to single line
                    self.marker() # handle marker style
                    return None

                if not self.haveLine and not self.multiLine: # just enter
                    self.append('')
                    self.marker()
                    return None
                return None

        # allow all other key events
        super(PyInterp, self).keyPressEvent(event)