Esempio n. 1
0
    def keypress(self, size, key):
        if key in config.edit_node_key_remappings:
            key = config.edit_node_key_remappings[key]

        p = self.edit_pos
        if key == 'enter':
            self.tree_widget.stop_editing()
            return None

        # paste
        elif key == "ctrl y":
            for char in self.paste_buffer:
                p = move_next_char(self.edit_text, p, -1)
                self.set_edit_text(self.edit_text + char)
                self.set_edit_pos(p + 1)

        # kill to beginning of line
        elif key == "ctrl u":
            if not self._delete_highlighted():
                if p == 0:
                    return key

                while (p != 0):
                    p = move_prev_char(self.edit_text, 0, p)
                    self.paste_buffer = self.edit_text[p:] + self.paste_buffer
                    self.set_edit_text(self.edit_text[:p] +
                                       self.edit_text[self.edit_pos:])
                    self.set_edit_pos(p)

        # kill to beginning of word
        elif key == "ctrl w":
            if not self._delete_highlighted():
                if p == 0:
                    return key

                # first delete all whitespace
                while (p != 0) and (self.edit_text[p - 1] == ' '):
                    p = move_prev_char(self.edit_text, 0, p)
                    self.paste_buffer = self.edit_text[p:] + self.paste_buffer
                    self.set_edit_text(self.edit_text[:p] +
                                       self.edit_text[self.edit_pos:])
                    self.set_edit_pos(p)

                # then delete all characters until whitespace or the beginning of the node is found
                while (p != 0) and (self.edit_text[p - 1] != ' '):
                    p = move_prev_char(self.edit_text, 0, p)
                    self.paste_buffer = self.edit_text[p:] + self.paste_buffer
                    self.set_edit_text(self.edit_text[:p] +
                                       self.edit_text[self.edit_pos:])
                    self.set_edit_pos(p)

        (maxcol, maxrow) = size
        key = self.__super.keypress((maxcol, ), key)
Esempio n. 2
0
    def calculate_text_segments(self, text, width, wrap):
        """
        Calculate the segments of text to display given width screen
        columns to display them.

        text - unicode text or byte string to display
        width - number of available screen columns
        wrap - wrapping mode used

        Returns a layout structure without alignment applied.
        """
        nl, nl_o, sp_o = "\n", "\n", " "
        if PYTHON3 and isinstance(text, bytes):
            nl = B(nl) # can only find bytes in python3 bytestrings
            nl_o = ord(nl_o) # + an item of a bytestring is the ordinal value
            sp_o = ord(sp_o)
        b = []
        p = 0
        if wrap == 'clip':
            # no wrapping to calculate, so it's easy.
            while p<=len(text):
                n_cr = text.find(nl, p)
                if n_cr == -1:
                    n_cr = len(text)
                sc = calc_width(text, p, n_cr)
                l = [(0,n_cr)]
                if p!=n_cr:
                    l = [(sc, p, n_cr)] + l
                b.append(l)
                p = n_cr+1
            return b


        while p<=len(text):
            # look for next eligible line break
            n_cr = text.find(nl, p)
            if n_cr == -1:
                n_cr = len(text)
            sc = calc_width(text, p, n_cr)
            if sc == 0:
                # removed character hint
                b.append([(0,n_cr)])
                p = n_cr+1
                continue
            if sc <= width:
                # this segment fits
                b.append([(sc,p,n_cr),
                    # removed character hint
                    (0,n_cr)])

                p = n_cr+1
                continue
            pos, sc = calc_text_pos( text, p, n_cr, width )
            if pos == p: # pathological width=1 double-byte case
                raise CanNotDisplayText(
                    "Wide character will not fit in 1-column width")
            if wrap == 'any':
                b.append([(sc,p,pos)])
                p = pos
                continue
            assert wrap == 'space'
            if text[pos] == sp_o:
                # perfect space wrap
                b.append([(sc,p,pos),
                    # removed character hint
                    (0,pos)])
                p = pos+1
                continue
            if is_wide_char(text, pos):
                # perfect next wide
                b.append([(sc,p,pos)])
                p = pos
                continue
            prev = pos
            while prev > p:
                prev = move_prev_char(text, p, prev)
                if text[prev] == sp_o:
                    sc = calc_width(text,p,prev)
                    l = [(0,prev)]
                    if p!=prev:
                        l = [(sc,p,prev)] + l
                    b.append(l)
                    p = prev+1
                    break
                if is_wide_char(text,prev):
                    # wrap after wide char
                    next = move_next_char(text, prev, pos)
                    sc = calc_width(text,p,next)
                    b.append([(sc,p,next)])
                    p = next
                    break
            else:
                # unwrap previous line space if possible to
                # fit more text (we're breaking a word anyway)
                if b and (len(b[-1]) == 2 or ( len(b[-1])==1
                        and len(b[-1][0])==2 )):
                    # look for removed space above
                    if len(b[-1]) == 1:
                        [(h_sc, h_off)] = b[-1]
                        p_sc = 0
                        p_off = p_end = h_off
                    else:
                        [(p_sc, p_off, p_end),
                               (h_sc, h_off)] = b[-1]
                    if (p_sc < width and h_sc==0 and
                        text[h_off] == sp_o):
                        # combine with previous line
                        del b[-1]
                        p = p_off
                        pos, sc = calc_text_pos(
                            text, p, n_cr, width )
                        b.append([(sc,p,pos)])
                        # check for trailing " " or "\n"
                        p = pos
                        if p < len(text) and (
                            text[p] in (sp_o, nl_o)):
                            # removed character hint
                            b[-1].append((0,p))
                            p += 1
                        continue


                # force any char wrap
                b.append([(sc,p,pos)])
                p = pos
        return b
Esempio n. 3
0
    def calculate_text_segments( self, text, width, wrap ):
        """
        Calculate the segments of text to display given width screen 
        columns to display them.  
        
        text - text to display
        width - number of available screen columns
        wrap - wrapping mode used
        
        Returns a layout structure without aligmnent applied.
        """
        b = []
        p = 0
        if wrap == 'clip':
            # no wrapping to calculate, so it's easy.
            while p<=len(text):
                n_cr = text.find("\n", p)
                if n_cr == -1: 
                    n_cr = len(text)
                sc = calc_width(text, p, n_cr)
                l = [(0,n_cr)]
                if p!=n_cr:
                    l = [(sc, p, n_cr)] + l
                b.append(l)
                p = n_cr+1
            return b

        
        while p<=len(text):
            # look for next eligible line break
            n_cr = text.find("\n", p)
            if n_cr == -1: 
                n_cr = len(text)
            sc = calc_width(text, p, n_cr)
            if sc == 0:
                # removed character hint
                b.append([(0,n_cr)])
                p = n_cr+1
                continue
            if sc <= width:
                # this segment fits
                b.append([(sc,p,n_cr),
                    # removed character hint
                    (0,n_cr)])
                
                p = n_cr+1
                continue
            pos, sc = calc_text_pos( text, p, n_cr, width )
            # FIXME: handle pathological width=1 double-byte case
            if wrap == 'any':
                b.append([(sc,p,pos)])
                p = pos
                continue
            assert wrap == 'space'
            if text[pos] == " ":
                # perfect space wrap
                b.append([(sc,p,pos),
                    # removed character hint
                    (0,pos)])
                p = pos+1
                continue
            if is_wide_char(text, pos):
                # perfect next wide
                b.append([(sc,p,pos)])
                p = pos
                continue
            prev = pos    
            while prev > p:
                prev = move_prev_char(text, p, prev)
                if text[prev] == " ":
                    sc = calc_width(text,p,prev)
                    l = [(0,prev)]
                    if p!=prev:
                        l = [(sc,p,prev)] + l
                    b.append(l)
                    p = prev+1 
                    break
                if is_wide_char(text,prev):
                    # wrap after wide char
                    next = move_next_char(text, prev, pos)
                    sc = calc_width(text,p,next)
                    b.append([(sc,p,next)])
                    p = next
                    break
            else:
                # unwrap previous line space if possible to
                # fit more text (we're breaking a word anyway)
                if b and (len(b[-1]) == 2 or ( len(b[-1])==1 
                        and len(b[-1][0])==2 )):
                    # look for removed space above
                    if len(b[-1]) == 1:
                        [(h_sc, h_off)] = b[-1]
                        p_sc = 0
                        p_off = p_end = h_off
                    else:
                        [(p_sc, p_off, p_end),
                               (h_sc, h_off)] = b[-1]
                    if (p_sc < width and h_sc==0 and
                        text[h_off] == " "):
                        # combine with previous line
                        del b[-1]
                        p = p_off
                        pos, sc = calc_text_pos( 
                            text, p, n_cr, width )
                        b.append([(sc,p,pos)])
                        # check for trailing " " or "\n"
                        p = pos
                        if p < len(text) and (
                            text[p] in (" ","\n")):
                            # removed character hint
                            b[-1].append((0,p))
                            p += 1
                        continue
                        
                        
                # force any char wrap
                b.append([(sc,p,pos)])
                p = pos
        return b
Esempio n. 4
0
    def calculate_text_segments(self, text, width, wrap):
        """
        Calculate the segments of text to display given width screen
        columns to display them.

        text - unicode text or byte string to display
        width - number of available screen columns
        wrap - wrapping mode used

        Returns a layout structure without alignment applied.
        """

        # TODO: This function is a horror and a mess, and really hard to
        # understand. It's based on urwids StandardLayout, which by itself
        # is overly complex, and I added tab handling, which made it worse.
        # It's a prime candidate for refacturing, making easier to understand
        # and as it is heavily used, profiling would be nice too.

        nl, nl_o, sp_o, tab_o = "\n", "\n", " ", "\t"
        if PYTHON3 and isinstance(text, bytes):
            nl = B(nl)  # can only find bytes in python3 bytestrings
            nl_o = ord(nl_o)  # + an item of a bytestring is the ordinal value
            sp_o = ord(sp_o)
            tab_o = ord(tab_o)
        b = []
        p = 0
        if wrap == 'clip':
            # no wrapping to calculate, so it's easy.
            l = []
            while p <= len(text):
                n_cr = find_newline(text, p)
                if p != n_cr:
                    line = text[p:n_cr]
                    pt = 0
                    while pt < len(line):
                        n_tab = line.find(tab_o, pt)
                        if n_tab == -1:
                            end = len(line)
                        else:
                            end = n_tab

                        sc = calc_width(line, pt, end)
                        if sc != 0:
                            l.append((sc, p + pt, p + end))

                        if end == n_tab:  # A tab was found
                            extra_space = (self.tab_width - (
                                sc % self.tab_width))
                            l.append((extra_space, p + n_tab))

                        pt = end + 1

                l.append((0, n_cr))
                b.append(l)
                l = []
                if text[n_cr:n_cr+2] in TWOCHAR_NEWLINES:
                    # Two char newline:
                    p = n_cr + 2
                else:
                    p = n_cr + 1
            return b

        while p <= len(text):
            # look for next eligible line break
            n_cr = find_newline(text, p)

            line = text[p:n_cr]
            l = []
            pt = 0
            lc = 0
            while pt < len(line):
                n_tab = line.find(tab_o, pt)
                if n_tab == -1:
                    end = len(line)
                else:
                    end = n_tab

                sc = calc_width(line, pt, end)

                if lc + sc <= width:
                    # this segment fits
                    if sc:
                        l.append((sc, p + pt, p + end))
                    if end == n_tab:  # A tab was found
                        extra_space = self.tab_width - (sc % self.tab_width)
                        l.append((extra_space, p + n_tab))
                        lc += extra_space
                    else:
                        # removed character hint
                        l.append((0, p + end))

                    pt = end + 1
                    lc += sc

                    if lc >= width:
                        # The tab can sometimes push line length to width, and
                        # then we adjust the line length and make a new line.
                        overshoot = lc - width
                        spaces, pos = l[-1]
                        l[-1] = (spaces - overshoot, pos)
                        b.append(l)
                        l = []
                        lc = 0
                    continue

                # This segment does not fit. Let's fit it.
                pos, sc = calc_text_pos(line, pt, end, width - lc)
                if pos == pt:  # pathological width=1 double-byte case
                    raise CanNotDisplayText(
                        "Wide character will not fit in 1-column width")

                if wrap == 'any':
                    l.append((sc, p + pt, p + pos))
                    l.append((0, p + pos))
                    b.append(l)
                    l = []
                    lc = 0
                    pt = pos
                    continue

                assert wrap == 'space'
                if line[pos] == sp_o:
                    # perfect space wrap
                    l.append((sc, p + pt, p + pos))
                    # removed character hint
                    l.append((0, p + pos))
                    b.append(l)
                    l = []
                    lc = 0
                    pt = pos + 1
                    continue

                if is_wide_char(line, pos):
                    # perfect next wide
                    l.append((sc, p + pt, p + pos))
                    b.append(l)
                    l = []
                    lc = 0
                    pt = pos
                    continue

                prev = pos
                while prev > pt:
                    prev = move_prev_char(line, pt, prev)
                    if line[prev] == sp_o:
                        sc = calc_width(line, pt, prev)
                        if prev != pt:
                            l.append((sc, p + pt, p + prev))
                        l.append((0, p + prev))
                        b.append(l)
                        l = []
                        lc = 0
                        pt = prev + 1
                        break

                    if is_wide_char(line, prev):
                        # wrap after wide char
                        nextc = move_next_char(line, prev, pos)
                        sc = calc_width(line, pt, nextc)
                        l.append((sc, p + pt, p + nextc))
                        b.append(l)
                        l = []
                        lc = 0
                        pt = nextc
                        break
                else:
                    if lc == 0:
                        # unwrap previous line space if possible to
                        # fit more text (we're breaking a word anyway)
                        if b and (len(b[-1]) == 2 or (len(b[-1]) == 1 and
                                                      len(b[-1][0]) == 2)):
                            # look for removed space above
                            if len(b[-1]) == 1:
                                [(h_sc, h_off)] = b[-1]
                                p_sc = 0
                                p_off = p_end = h_off
                            else:
                                [(p_sc, p_off, p_end),
                                 (h_sc, h_off)] = b[-1][-2:]
                            if (p_sc < width and h_sc == 0 and
                               text[h_off] == sp_o):
                                # combine with previous line
                                old_line = b[-1][:-2]
                                del b[-1]
                                pt = p_off - p
                                pos, sc = calc_text_pos(
                                    line, pt, end, width)
                                old_line.append((sc, p + pt, p + pos))
                                b.append(old_line)
                                # check for trailing " " or "\n"
                                pt = pos
                                if pt < len(text) and (
                                   text[pt] in (sp_o, nl_o)):
                                    # removed character hint
                                    b[-1].append((0, p + pt))
                                    pt += 1
                                continue
                    # Break on previous tab, and try again.
                    if l:
                        b.append(l)
                        l = []
                        lc = 0
                        continue

                    # There is no space to break the line on, unwrapping the
                    # previous line doesn't help, I guess we just break on a
                    # character.
                    b.append([(sc, p + pt, p + pos)])
                    l = []
                    lc = 0
                    pt = pos

            # force any char wrap
            if l:
                b.append(l)
            elif not line:
                # An empty line.
                b.append([(0, n_cr)])
                pt = 1

            if text[pt-1:pt+1] in TWOCHAR_NEWLINES:
                # Two char newline:
                pt += 1
            p += pt
        return b
Esempio n. 5
0
File: editor.py Progetto: gvx/ovic
 def keypress(self, size, key):
     if self.mode == 'n':
         p = self.edit_pos
         if key.isdigit():
             self.count += key
             self.draw_statusbar(size)
         elif key == 'esc':
             self.reset_command()
             self.draw_statusbar(size)
         elif key == 'i':
             self.set_mode('i', size)
         elif key == 'h':
             if p == 0:
                 return
             p = move_prev_char(self.edit_text, 0, p)
             self.set_edit_pos(p)
         elif key == 'j':
             x, y = self.get_cursor_coords(size)
             pref_col = self.get_pref_col(size)
             assert pref_col is not None
             if not self.move_cursor_to_coords(size, pref_col, y + 1):
                 return
         elif key == 'k':
             x, y = self.get_cursor_coords(size)
             pref_col = self.get_pref_col(size)
             assert pref_col is not None
             if not self.move_cursor_to_coords(size, pref_col, y - 1):
                 return
         elif key == 'l':
             if p >= len(self.edit_text):
                 return
             p = move_next_char(self.edit_text, p, len(self.edit_text))
             self.set_edit_pos(p)
         elif key == ':':
             self.command_start(':')
         elif key == '/':
             self.command_start('/')
         else:
             if key in self.path:
                 self.path = self.path[key]
                 if callable(self.path):
                     if self.path.command_or_motion == 'motion':
                         self.do_command(self.path, size)
                         if self.future_command:
                             self.do_command(self.future_command, size)
                         else:
                             self.master.document.move_caret()
                             self.move_cursor_to_coords(size, self.master.document.caret.offset, self.master.document.caret.par)
                         self.reset_command()
                     elif self.path.immediate:
                         self.do_command(self.path, size)
                         self.reset_command()
                     else:
                         self.future_command = self.path
                         self.reset_command_path()
                         self.draw_statusbar(size)
             else:
                 self.reset_command()
     elif self.mode == 'i':
         if key == 'esc':
             self.set_mode('n', size)
         elif key == 'meta enter':
             self.insert_text('\n')
         elif key == 'enter':
             self.insert_text('\n\n')
         else:
             super(Editor, self).keypress(size, key)
Esempio n. 6
0
    def calculate_text_segments(self, text, width, wrap):
        """
        Calculate the segments of text to display given width screen
        columns to display them.

        text - unicode text or byte string to display
        width - number of available screen columns
        wrap - wrapping mode used

        Returns a layout structure without aligmnent applied.
        """
        nl, nl_o, sp_o = "\n", "\n", " "
        if PYTHON3 and isinstance(text, bytes):
            nl = B(nl)  # can only find bytes in python3 bytestrings
            nl_o = ord(nl_o)  # + an item of a bytestring is the ordinal value
            sp_o = ord(sp_o)
        b = []
        p = 0
        if wrap == 'clip':
            # no wrapping to calculate, so it's easy.
            while p <= len(text):
                n_cr = text.find(nl, p)
                if n_cr == -1:
                    n_cr = len(text)
                sc = calc_width(text, p, n_cr)
                l = [(0, n_cr)]
                if p != n_cr:
                    l = [(sc, p, n_cr)] + l
                b.append(l)
                p = n_cr + 1
            return b

        while p <= len(text):
            # look for next eligible line break
            n_cr = text.find(nl, p)
            if n_cr == -1:
                n_cr = len(text)
            sc = calc_width(text, p, n_cr)
            if sc == 0:
                # removed character hint
                b.append([(0, n_cr)])
                p = n_cr + 1
                continue
            if sc <= width:
                # this segment fits
                b.append([
                    (sc, p, n_cr),
                    # removed character hint
                    (0, n_cr)
                ])

                p = n_cr + 1
                continue
            pos, sc = calc_text_pos(text, p, n_cr, width)
            if pos == p:  # pathological width=1 double-byte case
                raise CanNotDisplayText(
                    "Wide character will not fit in 1-column width")
            if wrap == 'any':
                b.append([(sc, p, pos)])
                p = pos
                continue
            assert wrap == 'space'
            if text[pos] == sp_o:
                # perfect space wrap
                b.append([
                    (sc, p, pos),
                    # removed character hint
                    (0, pos)
                ])
                p = pos + 1
                continue
            if is_wide_char(text, pos):
                # perfect next wide
                b.append([(sc, p, pos)])
                p = pos
                continue
            prev = pos
            while prev > p:
                prev = move_prev_char(text, p, prev)
                if text[prev] == sp_o:
                    sc = calc_width(text, p, prev)
                    l = [(0, prev)]
                    if p != prev:
                        l = [(sc, p, prev)] + l
                    b.append(l)
                    p = prev + 1
                    break
                if is_wide_char(text, prev):
                    # wrap after wide char
                    next = move_next_char(text, prev, pos)
                    sc = calc_width(text, p, next)
                    b.append([(sc, p, next)])
                    p = next
                    break
            else:
                # unwrap previous line space if possible to
                # fit more text (we're breaking a word anyway)
                if b and (len(b[-1]) == 2 or
                          (len(b[-1]) == 1 and len(b[-1][0]) == 2)):
                    # look for removed space above
                    if len(b[-1]) == 1:
                        [(h_sc, h_off)] = b[-1]
                        p_sc = 0
                        p_off = p_end = h_off
                    else:
                        [(p_sc, p_off, p_end), (h_sc, h_off)] = b[-1]
                    if (p_sc < width and h_sc == 0 and text[h_off] == sp_o):
                        # combine with previous line
                        del b[-1]
                        p = p_off
                        pos, sc = calc_text_pos(text, p, n_cr, width)
                        b.append([(sc, p, pos)])
                        # check for trailing " " or "\n"
                        p = pos
                        if p < len(text) and (text[p] in (sp_o, nl_o)):
                            # removed character hint
                            b[-1].append((0, p))
                            p += 1
                        continue

                # force any char wrap
                b.append([(sc, p, pos)])
                p = pos
        return b
Esempio n. 7
0
 def cmd_move_left(self, pressed=CURSOR_LEFT):
   if self.p==0: return pressed
   p = move_prev_char(self.edit_text,0,self.p)
   self.set_edit_pos(p)
Esempio n. 8
0
    def keypress(self, size, key):
        """
        Handle editing keystrokes, return others.

        >>> e, size = Edit(), (20,)
        >>> e.keypress(size, 'x')
        >>> e.keypress(size, 'left')
        >>> e.keypress(size, '1')
        >>> print e.edit_text
        1x
        >>> e.keypress(size, 'backspace')
        >>> e.keypress(size, 'end')
        >>> e.keypress(size, '2')
        >>> print e.edit_text
        x2
        >>> e.keypress(size, 'shift f1')
        'shift f1'
        """
        (maxcol,) = size

        p = self.edit_pos
        if self.valid_char(key):
            self.insert_text( key )

        elif key=="tab" and self.allow_tab:
            key = " "*(8-(self.edit_pos%8))
            self.insert_text( key )

        elif key=="enter" and self.multiline:
            key = "\n"
            self.insert_text( key )

        elif command_map[key] == 'cursor left':
            if p==0: return key
            p = move_prev_char(self.edit_text,0,p)
            self.set_edit_pos(p)
        
        elif command_map[key] == 'cursor right':
            if p >= len(self.edit_text): return key
            p = move_next_char(self.edit_text,p,len(self.edit_text))
            self.set_edit_pos(p)
        
        elif command_map[key] in ('cursor up', 'cursor down'):
            self.highlight = None
            
            x,y = self.get_cursor_coords((maxcol,))
            pref_col = self.get_pref_col((maxcol,))
            assert pref_col is not None
            #if pref_col is None: 
            #    pref_col = x

            if command_map[key] == 'cursor up': y -= 1
            else: y += 1

            if not self.move_cursor_to_coords((maxcol,),pref_col,y):
                return key
        
        elif key=="backspace":
            self.pref_col_maxcol = None, None
            if not self._delete_highlighted():
                if p == 0: return key
                p = move_prev_char(self.edit_text,0,p)
                self.set_edit_text( self.edit_text[:p] + 
                    self.edit_text[self.edit_pos:] )
                self.set_edit_pos( p )

        elif key=="delete":
            self.pref_col_maxcol = None, None
            if not self._delete_highlighted():
                if p >= len(self.edit_text):
                    return key
                p = move_next_char(self.edit_text,p,len(self.edit_text))
                self.set_edit_text( self.edit_text[:self.edit_pos] + 
                    self.edit_text[p:] )
        
        elif command_map[key] in ('cursor max left', 'cursor max right'):
            self.highlight = None
            self.pref_col_maxcol = None, None
            
            x,y = self.get_cursor_coords((maxcol,))
            
            if command_map[key] == 'cursor max left':
                self.move_cursor_to_coords((maxcol,), LEFT, y)
            else:
                self.move_cursor_to_coords((maxcol,), RIGHT, y)
            return
            
            
        else:
            # key wasn't handled
            return key
Esempio n. 9
0
    def keypress(self, size, key):
        """
        Handle editing keystrokes, return others.

        >>> e, size = Edit(), (20,)
        >>> e.keypress(size, 'x')
        >>> e.keypress(size, 'left')
        >>> e.keypress(size, '1')
        >>> print e.edit_text
        1x
        >>> e.keypress(size, 'backspace')
        >>> e.keypress(size, 'end')
        >>> e.keypress(size, '2')
        >>> print e.edit_text
        x2
        >>> e.keypress(size, 'shift f1')
        'shift f1'
        """
        (maxcol, ) = size

        p = self.edit_pos
        if self.valid_char(key):
            self.insert_text(key)

        elif key == "tab" and self.allow_tab:
            key = " " * (8 - (self.edit_pos % 8))
            self.insert_text(key)

        elif key == "enter" and self.multiline:
            key = "\n"
            self.insert_text(key)

        elif self._command_map[key] == 'cursor left':
            if p == 0: return key
            p = move_prev_char(self.edit_text, 0, p)
            self.set_edit_pos(p)

        elif self._command_map[key] == 'cursor right':
            if p >= len(self.edit_text): return key
            p = move_next_char(self.edit_text, p, len(self.edit_text))
            self.set_edit_pos(p)

        elif self._command_map[key] in ('cursor up', 'cursor down'):
            self.highlight = None

            x, y = self.get_cursor_coords((maxcol, ))
            pref_col = self.get_pref_col((maxcol, ))
            assert pref_col is not None
            #if pref_col is None:
            #    pref_col = x

            if self._command_map[key] == 'cursor up': y -= 1
            else: y += 1

            if not self.move_cursor_to_coords((maxcol, ), pref_col, y):
                return key

        elif key == "backspace":
            self.pref_col_maxcol = None, None
            if not self._delete_highlighted():
                if p == 0: return key
                p = move_prev_char(self.edit_text, 0, p)
                self.set_edit_text(self.edit_text[:p] +
                                   self.edit_text[self.edit_pos:])
                self.set_edit_pos(p)

        elif key == "delete":
            self.pref_col_maxcol = None, None
            if not self._delete_highlighted():
                if p >= len(self.edit_text):
                    return key
                p = move_next_char(self.edit_text, p, len(self.edit_text))
                self.set_edit_text(self.edit_text[:self.edit_pos] +
                                   self.edit_text[p:])

        elif self._command_map[key] in ('cursor max left', 'cursor max right'):
            self.highlight = None
            self.pref_col_maxcol = None, None

            x, y = self.get_cursor_coords((maxcol, ))

            if self._command_map[key] == 'cursor max left':
                self.move_cursor_to_coords((maxcol, ), LEFT, y)
            else:
                self.move_cursor_to_coords((maxcol, ), RIGHT, y)
            return

        else:
            # key wasn't handled
            return key
Esempio n. 10
0
File: widget.py Progetto: eykd/urwid
    def keypress(self, size, key):
        """
        Handle editing keystrokes, return others.

        >>> e, size = Edit(), (20,)
        >>> e.keypress(size, 'x')
        >>> e.keypress(size, 'left')
        >>> e.keypress(size, '1')
        >>> print e.edit_text
        1x
        >>> e.keypress(size, 'backspace')
        >>> e.keypress(size, 'end')
        >>> e.keypress(size, '2')
        >>> print e.edit_text
        x2
        >>> e.keypress(size, 'shift f1')
        'shift f1'
        """
        (maxcol,) = size

        p = self.edit_pos
        if self.valid_char(key):
            if (isinstance(key, unicode) and not
                    isinstance(self._caption, unicode)):
                # screen is sending us unicode input, must be using utf-8
                # encoding because that's all we support, so convert it
                # to bytes to match our caption's type
                key = key.encode('utf-8')
            self.insert_text(key)

        elif key=="tab" and self.allow_tab:
            key = " "*(8-(self.edit_pos%8))
            self.insert_text(key)

        elif key=="enter" and self.multiline:
            key = "\n"
            self.insert_text(key)

        elif self._command_map[key] == 'cursor left':
            if p==0: return key
            p = move_prev_char(self.edit_text,0,p)
            self.set_edit_pos(p)
        
        elif self._command_map[key] == 'cursor right':
            if p >= len(self.edit_text): return key
            p = move_next_char(self.edit_text,p,len(self.edit_text))
            self.set_edit_pos(p)
        
        elif self._command_map[key] in ('cursor up', 'cursor down'):
            self.highlight = None
            
            x,y = self.get_cursor_coords((maxcol,))
            pref_col = self.get_pref_col((maxcol,))
            assert pref_col is not None
            #if pref_col is None: 
            #    pref_col = x

            if self._command_map[key] == 'cursor up': y -= 1
            else: y += 1

            if not self.move_cursor_to_coords((maxcol,),pref_col,y):
                return key
        
        elif key=="backspace":
            self.pref_col_maxcol = None, None
            if not self._delete_highlighted():
                if p == 0: return key
                p = move_prev_char(self.edit_text,0,p)
                self.set_edit_text( self.edit_text[:p] + 
                    self.edit_text[self.edit_pos:] )
                self.set_edit_pos( p )

        elif key=="delete":
            self.pref_col_maxcol = None, None
            if not self._delete_highlighted():
                if p >= len(self.edit_text):
                    return key
                p = move_next_char(self.edit_text,p,len(self.edit_text))
                self.set_edit_text( self.edit_text[:self.edit_pos] + 
                    self.edit_text[p:] )
        
        elif self._command_map[key] in ('cursor max left', 'cursor max right'):
            self.highlight = None
            self.pref_col_maxcol = None, None
            
            x,y = self.get_cursor_coords((maxcol,))
            
            if self._command_map[key] == 'cursor max left':
                self.move_cursor_to_coords((maxcol,), LEFT, y)
            else:
                self.move_cursor_to_coords((maxcol,), RIGHT, y)
            return
            
            
        else:
            # key wasn't handled
            return key
Esempio n. 11
0
    def keypress(self, size, key):
        (maxcol, maxrow) = size

        focus_widget, pos = self.body.get_focus()

        # This is copied. I don't understand what it does.
        # I will test to remove it, but later.
        def actual_key(unhandled):
            if unhandled:
                return key

        if self.set_focus_pending or self.set_focus_valign_pending:
            self._set_focus_complete((maxcol, maxrow), focus=True)

        if self._valid_char(key):
            self._insert_char(key, focus_widget, pos)
            return

        if key == "tab":
            # Tab is magical and maps to different commands in different
            # situations. So far we insert a tab, though.
            self._insert_char('\t', focus_widget, pos)
            return

        if key == "enter":
            # We don't want to be able to remap enter, so we handle it here,
            # shortcutting it's command mapping.
            self.body.split_focus('\n')
            return

        command = self._command_map[key]
        # pass off the heavy lifting
        if command == urwid.CURSOR_UP:
            return actual_key(self._keypress_up((maxcol, maxrow)))

        if command == urwid.CURSOR_DOWN:
            return actual_key(self._keypress_down((maxcol, maxrow)))

        if command == urwid.CURSOR_PAGE_UP:
            return actual_key(self._keypress_page_up((maxcol, maxrow)))

        if command == urwid.CURSOR_PAGE_DOWN:
            return actual_key(self._keypress_page_down((maxcol, maxrow)))

        if command == urwid.CURSOR_MAX_LEFT:
            focus_widget.set_edit_pos(0)
            return

        if command == urwid.CURSOR_MAX_RIGHT:
            focus_widget.set_edit_pos(focus_widget.get_edit_len())
            return

        if command == urwid.CURSOR_LEFT:
            col = focus_widget.edit_pos
            if col != 0:
                col = move_prev_char(focus_widget.edit_text, 0, col)
                focus_widget.set_edit_pos(col)
                return

            # Start of line, move to previous line, if any:
            if self.focus_position == 0:
                # No previous line
                return key

            focus_widget, pos = self.body.get_prev(pos)
            self.set_focus(pos, 'below')
            self.keypress(size, "end")
            return

        if command == urwid.CURSOR_RIGHT:
            col = focus_widget.edit_pos
            l = focus_widget.get_edit_len()
            if col < l:
                col = move_next_char(focus_widget.edit_text, col,
                                     len(focus_widget.edit_text))
                focus_widget.set_edit_pos(col)
                return

            # We are moving beyond the end of line, go to next line.
            focus_widget, pos = self.body.get_next(pos)
            if not focus_widget:
                # No more lines
                return key

            self.set_focus(pos, 'above')
            self.keypress(size, "home")
            return

        if command == ERASE_LEFT:
            col = focus_widget.edit_pos
            if col == 0:
                if pos == 0:
                    # Nothing to delete
                    return key
                # Merge the lines
                self.body.combine_focus_with_prev()
                return
            self.body.code.delete_text(pos, col-1, pos, col)
            focus_widget.set_edit_text(self.body.code[pos])
            focus_widget.set_edit_pos(col-1)
            return

        if command == ERASE_RIGHT:
            col = focus_widget.edit_pos
            if col == focus_widget.get_edit_len():
                # End of line
                nextline, ignore = self.body.get_next(pos)
                if nextline is None:
                    # Nothing to delete
                    return key
                # Merge the lines
                self.body.combine_focus_with_next()
                return
            self.body.code.delete_text(pos, col, pos, col + 1)
            focus_widget.set_edit_text(self.body.code[pos])
            return

        return key