Beispiel #1
0
    def subseg(self, text, start, end):
        """
        Return a "sub-segment" list containing segment structures
        that make up a portion of this segment.

        A list is returned to handle cases where wide characters
        need to be replaced with a space character at either edge
        so two or three segments will be returned.
        """
        if start < 0: start = 0
        if end > self.sc: end = self.sc
        if start >= end:
            return []  # completely gone
        if self.text:
            # use text stored in segment (self.text)
            spos, epos, pad_left, pad_right = calc_trim_text(
                self.text, 0, len(self.text), start, end)
            return [(end - start, self.offs, bytes().ljust(pad_left) +
                     self.text[spos:epos] + bytes().ljust(pad_right))]
        elif self.end:
            # use text passed as parameter (text)
            spos, epos, pad_left, pad_right = calc_trim_text(
                text, self.offs, self.end, start, end)
            l = []
            if pad_left:
                l.append((1, spos - 1))
            l.append((end - start - pad_left - pad_right, spos, epos))
            if pad_right:
                l.append((1, epos))
            return l
        else:
            # simple padding adjustment
            return [(end - start, self.offs)]
Beispiel #2
0
    def subseg(self, text, start, end):
        """
        Return a "sub-segment" list containing segment structures
        that make up a portion of this segment.

        A list is returned to handle cases where wide characters
        need to be replaced with a space character at either edge
        so two or three segments will be returned.
        """
        if start < 0: start = 0
        if end > self.sc: end = self.sc
        if start >= end:
            return [] # completely gone
        if self.text:
            # use text stored in segment (self.text)
            spos, epos, pad_left, pad_right = calc_trim_text(
                self.text, 0, len(self.text), start, end )
            return [ (end-start, self.offs, bytes().ljust(pad_left) +
                self.text[spos:epos] + bytes().ljust(pad_right)) ]
        elif self.end:
            # use text passed as parameter (text)
            spos, epos, pad_left, pad_right = calc_trim_text(
                text, self.offs, self.end, start, end )
            l = []
            if pad_left:
                l.append((1,spos-1))
            l.append((end-start-pad_left-pad_right, spos, epos))
            if pad_right:
                l.append((1,epos))
            return l
        else:
            # simple padding adjustment
            return [(end-start,self.offs)]
Beispiel #3
0
def apply_target_encoding( s ):
    """
    Return (encoded byte string, character set rle).
    """
    if _use_dec_special and type(s) == unicode:
        # first convert drawing characters
        try:
            s = s.translate( escape.DEC_SPECIAL_CHARMAP )
        except NotImplementedError:
            # python < 2.4 needs to do this the hard way..
            for c, alt in zip(escape.DEC_SPECIAL_CHARS, 
                    escape.ALT_DEC_SPECIAL_CHARS):
                s = s.replace( c, escape.SO+alt+escape.SI )

    if type(s) == unicode:
        s = s.replace(escape.SI+escape.SO, u"") # remove redundant shifts
        s = codecs.encode(s, _target_encoding, 'replace')

    assert isinstance(s, bytes)
    SO = escape.SO.encode('ascii')
    SI = escape.SI.encode('ascii')

    sis = s.split(SO)

    assert isinstance(sis[0], bytes)

    sis0 = sis[0].replace(SI, bytes())
    sout = []
    cout = []
    if sis0:
        sout.append( sis0 )
        cout.append( (None,len(sis0)) )
    
    if len(sis)==1:
        return sis0, cout
    
    for sn in sis[1:]:
        assert isinstance(sn, bytes)
        assert isinstance(SI, bytes)
        sl = sn.split(SI, 1)
        if len(sl) == 1:
            sin = sl[0]
            assert isinstance(sin, bytes)
            sout.append(sin)
            rle_append_modify(cout, (escape.DEC_TAG.encode('ascii'), len(sin)))
            continue
        sin, son = sl
        son = son.replace(SI, bytes())
        if sin:
            sout.append(sin)
            rle_append_modify(cout, (escape.DEC_TAG, len(sin)))
        if son:
            sout.append(son)
            rle_append_modify(cout, (None, len(son)))

    outstr = bytes().join(sout)
    return outstr, cout
Beispiel #4
0
def apply_target_encoding(s):
    """
    Return (encoded byte string, character set rle).
    """
    if _use_dec_special and type(s) == str:
        # first convert drawing characters
        try:
            s = s.translate(escape.DEC_SPECIAL_CHARMAP)
        except NotImplementedError:
            # python < 2.4 needs to do this the hard way..
            for c, alt in zip(escape.DEC_SPECIAL_CHARS,
                              escape.ALT_DEC_SPECIAL_CHARS):
                s = s.replace(c, escape.SO + alt + escape.SI)

    if type(s) == str:
        s = s.replace(escape.SI + escape.SO, "")  # remove redundant shifts
        s = codecs.encode(s, _target_encoding, 'replace')

    assert isinstance(s, bytes)
    SO = escape.SO.encode('ascii')
    SI = escape.SI.encode('ascii')

    sis = s.split(SO)

    assert isinstance(sis[0], bytes)

    sis0 = sis[0].replace(SI, bytes())
    sout = []
    cout = []
    if sis0:
        sout.append(sis0)
        cout.append((None, len(sis0)))

    if len(sis) == 1:
        return sis0, cout

    for sn in sis[1:]:
        assert isinstance(sn, bytes)
        assert isinstance(SI, bytes)
        sl = sn.split(SI, 1)
        if len(sl) == 1:
            sin = sl[0]
            assert isinstance(sin, bytes)
            sout.append(sin)
            rle_append_modify(cout, (escape.DEC_TAG.encode('ascii'), len(sin)))
            continue
        sin, son = sl
        son = son.replace(SI, bytes())
        if sin:
            sout.append(sin)
            rle_append_modify(cout, (escape.DEC_TAG, len(sin)))
        if son:
            sout.append(son)
            rle_append_modify(cout, (None, len(son)))

    outstr = bytes().join(sout)
    return outstr, cout
Beispiel #5
0
    def parse_escape(self, char):
        if self.parsestate == 1:
            # within CSI
            if char in CSI_COMMANDS.keys():
                self.parse_csi(char)
                self.parsestate = 0
            elif char in B('0123456789;') or (not self.escbuf
                                              and char == B('?')):
                self.escbuf += char
                return
        elif self.parsestate == 0 and char == B(']'):
            # start of OSC
            self.escbuf = bytes()
            self.parsestate = 2
            return
        elif self.parsestate == 2 and char == B("\x07"):
            # end of OSC
            self.parse_osc(self.escbuf.lstrip(B('0')))
        elif self.parsestate == 2 and self.escbuf[-1:] + char == B(ESC + '\\'):
            # end of OSC
            self.parse_osc(self.escbuf[:-1].lstrip(B('0')))
        elif self.parsestate == 2 and self.escbuf.startswith(B('P')) and \
             len(self.escbuf) == 8:
            # set palette (ESC]Pnrrggbb)
            pass
        elif self.parsestate == 2 and not self.escbuf and char == B('R'):
            # reset palette
            pass
        elif self.parsestate == 2:
            self.escbuf += char
            return
        elif self.parsestate == 0 and char == B('['):
            # start of CSI
            self.escbuf = bytes()
            self.parsestate = 1
            return
        elif self.parsestate == 0 and char in (B('%'), B('#'), B('('), B(')')):
            # non-CSI sequence
            self.escbuf = char
            self.parsestate = 3
            return
        elif self.parsestate == 3:
            self.parse_noncsi(char, self.escbuf)
        elif char in (B('c'), B('D'), B('E'), B('H'), B('M'), B('Z'), B('7'),
                      B('8'), B('>'), B('=')):
            self.parse_noncsi(char)

        self.leave_escape()
Beispiel #6
0
 def _text_content(self):
     """
     Return the text content of the canvas as a list of strings,
     one for each row.
     """
     return [bytes().join([text for (attr, cs, text) in row])
         for row in self.content()]
Beispiel #7
0
    def reset(self):
        """
        Reset the terminal.
        """
        self.escbuf = bytes()
        self.within_escape = False
        self.parsestate = 0

        self.attrspec = None
        self.charset = TermCharset()

        self.saved_cursor = None
        self.saved_attrs = None

        self.is_rotten_cursor = False

        self.reset_scroll()

        self.init_tabstops()

        # terminal modes
        self.modes.reset()

        # initialize self.term
        self.clear()
Beispiel #8
0
 def _text_content(self):
     """
     Return the text content of the canvas as a list of strings,
     one for each row.
     """
     return [bytes().join([text for (attr, cs, text) in row])
         for row in self.content()]
Beispiel #9
0
    def __init__(self, text=None, attr=None, cs=None,
        cursor=None, maxcol=None, check_width=True):
        """
        text -- list of strings, one for each line
        attr -- list of run length encoded attributes for text
        cs -- list of run length encoded character set for text
        cursor -- (x,y) of cursor or None
        maxcol -- screen columns taken by this canvas
        check_width -- check and fix width of all lines in text
        """
        Canvas.__init__(self)
        if text == None:
            text = []

        if check_width:
            widths = []
            for t in text:
                if type(t) != bytes:
                    raise CanvasError("Canvas text must be plain strings encoded in the screen's encoding", repr(text))
                widths.append( calc_width( t, 0, len(t)) )
        else:
            assert type(maxcol) == int
            widths = [maxcol] * len(text)

        if maxcol is None:
            if widths:
                # find maxcol ourselves
                maxcol = max(widths)
            else:
                maxcol = 0

        if attr == None:
            attr = [[] for x in range(len(text))]
        if cs == None:
            cs = [[] for x in range(len(text))]

        # pad text and attr to maxcol
        for i in range(len(text)):
            w = widths[i]
            if w > maxcol:
                raise CanvasError("Canvas text is wider than the maxcol specified \n%r\n%r\n%r"%(maxcol,widths,text))
            if w < maxcol:
                text[i] = text[i] + bytes().rjust(maxcol-w)
            a_gap = len(text[i]) - rle_len( attr[i] )
            if a_gap < 0:
                raise CanvasError("Attribute extends beyond text \n%r\n%r" % (text[i],attr[i]) )
            if a_gap:
                rle_append_modify( attr[i], (None, a_gap))

            cs_gap = len(text[i]) - rle_len( cs[i] )
            if cs_gap < 0:
                raise CanvasError("Character Set extends beyond text \n%r\n%r" % (text[i],cs[i]) )
            if cs_gap:
                rle_append_modify( cs[i], (None, cs_gap))

        self._attr = attr
        self._cs = cs
        self.cursor = cursor
        self._text = text
        self._maxcol = maxcol
Beispiel #10
0
    def __init__(self, text=None, attr=None, cs=None, 
        cursor=None, maxcol=None, check_width=True):
        """
        text -- list of strings, one for each line
        attr -- list of run length encoded attributes for text
        cs -- list of run length encoded character set for text
        cursor -- (x,y) of cursor or None
        maxcol -- screen columns taken by this canvas
        check_width -- check and fix width of all lines in text
        """
        Canvas.__init__(self)
        if text == None: 
            text = []

        if check_width:
            widths = []
            for t in text:
                if type(t) != bytes:
                    raise CanvasError("Canvas text must be plain strings encoded in the screen's encoding", repr(text))
                widths.append( calc_width( t, 0, len(t)) )
        else:
            assert type(maxcol) == int
            widths = [maxcol] * len(text)

        if maxcol is None:
            if widths:
                # find maxcol ourselves
                maxcol = max(widths)
            else:
                maxcol = 0

        if attr == None: 
            attr = [[] for x in range(len(text))]
        if cs == None:
            cs = [[] for x in range(len(text))]

        # pad text and attr to maxcol
        for i in range(len(text)):
            w = widths[i]
            if w > maxcol: 
                raise CanvasError("Canvas text is wider than the maxcol specified \n%r\n%r\n%r"%(maxcol,widths,text))
            if w < maxcol:
                text[i] = text[i] + bytes().rjust(maxcol-w)
            a_gap = len(text[i]) - rle_len( attr[i] )
            if a_gap < 0:
                raise CanvasError("Attribute extends beyond text \n%r\n%r" % (text[i],attr[i]) )
            if a_gap:
                rle_append_modify( attr[i], (None, a_gap))
            
            cs_gap = len(text[i]) - rle_len( cs[i] )
            if cs_gap < 0:
                raise CanvasError("Character Set extends beyond text \n%r\n%r" % (text[i],cs[i]) )
            if cs_gap:
                rle_append_modify( cs[i], (None, cs_gap))
            
        self._attr = attr
        self._cs = cs
        self.cursor = cursor
        self._text = text
        self._maxcol = maxcol
Beispiel #11
0
    def parse_escape(self, char):
        if self.parsestate == 1:
            # within CSI
            if char in CSI_COMMANDS.keys():
                self.parse_csi(char)
                self.parsestate = 0
            elif char in B('0123456789;') or (not self.escbuf and char == B('?')):
                self.escbuf += char
                return
        elif self.parsestate == 0 and char == B(']'):
            # start of OSC
            self.escbuf = bytes()
            self.parsestate = 2
            return
        elif self.parsestate == 2 and char == B("\x07"):
            # end of OSC
            self.parse_osc(self.escbuf.lstrip(B('0')))
        elif self.parsestate == 2 and self.escbuf[-1:] + char == B(ESC + '\\'):
            # end of OSC
            self.parse_osc(self.escbuf[:-1].lstrip(B('0')))
        elif self.parsestate == 2 and self.escbuf.startswith(B('P')) and \
             len(self.escbuf) == 8:
            # set palette (ESC]Pnrrggbb)
            pass
        elif self.parsestate == 2 and not self.escbuf and char == B('R'):
            # reset palette
            pass
        elif self.parsestate == 2:
            self.escbuf += char
            return
        elif self.parsestate == 0 and char == B('['):
            # start of CSI
            self.escbuf = bytes()
            self.parsestate = 1
            return
        elif self.parsestate == 0 and char in (B('%'), B('#'), B('('), B(')')):
            # non-CSI sequence
            self.escbuf = char
            self.parsestate = 3
            return
        elif self.parsestate == 3:
            self.parse_noncsi(char, self.escbuf)
        elif char in (B('c'), B('D'), B('E'), B('H'), B('M'), B('Z'), B('7'), B('8'), B('>'), B('=')):
            self.parse_noncsi(char)

        self.leave_escape()
Beispiel #12
0
    def parse_escape(self, char):
        if self.parsestate == 1:
            # within CSI
            if char in CSI_COMMANDS.keys():
                self.parse_csi(char)
                self.parsestate = 0
            elif char in B("0123456789;") or (not self.escbuf and char == B("?")):
                self.escbuf += char
                return
        elif self.parsestate == 0 and char == B("]"):
            # start of OSC
            self.escbuf = bytes()
            self.parsestate = 2
            return
        elif self.parsestate == 2 and char == B("\x07"):
            # end of OSC
            self.parse_osc(self.escbuf.lstrip(B("0")))
        elif self.parsestate == 2 and self.escbuf[-1:] + char == B(ESC + "\\"):
            # end of OSC
            self.parse_osc(self.escbuf[:-1].lstrip(B("0")))
        elif self.parsestate == 2 and self.escbuf.startswith(B("P")) and len(self.escbuf) == 8:
            # set palette (ESC]Pnrrggbb)
            pass
        elif self.parsestate == 2 and not self.escbuf and char == B("R"):
            # reset palette
            pass
        elif self.parsestate == 2:
            self.escbuf += char
            return
        elif self.parsestate == 0 and char == B("["):
            # start of CSI
            self.escbuf = bytes()
            self.parsestate = 1
            return
        elif self.parsestate == 0 and char in (B("%"), B("#"), B("("), B(")")):
            # non-CSI sequence
            self.escbuf = char
            self.parsestate = 3
            return
        elif self.parsestate == 3:
            self.parse_noncsi(char, self.escbuf)
        elif char in (B("c"), B("D"), B("E"), B("H"), B("M"), B("Z"), B("7"), B("8"), B(">"), B("=")):
            self.parse_noncsi(char)

        self.leave_escape()
Beispiel #13
0
def trim_text_attr_cs(text, attr, cs, start_col, end_col):
    """
    Return ( trimmed text, trimmed attr, trimmed cs ).
    """
    spos, epos, pad_left, pad_right = calc_trim_text(text, 0, len(text),
                                                     start_col, end_col)
    attrtr = rle_subseg(attr, spos, epos)
    cstr = rle_subseg(cs, spos, epos)
    if pad_left:
        al = rle_get_at(attr, spos - 1)
        rle_append_beginning_modify(attrtr, (al, 1))
        rle_append_beginning_modify(cstr, (None, 1))
    if pad_right:
        al = rle_get_at(attr, epos)
        rle_append_modify(attrtr, (al, 1))
        rle_append_modify(cstr, (None, 1))

    return (bytes().rjust(pad_left) + text[spos:epos] +
            bytes().rjust(pad_right), attrtr, cstr)
Beispiel #14
0
def trim_text_attr_cs( text, attr, cs, start_col, end_col ):
    """
    Return ( trimmed text, trimmed attr, trimmed cs ).
    """
    spos, epos, pad_left, pad_right = calc_trim_text( 
        text, 0, len(text), start_col, end_col )
    attrtr = rle_subseg( attr, spos, epos )
    cstr = rle_subseg( cs, spos, epos )
    if pad_left:
        al = rle_get_at( attr, spos-1 )
        rle_append_beginning_modify( attrtr, (al, 1) )
        rle_append_beginning_modify( cstr, (None, 1) )
    if pad_right:
        al = rle_get_at( attr, epos )
        rle_append_modify( attrtr, (al, 1) )
        rle_append_modify( cstr, (None, 1) )

    return (bytes().rjust(pad_left) + text[spos:epos] +
        bytes().rjust(pad_right), attrtr, cstr)
Beispiel #15
0
 def content(self, trim_left, trim_top, cols, rows, attr):
     """
     return (cols, rows) of spaces with default attributes.
     """
     def_attr = None
     if attr and None in attr:
         def_attr = attr[None]
     line = [(def_attr, None, bytes().rjust(cols))]
     for i in range(rows):
         yield line
Beispiel #16
0
 def content(self, trim_left, trim_top, cols, rows, attr):
     """
     return (cols, rows) of spaces with default attributes.
     """
     def_attr = None
     if attr and None in attr:
         def_attr = attr[None]
     line = [(def_attr, None, bytes().rjust(cols))]
     for i in range(rows):
         yield line
Beispiel #17
0
    def __init__(self, width, height, widget):
        Canvas.__init__(self)

        self.width, self.height = width, height
        self.widget = widget
        self.modes = widget.term_modes

        self.scrollback_buffer = TermScroller()
        self.scrolling_up = 0

        self.utf8_eat_bytes = None
        self.utf8_buffer = bytes()

        self.coords["cursor"] = (0, 0, None)

        self.reset()
Beispiel #18
0
    def process_char(self, char):
        """
        Process a single character (single- and multi-byte).

        char -- a byte string
        """
        x, y = self.term_cursor

        if isinstance(char, int):
            char = chr(char)

        dc = self.modes.display_ctrl

        if char == B("\x1b") and self.parsestate != 2: # escape
            self.within_escape = True
        elif not dc and char == B("\x0d"): # carriage return
            self.carriage_return()
        elif not dc and char == B("\x0f"): # activate G0
            self.charset.activate(0)
        elif not dc and char == B("\x0e"): # activate G1
            self.charset.activate(1)
        elif not dc and char in B("\x0a\x0b\x0c"): # line feed
            self.linefeed()
            if self.modes.lfnl:
                self.carriage_return()
        elif not dc and char == B("\x09"): # char tab
            self.tab()
        elif not dc and char == B("\x08"): # backspace
            if x > 0:
                self.set_term_cursor(x - 1, y)
        elif not dc and char == B("\x07") and self.parsestate != 2: # beep
            # we need to check if we're in parsestate 2, as an OSC can be
            # terminated by the BEL character!
            self.widget.beep()
        elif not dc and char in B("\x18\x1a"): # CAN/SUB
            self.leave_escape()
        elif not dc and char == B("\x7f"): # DEL
            pass # this is ignored
        elif self.within_escape:
            self.parse_escape(char)
        elif not dc and char == B("\x9b"): # CSI (equivalent to "ESC [")
            self.within_escape = True
            self.escbuf = bytes()
            self.parsestate = 1
        else:
            self.push_cursor(char)
Beispiel #19
0
def apply_text_layout(text, attr, ls, maxcol):
    t = []
    a = []
    c = []
    
    class AttrWalk:
        pass
    aw = AttrWalk
    aw.k = 0 # counter for moving through elements of a
    aw.off = 0 # current offset into text of attr[ak]
    
    def arange( start_offs, end_offs ):
        """Return an attribute list for the range of text specified."""
        if start_offs < aw.off:
            aw.k = 0
            aw.off = 0
        o = []
        while aw.off < end_offs:
            if len(attr)<=aw.k:
                # run out of attributes
                o.append((None,end_offs-max(start_offs,aw.off)))
                break
            at,run = attr[aw.k]
            if aw.off+run <= start_offs:
                # move forward through attr to find start_offs
                aw.k += 1
                aw.off += run
                continue
            if end_offs <= aw.off+run:
                o.append((at, end_offs-max(start_offs,aw.off)))
                break
            o.append((at, aw.off+run-max(start_offs, aw.off)))
            aw.k += 1
            aw.off += run
        return o

    
    for line_layout in ls:
        # trim the line to fit within maxcol
        line_layout = trim_line( line_layout, text, 0, maxcol )
        
        line = []
        linea = []
        linec = []
            
        def attrrange( start_offs, end_offs, destw ):
            """
            Add attributes based on attributes between
            start_offs and end_offs. 
            """
            if start_offs == end_offs:
                [(at,run)] = arange(start_offs,end_offs)
                rle_append_modify( linea, ( at, destw ))
                return
            if destw == end_offs-start_offs:
                for at, run in arange(start_offs,end_offs):
                    rle_append_modify( linea, ( at, run ))
                return
            # encoded version has different width
            o = start_offs
            for at, run in arange(start_offs, end_offs):
                if o+run == end_offs:
                    rle_append_modify( linea, ( at, destw ))
                    return
                tseg = text[o:o+run]
                tseg, cs = apply_target_encoding( tseg )
                segw = rle_len(cs)
                
                rle_append_modify( linea, ( at, segw ))
                o += run
                destw -= segw
            
            
        for seg in line_layout:
            #if seg is None: assert 0, ls
            s = LayoutSegment(seg)
            if s.end:
                tseg, cs = apply_target_encoding(
                    text[s.offs:s.end])
                line.append(tseg)
                attrrange(s.offs, s.end, rle_len(cs))
                rle_join_modify( linec, cs )
            elif s.text:
                tseg, cs = apply_target_encoding( s.text )
                line.append(tseg)
                attrrange( s.offs, s.offs, len(tseg) )
                rle_join_modify( linec, cs )
            elif s.offs:
                if s.sc:
                    line.append(bytes().rjust(s.sc))
                    attrrange( s.offs, s.offs, s.sc )
            else:
                line.append(bytes().rjust(s.sc))
                linea.append((None, s.sc))
                linec.append((None, s.sc))

        t.append(bytes().join(line))
        a.append(linea)
        c.append(linec)

    return TextCanvas(t, a, c, maxcol=maxcol)
Beispiel #20
0
    def keypress(self, size, key):
        if self.terminated:
            return key

        if key == "window resize":
            width, height = size
            self.touch_term(width, height)
            return

        if (self.last_key == self.escape_sequence
                and key == self.escape_sequence):
            # escape sequence pressed twice...
            self.last_key = key
            self.keygrab = True
            # ... so pass it to the terminal
        elif self.keygrab:
            if self.escape_sequence == key:
                # stop grabbing the terminal
                self.keygrab = False
                self.last_key = key
                return
        else:
            if key == 'page up':
                self.term.scroll_buffer()
                self.last_key = key
                self._invalidate()
                return
            elif key == 'page down':
                self.term.scroll_buffer(up=False)
                self.last_key = key
                self._invalidate()
                return
            elif (self.last_key == self.escape_sequence
                  and key != self.escape_sequence):
                # hand down keypress directly after ungrab.
                self.last_key = key
                return key
            elif self.escape_sequence == key:
                # start grabbing the terminal
                self.keygrab = True
                self.last_key = key
                return
            elif self._command_map[key] is None or key == 'enter':
                # printable character or escape sequence means:
                # lock in terminal...
                self.keygrab = True
                # ... and do key processing
            else:
                # hand down keypress
                self.last_key = key
                return key

        self.last_key = key

        self.term.scroll_buffer(reset=True)

        if key.startswith("ctrl "):
            if key[-1].islower():
                key = chr(ord(key[-1]) - ord('a') + 1)
            else:
                key = chr(ord(key[-1]) - ord('A') + 1)
        else:
            if self.term_modes.keys_decckm and key in KEY_TRANSLATIONS_DECCKM:
                key = KEY_TRANSLATIONS_DECCKM.get(key)
            else:
                key = KEY_TRANSLATIONS.get(key, key)

        # ENTER transmits both a carriage return and linefeed in LF/NL mode.
        if self.term_modes.lfnl and key == "\x0d":
            key += "\x0a"

        if sys.version_info[0] >= 3:
            key = bytes(key, 'ascii')

        os.write(self.master, key)
Beispiel #21
0
    def keypress(self, size, key):
        if self.terminated:
            return key

        if key == "window resize":
            width, height = size
            self.touch_term(width, height)
            return

        if self.last_key == self.escape_sequence and key == self.escape_sequence:
            # escape sequence pressed twice...
            self.last_key = key
            self.keygrab = True
            # ... so pass it to the terminal
        elif self.keygrab:
            if self.escape_sequence == key:
                # stop grabbing the terminal
                self.keygrab = False
                self.last_key = key
                return
        else:
            if key == "page up":
                self.term.scroll_buffer()
                self.last_key = key
                self._invalidate()
                return
            elif key == "page down":
                self.term.scroll_buffer(up=False)
                self.last_key = key
                self._invalidate()
                return
            elif self.last_key == self.escape_sequence and key != self.escape_sequence:
                # hand down keypress directly after ungrab.
                self.last_key = key
                return key
            elif self.escape_sequence == key:
                # start grabbing the terminal
                self.keygrab = True
                self.last_key = key
                return
            elif self._command_map[key] is None or key == "enter":
                # printable character or escape sequence means:
                # lock in terminal...
                self.keygrab = True
                # ... and do key processing
            else:
                # hand down keypress
                self.last_key = key
                return key

        self.last_key = key

        self.term.scroll_buffer(reset=True)

        if key.startswith("ctrl "):
            if key[-1].islower():
                key = chr(ord(key[-1]) - ord("a") + 1)
            else:
                key = chr(ord(key[-1]) - ord("A") + 1)
        else:
            if self.term_modes.keys_decckm and key in KEY_TRANSLATIONS_DECCKM:
                key = KEY_TRANSLATIONS_DECCKM.get(key)
            else:
                key = KEY_TRANSLATIONS.get(key, key)

        # ENTER transmits both a carriage return and linefeed in LF/NL mode.
        if self.term_modes.lfnl and key == "\x0d":
            key += "\x0a"

        if sys.version_info[0] >= 3:
            key = bytes(key, "ascii")

        os.write(self.master, key)
Beispiel #22
0
 def leave_escape(self):
     self.within_escape = False
     self.parsestate = 0
     self.escbuf = bytes()
Beispiel #23
0
def apply_text_layout(text, attr, ls, maxcol):
    t = []
    a = []
    c = []

    class AttrWalk:
        pass
    aw = AttrWalk
    aw.k = 0 # counter for moving through elements of a
    aw.off = 0 # current offset into text of attr[ak]

    def arange( start_offs, end_offs ):
        """Return an attribute list for the range of text specified."""
        if start_offs < aw.off:
            aw.k = 0
            aw.off = 0
        o = []
        while aw.off < end_offs:
            if len(attr)<=aw.k:
                # run out of attributes
                o.append((None,end_offs-max(start_offs,aw.off)))
                break
            at,run = attr[aw.k]
            if aw.off+run <= start_offs:
                # move forward through attr to find start_offs
                aw.k += 1
                aw.off += run
                continue
            if end_offs <= aw.off+run:
                o.append((at, end_offs-max(start_offs,aw.off)))
                break
            o.append((at, aw.off+run-max(start_offs, aw.off)))
            aw.k += 1
            aw.off += run
        return o


    for line_layout in ls:
        # trim the line to fit within maxcol
        line_layout = trim_line( line_layout, text, 0, maxcol )

        line = []
        linea = []
        linec = []

        def attrrange( start_offs, end_offs, destw ):
            """
            Add attributes based on attributes between
            start_offs and end_offs.
            """
            if start_offs == end_offs:
                [(at,run)] = arange(start_offs,end_offs)
                rle_append_modify( linea, ( at, destw ))
                return
            if destw == end_offs-start_offs:
                for at, run in arange(start_offs,end_offs):
                    rle_append_modify( linea, ( at, run ))
                return
            # encoded version has different width
            o = start_offs
            for at, run in arange(start_offs, end_offs):
                if o+run == end_offs:
                    rle_append_modify( linea, ( at, destw ))
                    return
                tseg = text[o:o+run]
                tseg, cs = apply_target_encoding( tseg )
                segw = rle_len(cs)

                rle_append_modify( linea, ( at, segw ))
                o += run
                destw -= segw


        for seg in line_layout:
            #if seg is None: assert 0, ls
            s = LayoutSegment(seg)
            if s.end:
                tseg, cs = apply_target_encoding(
                    text[s.offs:s.end])
                line.append(tseg)
                attrrange(s.offs, s.end, rle_len(cs))
                rle_join_modify( linec, cs )
            elif s.text:
                tseg, cs = apply_target_encoding( s.text )
                line.append(tseg)
                attrrange( s.offs, s.offs, len(tseg) )
                rle_join_modify( linec, cs )
            elif s.offs:
                if s.sc:
                    line.append(bytes().rjust(s.sc))
                    attrrange( s.offs, s.offs, s.sc )
            else:
                line.append(bytes().rjust(s.sc))
                linea.append((None, s.sc))
                linec.append((None, s.sc))

        t.append(bytes().join(line))
        a.append(linea)
        c.append(linec)

    return TextCanvas(t, a, c, maxcol=maxcol)