lineabstraction.py :  » IDE » PyPE » PyPE-2.9.1 » plugins » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » IDE » PyPE 
PyPE » PyPE 2.9.1 » plugins » lineabstraction.py

'''
Line-based abstraction layer over StyledTextCtrl.

This software is licensed under the GPL (GNU General Public License) version 2
as it appears here: http://www.gnu.org/copyleft/gpl.html
It is also included with this archive as `gpl.txt <gpl.txt>`_.

'''

import sys

KE = "%s does not support %s"
KE2 = "%s does not support strides != 1, your stride was %s"
TE = "%s requires lines that subclass from basestring not %s"

def Property(name, bases, dict):
    get = dict.get('get', None)
    set = dict.get('set', None)
    de1 = dict.get('de1', None) #that's a numeral 1
    doc = dict.get('__doc__', None)
    return property(get, set, de1, doc)

class LineAbstraction(object):
    if 1:
        '''
        A 0-indexed line abstraction that supports manipulation of the
        provided document.
        '''
        __slots__ = ('stc curline curlinei curlinep selectedlines '
                     'selectedlinesi targetlines targetlinesi ').split()
    
    def __init__(self, stc):
        self.stc = stc
    
    def _mod(self):
        self.stc.gotcharacter()
    
    class curline:
        if 1:
            '''
            Manipulates the current line.
            '''
        __metaclass__ = Property
        def get(self):
            return self[self.curlinei]
        def set(self, value):
            self[self.curlinei] = value
            self._mod()
        def de1(self):
            del self[self.curlinei]
            self._mod()
    
    class curlinei:
        if 1:
            '''
            Manipulates the current line's index.
            '''
        __metaclass__ = Property
        def get(self):
            x = self.stc.GetCurrentPos()
            return self.stc.LineFromPosition(x)
        def set(self, index):
            x,y = self._line_range(index)
            self.stc.SetSelection(x,x)
    
    class curlinep:
        if 1:
            '''
            Manipulates the cursor position in the current line.
            '''
        __metaclass__ = Property
        def get(self):
            x = self.stc.GetCurrentPos()
            y = self.stc.LineFromPosition(x)
            y = self.stc.PositionFromLine(y)
            curline = self.curline
            if type(curline) is not unicode:
                return x-y
            #the stc gives offsets related to character positions in utf-8
            #encoded text
            return len(curline.encode('utf-8')[:x-y].decode('utf-8'))
        def set(self, posn):
            x = self.stc.GetCurrentPos()
            y = self.stc.LineFromPosition(x)
            y = self.stc.PositionFromLine(y)
            curline = self.curline
            if posn < 0:
                posn %= len(curline)
            if posn > len(curline):
                posn = len(curline)
            #need to convert to utf-8 encoded offsets on unicode platforms
            if type(curline) is unicode:
                posn = len(curline[:posn].encode('utf-8'))
            self.stc.SetSelection(y+posn, y+posn)
    
    class selectedlines:
        if 1:
            '''
            Manipulates the currently selected lines.
            Setting requires a sequence of lines, CR and LF endings are
            pre-rstripped from theinputlinesinsertedonebetweeneachline import 
            during setting.
            '''
        __metaclass__ = Property
        def get(self):
            return [self[i] for i in xrange(*self.selectedlinesi)]
        
        def set(self, value):
            self.selectedlinesi = self.selectedlinesi
            p = self.stc.GetSelection()[0]
            if value and (value[-1].endswith('\r') or value[-1].endswith('\n')):
                #we don't want to use += here!
                value = value + ['']
            self.stc.ReplaceSelection(self.stc.format.join([i.rstrip('\r\n') for i in value]))
            self.stc.SetSelection(p, self.stc.GetSelection()[1])
        
        def de1(self):
            self.selectedlinesi = self.selectedlinesi
            self.stc.ReplaceSelection('')
            self._mod()
    
    class selectedlinesi:
        if 1:
            '''
            Manipulates the indices of the currently selected lines.
            '''
        __metaclass__ = Property
        def get(self):
            x,y = self.stc.GetSelection()
            x,y = min(x,y), max(x,y)
            start = self._line_range(self.stc.LineFromPosition(x))[0]
            #we use y-1 because otherwise
            #for i in xrange(10):
            #    lines.selectedlinesi = lines.selectedlinesi
            #will continually select more and more lines
            end = self._line_range(self.stc.LineFromPosition(y-1))[1]
            return self.stc.LineFromPosition(start), self.stc.LineFromPosition(max(end-1, start))+1
        
        def set(self, range):
            try:
                start, end = range
            except:
                raise ValueError, "selected line range must be a sequence of integers of length 2"
            if end < start:
                start, end = end, start
            start = self._line_range(start)[0]
            end = self._line_range(end)[0]
            self.stc.SetSelection(start, end)
            self._mod()
    
    class targetlines:
        if 1:
            '''
            Manipulates the currently targeted lines.
            Setting requires a sequence of lines, CR and LF endings are
            pre-rstripped from theinputlinesinsertedonebetweeneachline import 
            during setting.
            '''
        __metaclass__ = Property
        def get(self):
            return [self[i] for i in xrange(*self.targetlinesi)]
        
        def set(self, value):
            self.targetlinesi = self.targetlinesi
            if value and (value[-1].endswith('\r') or value[-1].endswith('\n')):
                #we don't want to use += here!
                value = value + ['']
            self.stc.ReplaceTarget(self.stc.format.join([i.rstrip('\r\n') for i in value]))
            self._mod()
        
        def de1(self):
            self.targetlinesi = self.targetlinesi
            self.stc.ReplaceTarget('')
            self._mod()
    
    class targetlinesi:
        if 1:
            '''
            Manipulates the indices of the currently targeted lines.
            '''
        __metaclass__ = Property
        def get(self):
            x,y = self.stc.GetTargetStart(), self.stc.GetTargetEnd()
            x,y = min(x,y), max(x,y)
            start = self._line_range(self.stc.LineFromPosition(x))[0]
            #we use y-1 because otherwise
            #for i in xrange(10):
            #    lines.selectedlinesi = lines.selectedlinesi
            #will continually select more and more lines
            end = self._line_range(self.stc.LineFromPosition(y-1))[1]
            return self.stc.LineFromPosition(start), self.stc.LineFromPosition(max(end-1, start))+1
        
        def set(self, range):
            try:
                start, end = range
            except:
                raise ValueError, "selected line range must be a sequence of integers of length 2"
            if end < start:
                start, end = end, start
            start = self._line_range(start)[0]
            end = self._line_range(end)[0]
            self.stc.SetTargetStart(start)
            self.stc.SetTargetEnd(end)
    
    def get_indent(self, lineno):
        '''
        Allows read-only access to indent level for particular lines.
        '''
        line = self[lineno]
        ci = len(line) - len(line.lstrip())
        # do we care about the fact that this line is blank?
        return len(line[:ci].replace('\t', 8))
    
    def __len__(self):
        return self.stc.GetLineCount()
    
    def _line_range(self, index):
        '''
        Utility method for getting the starting and ending position of this
        line.
        '''
        if not isinstance(index, (int, long)):
            raise KeyError, KE%(self.__class__, type(index))
        x = len(self)
        if index < 0:
            index %= x
        y = self.stc.GetTextLength()
        if index >= x:
            return y,y
        elif x == 1:
            return 0,y
        elif index == 0:
            return 0, self.stc.PositionFromLine(1)
        elif index == x-1:
            return self.stc.PositionFromLine(index), y
        else:
            return self.stc.PositionFromLine(index), self.stc.PositionFromLine(index+1)
    
    def __getitem__(self, index):
        '''
        Gets a line or contiguous sequence of lines.
        That is, it supports slices, but step must be equal to 1.
        '''
        if not isinstance(index, (int, long, slice)):
            raise KeyError, KE%(self.__class__, type(index))
        if isinstance(index, slice):
            if index.step not in (1, None):
                raise KeyError, KE2%(self.__class__, index.step)
            start = max(index.start, 0)
            stop = index.stop
            if stop == None:
                stop = sys.maxint
            stop = min(stop, len(self)-1)
            return [self[i] for i in xrange(start, stop)]
        return self.stc.GetTextRange(*self._line_range(index))
    
    def __setitem__(self, index, value):
        '''
        Changes the content of a line.
        Your new line must include a line ending if you want to keep this line
        separate from thenext. import 
        Does not support slices.
        '''
        
        if not isinstance(value, basestring):
            raise TypeError, TE%(self.__class__, type(value))
        y,z = self._line_range(index)
        self.stc.SetTargetStart(y)
        self.stc.SetTargetEnd(z)
        self.stc.ReplaceTarget(value)
        self._mod()
    
    def __delitem__(self, index):
        '''
        Deletes a particular line.
        '''
        self[index] = ''
        self._mod()
    
    def __iter__(self):
        '''
        Yields every line in the file in order (uses a 'current line' index,
        so things like:
            
            for i,j in enumerate(lines):
                del lines[i]
        
        will actually delete every other line.
        '''
        i = 0
        while i < len(self):
            yield self[i]
            i += 1
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.