buffer.py 4.21 KB
Newer Older
xuebingbing's avatar
xuebingbing committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
"""Buffer class."""

__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id: buffer.py 54528 2008-07-07 18:35:49Z RD $"
__revision__ = "$Revision: 54528 $"[11:-2]

from interpreter import Interpreter
import imp
import os
import sys

import document


class Buffer:
    """Buffer class."""

    id = 0

    def __init__(self, filename=None):
        """Create a Buffer instance."""
        Buffer.id += 1
        self.id = Buffer.id
        self.interp = Interpreter(locals={})
        self.name = ''
        self.editors = {}
        self.editor = None
        self.modules = sys.modules.keys()
        self.syspath = sys.path[:]
        while True:
            try:
                self.syspath.remove('')
            except ValueError:
                break
        while True:
            try:
                self.syspath.remove('.')
            except ValueError:
                break
        self.open(filename)

    def addEditor(self, editor):
        """Add an editor."""
        self.editor = editor
        self.editors[editor.id] = editor

    def hasChanged(self):
        """Return True if text in editor has changed since last save."""
        if self.editor:
            return self.editor.hasChanged()
        else:
            return False

    def new(self, filepath):
        """New empty buffer."""
        if not filepath:
            return
        if os.path.exists(filepath):
            self.confirmed = self.overwriteConfirm(filepath)
        else:
            self.confirmed = True

    def open(self, filename):
        """Open file into buffer."""
        self.doc = document.Document(filename)
        self.name = self.doc.filename or ('Untitled:' + str(self.id))
        self.modulename = self.doc.filebase
        # XXX This should really make sure filedir is first item in syspath.
        # XXX Or maybe this should be moved to the update namespace method.
        if self.doc.filedir and self.doc.filedir not in self.syspath:
            # To create the proper context for updateNamespace.
            self.syspath.insert(0, self.doc.filedir)
        if self.doc.filepath and os.path.exists(self.doc.filepath):
            self.confirmed = True
        if self.editor:
            text = self.doc.read()
            self.editor._setBuffer(buffer=self, text=text)

    def overwriteConfirm(self, filepath):
        """Confirm overwriting an existing file."""
        return False

    def save(self):
        """Save buffer."""
        filepath = self.doc.filepath
        if not filepath:
            return  # XXX Get filename
        if not os.path.exists(filepath):
            self.confirmed = True
        if not self.confirmed:
            self.confirmed = self.overwriteConfirm(filepath)
        if self.confirmed:
            self.doc.write(self.editor.getText())
            if self.editor:
                self.editor.setSavePoint()

    def saveAs(self, filename):
        """Save buffer."""
        self.doc = document.Document(filename)
        self.name = self.doc.filename
        self.modulename = self.doc.filebase
        self.save()

    def updateNamespace(self):
        """Update the namespace for autocompletion and calltips.

        Return True if updated, False if there was an error."""
        if not self.interp or not hasattr(self.editor, 'getText'):
            return False
        syspath = sys.path
        sys.path = self.syspath
        text = self.editor.getText()
        text = text.replace('\r\n', '\n')
        text = text.replace('\r', '\n')
        name = self.modulename or self.name
        module = imp.new_module(name)
        newspace = module.__dict__.copy()
        try:
            try:
                code = compile(text, name, 'exec')
            except:
                raise
#                return False
            try:
                exec code in newspace
            except:
                raise
#                return False
            else:
                # No problems, so update the namespace.
                self.interp.locals.clear()
                self.interp.locals.update(newspace)
                return True
        finally:
            sys.path = syspath
            for m in sys.modules.keys():
                if m not in self.modules:
                    del sys.modules[m]