Beispiel #1
0
    def __init__(
        self,
        edit_text="",
        multiline=True,
        align="left",
        wrap="space",
        allow_tab=True,
        edit_pos=None,
        layout=None,
        lexer=None,
        formatter=None,
    ):

        if lexer is not None:
            self.lexer = lexer
        else:
            self.lexer = pygments.lexers.get_lexer_by_name("python")

        if formatter is not None:
            self.formatter = formatter
        else:
            self.formatter = UrwidFormatter()

        # note: captions not allowed
        widget.Edit.__init__(self, "", edit_text, multiline, align, wrap, allow_tab, edit_pos, layout)

        if edit_text:
            self.colorize()

        self.enterpressed = False
    def __init__(self, inputlines=4, caption='>>> '):
        # make inner widgets
        # first the input widgets
        # the input widgets are a 'captionwidget' for the prompt, next
        # to the inputwidget.
        # this means that the prompt is completely uneditable without
        # trying, and also takes care of indenting past the
        # prompt
        
        self.formatter = UrwidFormatter()
        self.lexer = pygments.lexers.get_lexer_by_name('python', stripall='True', ensurenl='False')
        self.errlexer = pygments.lexers.get_lexer_by_name('pytb', stripall='True', ensurenl='False')

        self.inputbox = PromptPyEdit(multiline=True,lexer = self.lexer, formatter = self.formatter)
        self.inputwidget = urwid.Filler(self.inputbox, valign='top')
        
        # the completion box
        self.completionbox = TextGrid()
        
        # the 'upper' box, which can be switched to completions, help, etc.
        self.upperbox = UpperBox(self.completionbox)
        
        # now the output widgets
        self.outputbox = OutputBox()    # Box widget
        self.outputwidget = self.outputbox
        #self.outputwidget = urwid.Filler(self.outputbox, valign='top')
                    # Box widget
        
        # now initialize as a pile
        urwid.Pile.__init__(self, [
            ('flow', self.upperbox),
            self.outputwidget,
            ('fixed', inputlines, self.inputwidget)]
        )
        self.set_focus(self.inputwidget)
Beispiel #3
0
  def enable_syntax_coloring(self):
    debug("INITIALIZING SYNTAX COLORED WIDGET")
    walker = urwid.SimpleListWalker([])

    self.previous_widget = self.window.original_widget
    listbox = TextBox(walker)
    self.window.original_widget = listbox
    self.syntax_colored = True
    focused_index = self.get_focus_index(self.previous_widget)

    formatter = UrwidFormatter(style=PYGMENTS_STYLE)
    def handle_token(token, formatted_line, diff=False):
      text = token[1]
      if not text:
        return

      if text.find('\n') >= 0:
        split_line = clear_escape_codes(text)
        while split_line:
          n = split_line.find('\n')
          if n >= 0:
            last_word = split_line[:n]
            split_line = split_line[n+1:]
            formatted_line.append(last_word)
            if diff:
              walker.append(DiffLine(list(formatted_line)))
            else:
              walker.append(urwid.Text(list(formatted_line)))

            del formatted_line[:]
          else:
            formatted_line.append((token[0], split_line))
            break
      else:
        token = (token[0], clear_escape_codes(token[1]))
        formatted_line.append(token)

      # end of handle_token function

    def add_diff_lines_to_walker(ret, index, walker, clear_walker=True, cb=None, fname=None):

      if clear_walker:
        walker[:] = [ ]

      wlines = []
      # stupid \n ending required...
      iterator = itertools.count(index)
      for index in iterator:

        if index >= len(ret['lines']) or self.quit:
          break

        line = clear_escape_codes(ret['lines'][index])

        if line.startswith("diff --git"):
          diff_index = index

          commit_lines = [ line ]
          def add_line():
            commit_lines.append(clear_escape_codes(ret['lines'][iterator.next()]))
            return 1
            # doh. even though iterator is consuming it, we need this for later

          index += add_line() # Author
          index += add_line() # Date
          index += add_line() # Blah

          index += 1


          # Look upwards for the commit line (find the first line that starts with Author and Date)
          # and put them in commit_lines

          author_index = None

          for windex, wline in enumerate(wlines):
            if wline.startswith("Author:"):
              author_index = windex

          if author_index:
            commit_lines = wlines[author_index-1:] + commit_lines
            wlines = wlines[:author_index-1]

          if wlines:
            debug("ADDING SYNTAX LINES", wlines, self.fname)
            add_lines_to_walker(wlines, walker, self.fname, diff=True)

          if commit_lines:
            debug("ADDING COMMIT LINES", commit_lines, self.fname)

            if not clear_walker and author_index:
              walker.append(urwid.Text(""))
            add_lines_to_walker(commit_lines, walker, None, skip_colors=True, diff=True)

          # next fname output
          self.fname = line.split().pop()
          debug("SETTING FNAME TO", self.fname)

          def future_call(index, walker):
            self.update_pager()
            self.ret['syntax_lines'] = index
            add_diff_lines_to_walker(ret, index, walker, clear_walker=False, cb=cb)

          thread = threading.Thread(target=future_call, args=(index, walker))
          time.sleep(0.001)
          if not self.quit:
            thread.start()
          return
        else:
          wlines.append(line)

      if wlines:
        # When we make it to the way end, put the last file contents in
        add_lines_to_walker(wlines, walker, self.fname, diff=True)

      if cb:
        cb()

      self.ret['syntax_lines'] = index
      # This is when we are finally done. (For reals)
      self.update_pager()

    def add_lines_to_walker(lines, walker, fname=None, diff=False, skip_colors=False):
      if len(lines):
        lexer = None
        forced = False

        if not fname and skip_colors:
          debug("LINES BEFORE LEXER", lines)
          debug("SKIPPING COLORING", fname, diff)
          lines = self.escape_ansi_colors([line.rstrip() for line in lines])
          self.syntax_lang = "None"
          walker.extend(lines)
          return

        output = "".join(lines)
        try:
          forced = True
          if not fname in _lexer_fname_cache:
            _lexer_fname_cache[fname] = pygments.lexers.get_lexer_for_filename(fname)

          lexer = _lexer_fname_cache[fname]
        except:
          pass

        if not lexer:
          try:
              lexer = guess_lexer(output)
          except Exception, e:
              debug("EXCEPTION", e);
              lexer = pygments.lexers.TextLexer()

        if diff and forced:
          self.syntax_lang = "git diff"
          debug("LEXER (FORCED) ", lexer)
        else:
          score = lexer.__class__.analyse_text(output)
          self.syntax_lang = lexer.name
          debug("LEXER (TRIED: %s) and (GUESSED) SCORE" % (fname), lexer, score)
          if score < 0.3:
            # COULDNT FIGURE OUT A GOOD SYNTAX HIGHLIGHTER
            # DISABLE IT
            lexer = pygments.lexers.get_lexer_by_name('text')
            self.syntax_lang = "none. (Couldn't auto-detect a syntax)"

            lines = self.escape_ansi_colors([line.rstrip() for line in lines], self.syntax_colored)
            walker.extend(lines)
            return

        if lexer.__class__ is pygments.lexers.TextLexer:
          debug("TEXT LEXER! DISABLING")
          lines = self.escape_ansi_colors(["%s" % line.rstrip() for line in lines], self.syntax_colored)
          walker.extend(lines)
          return

        tokens = lexer.get_tokens(output)

        # Build the syntax output up line by line, so that it can be highlighted
        # one line at a time
        formatted_tokens = list(formatter.formatgenerator(tokens))
        formatted_line = []

        for token in formatted_tokens:
          handle_token(token, formatted_line, diff)

        if formatted_line:
          walker.append(urwid.Text(list(formatted_line)))
Beispiel #4
0
class PythonEdit(widget.Edit):  # flow
    """An editbox that colorizes python code.
    A FLOW widget."""

    def __init__(
        self,
        edit_text="",
        multiline=True,
        align="left",
        wrap="space",
        allow_tab=True,
        edit_pos=None,
        layout=None,
        lexer=None,
        formatter=None,
    ):

        if lexer is not None:
            self.lexer = lexer
        else:
            self.lexer = pygments.lexers.get_lexer_by_name("python")

        if formatter is not None:
            self.formatter = formatter
        else:
            self.formatter = UrwidFormatter()

        # note: captions not allowed
        widget.Edit.__init__(self, "", edit_text, multiline, align, wrap, allow_tab, edit_pos, layout)

        if edit_text:
            self.colorize()

        self.enterpressed = False

    def handlekey(self, size, key):
        """Extra magic for a python editor"""
        # deal with double enter - return it
        if key == "enter" and self.multiline and not self.enterpressed:
            self.enterpressed = True
            return urwid.Edit.keypress(self, size, key)

        elif key == "enter" and self.multiline and self.enterpressed:
            return key
        else:
            self.enterpressed = False

        return widget.Edit.keypress(self, size, key)

    def keypress(self, size, key):
        """Handles colorpress"""
        retval = self.handlekey(size, key)
        self.colorize()
        return retval

    @property
    def markup(self):
        return self.get_text()

    def colorize(self):
        text = self.edit_text
        assert hasattr(self, "formatter")
        assert hasattr(self, "lexer")
        tkns = self.lexer.get_tokens(text)
        markup = list(self.formatter.formatgenerator(tkns))
        widget.Text.set_text(self, markup)
class InterpreterWidget(urwid.Pile):
    """A widget that looks like an interpreter.

    Note that this is simply a widget, and has no extra functionality;
    it exists to organize the inner widgets."""
    def __init__(self, inputlines=4, caption='>>> '):
        # make inner widgets
        # first the input widgets
        # the input widgets are a 'captionwidget' for the prompt, next
        # to the inputwidget.
        # this means that the prompt is completely uneditable without
        # trying, and also takes care of indenting past the
        # prompt
        
        self.formatter = UrwidFormatter()
        self.lexer = pygments.lexers.get_lexer_by_name('python', stripall='True', ensurenl='False')
        self.errlexer = pygments.lexers.get_lexer_by_name('pytb', stripall='True', ensurenl='False')

        self.inputbox = PromptPyEdit(multiline=True,lexer = self.lexer, formatter = self.formatter)
        self.inputwidget = urwid.Filler(self.inputbox, valign='top')
        
        # the completion box
        self.completionbox = TextGrid()
        
        # the 'upper' box, which can be switched to completions, help, etc.
        self.upperbox = UpperBox(self.completionbox)
        
        # now the output widgets
        self.outputbox = OutputBox()    # Box widget
        self.outputwidget = self.outputbox
        #self.outputwidget = urwid.Filler(self.outputbox, valign='top')
                    # Box widget
        
        # now initialize as a pile
        urwid.Pile.__init__(self, [
            ('flow', self.upperbox),
            self.outputwidget,
            ('fixed', inputlines, self.inputwidget)]
        )
        self.set_focus(self.inputwidget)
    
    def set_input_caption(self, caption):
        self.inputbox.set_prompt(caption)
    
    def highlight(self, txt):
        tkns = self.lexer.get_tokens(txt)
        return list(self.formatter.formatgenerator(tkns))

    def highlight_err(self, txt):
        tkns = self.errlexer.get_tokens(txt)
        return list(self.formatter.formatgenerator(tkns))

    @property
    def input_text(self):
        return self.inputbox.text
    
    @input_text.setter
    def input_text(self, newtxt):
        self.inputbox.text = u''
        
    def set_style(self, s):
        if isinstance(s, basestring):
            s = pygments.styles.get_style_by_name(s)
        self.formatter.style = s
    
    def add_to_output(self, markup):
        self.outputbox.add_stdout(markup)
        return
        
    def _get_widget_size(self, widget, selfsize):
        item_rows = None
        if len(selfsize)==2: # Box widget
            item_rows = self.get_item_rows( selfsize, focus=True )
        i = self.widget_list.index(widget)
        return self.get_item_size(selfsize,i,True,item_rows)
    
    def _passkey(self, widget, size, key):
        """Pass the key along to an inner widget."""
        tsize = self._get_widget_size(widget, size)
        key = widget.keypress( tsize, key )
        return key
    
    def keypress(self, size, key):
        """We do not want the normal urwid.Pile keypress stuff to happen..."""
        # let the focus item use the key, if it can...
        if (self.focus_item.selectable() and 
                self.focus_item is not self.outputwidget):
            key = self._passkey(self.focus_item, size, key)
        
        # try it on the outputbox
    
        origkey = key
        if key in ('up','page up', 'home'):
            self.outputbox.jumptobottom = False
            key = None
        key = self._passkey(self.outputwidget, size, origkey)
        tsize = self._get_widget_size(self.outputwidget, size)
        if (origkey in ('down', 'page down', 'end')
                and self.outputbox.atbottom(tsize)):
            self.outputbox.jumptobottom = True
            key = None
        
        if key == 'ctrl k':
            # switch focus widget
            if self.focus_item is self.outputwidget:
                self.set_focus(self.inputwidget)
            else:
                self.set_focus(self.outputwidget)
            return
        return key