Major restructuring to get a better foundation.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@20227 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -4,12 +4,12 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
import base
|
||||
import buffer
|
||||
import crust
|
||||
import dispatcher
|
||||
import document
|
||||
import editor
|
||||
import editwindow
|
||||
import filling
|
||||
import frame
|
||||
import images
|
||||
|
@@ -1,4 +1,4 @@
|
||||
"""Base editor."""
|
||||
"""EditWindow class."""
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
@@ -42,14 +42,14 @@ else: # GTK
|
||||
}
|
||||
|
||||
|
||||
class Editor(stc.wxStyledTextCtrl):
|
||||
"""Editor based on StyledTextCtrl."""
|
||||
class EditWindow(stc.wxStyledTextCtrl):
|
||||
"""EditWindow based on StyledTextCtrl."""
|
||||
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||
size=wx.wxDefaultSize, style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER):
|
||||
"""Create an Editor instance."""
|
||||
"""Create EditWindow instance."""
|
||||
stc.wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
|
||||
self.__config()
|
||||
stc.EVT_STC_UPDATEUI(self, id, self.OnUpdateUI)
|
||||
|
@@ -6,6 +6,7 @@ __revision__ = "$Revision$"[11:-2]
|
||||
|
||||
from wxPython import wx
|
||||
|
||||
from interpreter import Interpreter
|
||||
import imp
|
||||
import os
|
||||
import sys
|
||||
@@ -24,13 +25,14 @@ class Buffer:
|
||||
|
||||
id = 0
|
||||
|
||||
def __init__(self, editor, interp, filename=None):
|
||||
def __init__(self, filename=None):
|
||||
"""Create a Buffer instance."""
|
||||
Buffer.id += 1
|
||||
self.id = Buffer.id
|
||||
self.interp = Interpreter(locals={})
|
||||
self.name = ''
|
||||
self.editor = editor
|
||||
self.interp = interp
|
||||
self.editors = {}
|
||||
self.editor = None
|
||||
self.modules = sys.modules.keys()
|
||||
self.syspath = sys.path[:]
|
||||
while True:
|
||||
@@ -45,18 +47,17 @@ class Buffer:
|
||||
break
|
||||
self.open(filename)
|
||||
|
||||
def getStatus(self):
|
||||
"""Return (filepath, line, column) status tuple."""
|
||||
editor = self.editor
|
||||
pos = editor.GetCurrentPos()
|
||||
line = editor.LineFromPosition(pos) + 1
|
||||
col = editor.GetColumn(pos)
|
||||
status = (self.doc.filepath or self.name, line, col)
|
||||
return status
|
||||
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."""
|
||||
return self.editor.GetModify()
|
||||
if self.editor:
|
||||
return self.editor.hasChanged()
|
||||
else:
|
||||
return False
|
||||
|
||||
def new(self, filepath):
|
||||
"""New empty buffer."""
|
||||
@@ -72,14 +73,16 @@ class Buffer:
|
||||
self.doc = document.Document(filename)
|
||||
self.name = self.doc.filename or ('Untitled:' + str(self.id))
|
||||
self.modulename = self.doc.filebase
|
||||
if self.doc.filepath and os.path.exists(self.doc.filepath):
|
||||
self.editor.ClearAll()
|
||||
self.editor.SetText(self.doc.read())
|
||||
self.editor.EmptyUndoBuffer()
|
||||
self.editor.SetSavePoint()
|
||||
self.confirmed = True
|
||||
# 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(filepath):
|
||||
"""Confirm overwriting an existing file."""
|
||||
@@ -95,43 +98,36 @@ class Buffer:
|
||||
if not self.confirmed:
|
||||
self.confirmed = self.overwriteConfirm(filepath)
|
||||
if self.confirmed:
|
||||
self.doc.write(self.editor.GetText())
|
||||
self.editor.SetSavePoint()
|
||||
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
|
||||
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())
|
||||
self.editor.SetSavePoint()
|
||||
self.save()
|
||||
|
||||
def updateNamespace(self):
|
||||
"""Update the namespace for autocompletion and calltips.
|
||||
|
||||
Return True if updated, False if there was an error."""
|
||||
backup = self.interp.locals
|
||||
if not self.interp or not hasattr(self.editor, 'getText'):
|
||||
return False
|
||||
syspath = sys.path
|
||||
sys.path = self.syspath
|
||||
code = self.editor.GetText()
|
||||
code = self.editor.getText()
|
||||
module = imp.new_module(str(self.modulename))
|
||||
namespace = module.__dict__.copy()
|
||||
try:
|
||||
try:
|
||||
exec code in namespace
|
||||
except:
|
||||
self.interp.locals = backup
|
||||
return False
|
||||
else:
|
||||
self.interp.locals = namespace
|
||||
self.interp.locals.clear()
|
||||
self.interp.locals.update(namespace)
|
||||
return True
|
||||
finally:
|
||||
sys.path = syspath
|
||||
|
@@ -38,7 +38,7 @@ class Crust(wx.wxSplitterWindow):
|
||||
self.shell = Shell(parent=self, introText=intro,
|
||||
locals=locals, InterpClass=InterpClass,
|
||||
*args, **kwds)
|
||||
self.buffer = self.shell.buffer
|
||||
self.editor = self.shell
|
||||
if rootObject is None:
|
||||
rootObject = self.shell.interp.locals
|
||||
self.notebook = wx.wxNotebook(parent=self, id=-1)
|
||||
|
@@ -30,11 +30,14 @@ class Document:
|
||||
|
||||
def read(self):
|
||||
"""Return contents of file."""
|
||||
f = file(self.filepath, 'rb')
|
||||
try:
|
||||
return f.read()
|
||||
finally:
|
||||
f.close()
|
||||
if self.filepath and os.path.exists(self.filepath):
|
||||
f = file(self.filepath, 'rb')
|
||||
try:
|
||||
return f.read()
|
||||
finally:
|
||||
f.close()
|
||||
else:
|
||||
return ''
|
||||
|
||||
def write(self, text):
|
||||
"""Write text to file."""
|
||||
|
@@ -6,13 +6,12 @@ __revision__ = "$Revision$"[11:-2]
|
||||
|
||||
from wxPython import wx
|
||||
|
||||
import base
|
||||
import buffer
|
||||
from buffer import Buffer
|
||||
import crust
|
||||
import dispatcher
|
||||
import editwindow
|
||||
import frame
|
||||
import interpreter
|
||||
import shell
|
||||
from shell import Shell
|
||||
import version
|
||||
|
||||
try:
|
||||
@@ -28,12 +27,13 @@ class EditorFrame(frame.Frame):
|
||||
def __init__(self, parent=None, id=-1, title='PyAlaCarte',
|
||||
pos=wx.wxDefaultPosition, size=(800, 600),
|
||||
style=wx.wxDEFAULT_FRAME_STYLE, filename=None):
|
||||
"""Create an EditorFrame instance."""
|
||||
"""Create EditorFrame instance."""
|
||||
frame.Frame.__init__(self, parent, id, title, pos, size, style)
|
||||
self._buffers = {}
|
||||
self._buffer = None # Current buffer.
|
||||
self.buffers = {}
|
||||
self.buffer = None # Current buffer.
|
||||
self.editor = None
|
||||
self._statusText = title + ' - the tastiest Python editor.'
|
||||
self._defaultText = title + ' - the tastiest Python editor.'
|
||||
self._statusText = self._defaultText
|
||||
self.SetStatusText(self._statusText)
|
||||
wx.EVT_IDLE(self, self.OnIdle)
|
||||
self._setup()
|
||||
@@ -46,6 +46,11 @@ class EditorFrame(frame.Frame):
|
||||
Useful for subclasses."""
|
||||
pass
|
||||
|
||||
def setEditor(self, editor):
|
||||
self.editor = editor
|
||||
self.buffer = self.editor.buffer
|
||||
self.buffers[self.buffer.id] = self.buffer
|
||||
|
||||
def OnAbout(self, event):
|
||||
"""Display an About window."""
|
||||
title = 'About PyAlaCarte'
|
||||
@@ -57,8 +62,8 @@ class EditorFrame(frame.Frame):
|
||||
|
||||
def OnClose(self, event):
|
||||
"""Event handler for closing."""
|
||||
for buffer in self._buffers.values():
|
||||
self._buffer = buffer
|
||||
for buffer in self.buffers.values():
|
||||
self.buffer = buffer
|
||||
if buffer.hasChanged():
|
||||
cancel = self.bufferSuggestSave()
|
||||
if cancel and event.CanVeto():
|
||||
@@ -74,12 +79,14 @@ class EditorFrame(frame.Frame):
|
||||
|
||||
def _updateStatus(self):
|
||||
"""Show current status information."""
|
||||
if self._buffer:
|
||||
status = self._buffer.getStatus()
|
||||
if self.editor and hasattr(self.editor, 'getStatus'):
|
||||
status = self.editor.getStatus()
|
||||
text = 'File: %s | Line: %d | Column: %d' % status
|
||||
if text != self._statusText:
|
||||
self.SetStatusText(text)
|
||||
self._statusText = text
|
||||
else:
|
||||
text = self._defaultText
|
||||
if text != self._statusText:
|
||||
self.SetStatusText(text)
|
||||
self._statusText = text
|
||||
|
||||
def _updateTitle(self):
|
||||
"""Show current title information."""
|
||||
@@ -95,7 +102,7 @@ class EditorFrame(frame.Frame):
|
||||
|
||||
def hasBuffer(self):
|
||||
"""Return True if there is a current buffer."""
|
||||
if self._buffer:
|
||||
if self.buffer:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -113,25 +120,26 @@ class EditorFrame(frame.Frame):
|
||||
def bufferCreate(self, filename=None):
|
||||
"""Create new buffer."""
|
||||
self.bufferDestroy()
|
||||
interp = interpreter.Interpreter(locals={})
|
||||
self.editor = Editor(interp=interp, parent=self, filename=filename)
|
||||
self._buffer = self.editor.buffer
|
||||
self._buffers[self._buffer.id] = self._buffer
|
||||
self._buffer.editor.SetFocus()
|
||||
buffer = Buffer()
|
||||
editor = Editor(parent=self)
|
||||
buffer.addEditor(editor)
|
||||
buffer.open(filename)
|
||||
self.setEditor(editor)
|
||||
self.editor.setFocus()
|
||||
|
||||
def bufferDestroy(self):
|
||||
"""Destroy the current buffer."""
|
||||
if self._buffer:
|
||||
del self._buffers[self._buffer.id]
|
||||
self._buffer = None
|
||||
if self.editor:
|
||||
self.editor.Destroy()
|
||||
if self.buffer:
|
||||
for editor in self.buffer.editors.values():
|
||||
editor.destroy()
|
||||
self.editor = None
|
||||
del self.buffers[self.buffer.id]
|
||||
self.buffer = None
|
||||
|
||||
def bufferHasChanged(self):
|
||||
"""Return True if buffer has changed since last save."""
|
||||
if self._buffer:
|
||||
return self._buffer.hasChanged()
|
||||
if self.buffer:
|
||||
return self.buffer.hasChanged()
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -152,8 +160,8 @@ class EditorFrame(frame.Frame):
|
||||
if cancel:
|
||||
return cancel
|
||||
filedir = ''
|
||||
if self._buffer and self._buffer.doc.filedir:
|
||||
filedir = self._buffer.doc.filedir
|
||||
if self.buffer and self.buffer.doc.filedir:
|
||||
filedir = self.buffer.doc.filedir
|
||||
result = openSingle(directory=filedir)
|
||||
if result.path:
|
||||
self.bufferCreate(result.path)
|
||||
@@ -170,8 +178,8 @@ class EditorFrame(frame.Frame):
|
||||
|
||||
def bufferSave(self):
|
||||
"""Save buffer to its file."""
|
||||
if self._buffer.doc.filepath:
|
||||
self._buffer.save()
|
||||
if self.buffer.doc.filepath:
|
||||
self.buffer.save()
|
||||
cancel = False
|
||||
else:
|
||||
cancel = self.bufferSaveAs()
|
||||
@@ -179,16 +187,16 @@ class EditorFrame(frame.Frame):
|
||||
|
||||
def bufferSaveAs(self):
|
||||
"""Save buffer to a new filename."""
|
||||
if self.bufferHasChanged() and self._buffer.doc.filepath:
|
||||
if self.bufferHasChanged() and self.buffer.doc.filepath:
|
||||
cancel = self.bufferSuggestSave()
|
||||
if cancel:
|
||||
return cancel
|
||||
filedir = ''
|
||||
if self._buffer and self._buffer.doc.filedir:
|
||||
filedir = self._buffer.doc.filedir
|
||||
if self.buffer and self.buffer.doc.filedir:
|
||||
filedir = self.buffer.doc.filedir
|
||||
result = saveSingle(directory=filedir)
|
||||
if result.path:
|
||||
self._buffer.saveAs(result.path)
|
||||
self.buffer.saveAs(result.path)
|
||||
cancel = False
|
||||
else:
|
||||
cancel = True
|
||||
@@ -199,7 +207,7 @@ class EditorFrame(frame.Frame):
|
||||
result = messageDialog(parent=None,
|
||||
message='%s has changed.\n'
|
||||
'Would you like to save it first'
|
||||
'?' % self._buffer.name,
|
||||
'?' % self.buffer.name,
|
||||
title='Save current file?')
|
||||
if result.positive:
|
||||
cancel = self.bufferSave()
|
||||
@@ -209,7 +217,7 @@ class EditorFrame(frame.Frame):
|
||||
|
||||
def updateNamespace(self):
|
||||
"""Update the buffer namespace for autocompletion and calltips."""
|
||||
if self._buffer.updateNamespace():
|
||||
if self.buffer.updateNamespace():
|
||||
self.SetStatusText('Namespace updated')
|
||||
else:
|
||||
self.SetStatusText('Error executing, unable to update namespace')
|
||||
@@ -221,24 +229,26 @@ class EditorNotebookFrame(EditorFrame):
|
||||
def __init__(self, parent=None, id=-1, title='PyAlaMode',
|
||||
pos=wx.wxDefaultPosition, size=(800, 600),
|
||||
style=wx.wxDEFAULT_FRAME_STYLE, filename=None):
|
||||
"""Create an EditorNotebookFrame instance."""
|
||||
"""Create EditorNotebookFrame instance."""
|
||||
self.notebook = None
|
||||
EditorFrame.__init__(self, parent, id, title, pos,
|
||||
size, style, filename)
|
||||
if self.notebook:
|
||||
dispatcher.connect(receiver=self._editorChange,
|
||||
signal='EditorChange', sender=self.notebook)
|
||||
|
||||
def _setup(self):
|
||||
"""Setup prior to first buffer creation.
|
||||
|
||||
Useful for subclasses."""
|
||||
self._notebook = BufferNotebook(parent=self)
|
||||
dispatcher.connect(receiver=self._bufferChange,
|
||||
signal='BufferChange', sender=self._notebook)
|
||||
Called automatically by base class during init."""
|
||||
self.notebook = EditorNotebook(parent=self)
|
||||
intro = 'PyCrust %s' % version.VERSION
|
||||
import imp
|
||||
module = imp.new_module('__main__')
|
||||
import __builtin__
|
||||
module.__dict__['__builtins__'] = __builtin__
|
||||
namespace = module.__dict__.copy()
|
||||
self.crust = crust.Crust(parent=self._notebook, intro=intro, locals=namespace)
|
||||
self.crust = crust.Crust(parent=self.notebook, intro=intro, locals=namespace)
|
||||
self.shell = self.crust.shell
|
||||
# Override the filling so that status messages go to the status bar.
|
||||
self.crust.filling.tree.setStatusText = self.SetStatusText
|
||||
@@ -246,14 +256,12 @@ class EditorNotebookFrame(EditorFrame):
|
||||
self.shell.setStatusText = self.SetStatusText
|
||||
# Fix a problem with the sash shrinking to nothing.
|
||||
self.crust.filling.SetSashPosition(200)
|
||||
self._notebook.AddPage(page=self.crust, text='PyCrust', select=True)
|
||||
self._buffer = self.crust.buffer
|
||||
self._buffers[self._buffer.id] = self._buffer
|
||||
self._buffer.editor.SetFocus()
|
||||
self.notebook.AddPage(page=self.crust, text='PyCrust', select=True)
|
||||
self.setEditor(self.crust.editor)
|
||||
|
||||
def _bufferChange(self, buffer):
|
||||
"""Buffer change signal receiver."""
|
||||
self._buffer = buffer
|
||||
def _editorChange(self, editor):
|
||||
"""Editor change signal receiver."""
|
||||
self.setEditor(editor)
|
||||
|
||||
def OnAbout(self, event):
|
||||
"""Display an About window."""
|
||||
@@ -278,24 +286,24 @@ class EditorNotebookFrame(EditorFrame):
|
||||
|
||||
def bufferCreate(self, filename=None):
|
||||
"""Create new buffer."""
|
||||
interp = interpreter.Interpreter(locals={})
|
||||
editor = Editor(interp=interp, parent=self._notebook,
|
||||
filename=filename)
|
||||
self._buffer = editor.buffer
|
||||
self._buffers[self._buffer.id] = self._buffer
|
||||
self._notebook.AddPage(page=editor, text=self._buffer.name,
|
||||
select=True)
|
||||
self._buffer.editor.SetFocus()
|
||||
buffer = Buffer()
|
||||
editor = Editor(parent=self.notebook)
|
||||
buffer.addEditor(editor)
|
||||
buffer.open(filename)
|
||||
self.setEditor(editor)
|
||||
self.notebook.AddPage(page=editor.window, text=self.buffer.name,
|
||||
select=True)
|
||||
self.editor.setFocus()
|
||||
|
||||
def bufferDestroy(self):
|
||||
"""Destroy the current buffer."""
|
||||
selection = self._notebook.GetSelection()
|
||||
selection = self.notebook.GetSelection()
|
||||
## print "Destroy Selection:", selection
|
||||
if selection > 0: # Don't destroy the PyCrust tab.
|
||||
if self._buffer:
|
||||
del self._buffers[self._buffer.id]
|
||||
self._buffer = None # Do this before DeletePage().
|
||||
self._notebook.DeletePage(selection)
|
||||
if self.buffer:
|
||||
del self.buffers[self.buffer.id]
|
||||
self.buffer = None # Do this before DeletePage().
|
||||
self.notebook.DeletePage(selection)
|
||||
|
||||
def bufferNew(self):
|
||||
"""Create new buffer."""
|
||||
@@ -306,8 +314,8 @@ class EditorNotebookFrame(EditorFrame):
|
||||
def bufferOpen(self):
|
||||
"""Open file in buffer."""
|
||||
filedir = ''
|
||||
if self._buffer and self._buffer.doc.filedir:
|
||||
filedir = self._buffer.doc.filedir
|
||||
if self.buffer and self.buffer.doc.filedir:
|
||||
filedir = self.buffer.doc.filedir
|
||||
result = openMultiple(directory=filedir)
|
||||
for path in result.paths:
|
||||
self.bufferCreate(path)
|
||||
@@ -315,14 +323,16 @@ class EditorNotebookFrame(EditorFrame):
|
||||
return cancel
|
||||
|
||||
|
||||
class BufferNotebook(wx.wxNotebook):
|
||||
"""A notebook containing a page for each buffer."""
|
||||
class EditorNotebook(wx.wxNotebook):
|
||||
"""A notebook containing a page for each editor."""
|
||||
|
||||
def __init__(self, parent):
|
||||
"""Create a BufferNotebook instance."""
|
||||
"""Create EditorNotebook instance."""
|
||||
wx.wxNotebook.__init__(self, parent, id=-1)
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGING(self, self.GetId(), self.OnPageChanging)
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGING(self, self.GetId(),
|
||||
self.OnPageChanging)
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(),
|
||||
self.OnPageChanged)
|
||||
|
||||
def OnPageChanging(self, event):
|
||||
"""Page changing event handler."""
|
||||
@@ -338,87 +348,70 @@ class BufferNotebook(wx.wxNotebook):
|
||||
## print "Changed from:", old
|
||||
new = event.GetSelection()
|
||||
## print "Changed to new:", new
|
||||
page = self.GetPage(new)
|
||||
buffer = page.buffer
|
||||
buffer.editor.SetFocus()
|
||||
dispatcher.send(signal='BufferChange', sender=self, buffer=buffer)
|
||||
window = self.GetPage(new)
|
||||
dispatcher.send(signal='EditorChange', sender=self,
|
||||
editor=window.editor)
|
||||
window.SetFocus()
|
||||
event.Skip()
|
||||
|
||||
|
||||
class BufferEditorShellNotebookFrame(EditorFrame):
|
||||
"""Frame containing one or more editor notebooks."""
|
||||
class EditorShellNotebookFrame(EditorNotebookFrame):
|
||||
"""Frame containing a notebook containing EditorShellNotebooks."""
|
||||
|
||||
def __init__(self, parent=None, id=-1, title='PyAlaMode',
|
||||
pos=wx.wxDefaultPosition, size=(600, 400),
|
||||
style=wx.wxDEFAULT_FRAME_STYLE,
|
||||
filename=None, singlefile=False):
|
||||
"""Create a BufferEditorShellNotebookFrame instance."""
|
||||
"""Create EditorShellNotebookFrame instance."""
|
||||
self._singlefile = singlefile
|
||||
EditorFrame.__init__(self, parent, id, title, pos,
|
||||
size, style, filename)
|
||||
EditorNotebookFrame.__init__(self, parent, id, title, pos,
|
||||
size, style, filename)
|
||||
|
||||
def _setup(self):
|
||||
"""Setup prior to first buffer creation.
|
||||
|
||||
Useful for subclasses."""
|
||||
Called automatically by base class during init."""
|
||||
if not self._singlefile:
|
||||
self._notebook = BufferNotebook(parent=self)
|
||||
dispatcher.connect(receiver=self._bufferChange,
|
||||
signal='BufferChange', sender=self._notebook)
|
||||
|
||||
def _bufferChange(self, buffer):
|
||||
"""Buffer change signal receiver."""
|
||||
self._buffer = buffer
|
||||
self.notebook = EditorNotebook(parent=self)
|
||||
|
||||
def OnAbout(self, event):
|
||||
"""Display an About window."""
|
||||
title = 'About PyAlaMode'
|
||||
title = 'About PyAlaModePlus'
|
||||
text = 'Another fine, flaky program.'
|
||||
dialog = wx.wxMessageDialog(self, text, title,
|
||||
wx.wxOK | wx.wxICON_INFORMATION)
|
||||
dialog.ShowModal()
|
||||
dialog.Destroy()
|
||||
|
||||
def _updateTitle(self):
|
||||
"""Show current title information."""
|
||||
title = self.GetTitle()
|
||||
if self.bufferHasChanged():
|
||||
if title.startswith('* '):
|
||||
pass
|
||||
else:
|
||||
self.SetTitle('* ' + title)
|
||||
else:
|
||||
if title.startswith('* '):
|
||||
self.SetTitle(title[2:])
|
||||
|
||||
def bufferCreate(self, filename=None):
|
||||
"""Create new buffer."""
|
||||
if self._singlefile:
|
||||
self.bufferDestroy()
|
||||
notebook = self._notebook = EditorShellNotebook(parent=self,
|
||||
filename=filename)
|
||||
else:
|
||||
notebook = EditorShellNotebook(parent=self._notebook,
|
||||
notebook = EditorShellNotebook(parent=self,
|
||||
filename=filename)
|
||||
self._buffer = notebook.buffer
|
||||
self.notebook = notebook
|
||||
else:
|
||||
notebook = EditorShellNotebook(parent=self.notebook,
|
||||
filename=filename)
|
||||
self.setEditor(notebook.editor)
|
||||
if not self._singlefile:
|
||||
self._notebook.AddPage(page=notebook, text=self._buffer.name,
|
||||
select=True)
|
||||
self._buffers[self._buffer.id] = self._buffer
|
||||
self._buffer.editor.SetFocus()
|
||||
self.notebook.AddPage(page=notebook, text=self.buffer.name,
|
||||
select=True)
|
||||
self.editor.setFocus()
|
||||
|
||||
def bufferDestroy(self):
|
||||
"""Destroy the current buffer."""
|
||||
if self._buffer:
|
||||
del self._buffers[self._buffer.id]
|
||||
self._buffer = None # Do this before DeletePage().
|
||||
if self.buffer:
|
||||
self.editor = None
|
||||
del self.buffers[self.buffer.id]
|
||||
self.buffer = None # Do this before DeletePage().
|
||||
if self._singlefile:
|
||||
self._notebook.Destroy()
|
||||
self._notebook = None
|
||||
self.notebook.Destroy()
|
||||
self.notebook = None
|
||||
else:
|
||||
selection = self._notebook.GetSelection()
|
||||
print "Destroy Selection:", selection
|
||||
self._notebook.DeletePage(selection)
|
||||
selection = self.notebook.GetSelection()
|
||||
## print "Destroy Selection:", selection
|
||||
self.notebook.DeletePage(selection)
|
||||
|
||||
def bufferNew(self):
|
||||
"""Create new buffer."""
|
||||
@@ -437,8 +430,8 @@ class BufferEditorShellNotebookFrame(EditorFrame):
|
||||
if cancel:
|
||||
return cancel
|
||||
filedir = ''
|
||||
if self._buffer and self._buffer.doc.filedir:
|
||||
filedir = self._buffer.doc.filedir
|
||||
if self.buffer and self.buffer.doc.filedir:
|
||||
filedir = self.buffer.doc.filedir
|
||||
if self._singlefile:
|
||||
result = openSingle(directory=filedir)
|
||||
if result.path:
|
||||
@@ -451,94 +444,125 @@ class BufferEditorShellNotebookFrame(EditorFrame):
|
||||
return cancel
|
||||
|
||||
|
||||
class BufferEditorShellNotebook(wx.wxNotebook):
|
||||
"""A notebook containing a page for each buffer."""
|
||||
|
||||
def __init__(self, parent):
|
||||
"""Create a BufferEditorShellNotebook instance."""
|
||||
wx.wxNotebook.__init__(self, parent, id=-1)
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
|
||||
|
||||
def OnPageChanged(self, event):
|
||||
"""Page changed event handler."""
|
||||
## old = event.GetOldSelection()
|
||||
## print "Changed from old:", old
|
||||
new = event.GetSelection()
|
||||
## print "Changed to new:", new
|
||||
page = self.GetPage(new)
|
||||
buffer = page.buffer
|
||||
subselection = page.GetSelection()
|
||||
page.focus(subselection)
|
||||
dispatcher.send(signal='BufferChange', sender=self, buffer=buffer)
|
||||
event.Skip()
|
||||
|
||||
|
||||
class EditorShellNotebook(wx.wxNotebook):
|
||||
"""A notebook containing an editor page and a shell page."""
|
||||
|
||||
def __init__(self, parent, filename=None):
|
||||
"""Create an EditorShellNotebook instance."""
|
||||
"""Create EditorShellNotebook instance."""
|
||||
wx.wxNotebook.__init__(self, parent, id=-1)
|
||||
usePanels = True
|
||||
if usePanels:
|
||||
shellparent = shellpanel = wx.wxPanel(self, -1)
|
||||
editorparent = editorpanel = wx.wxPanel(self, -1)
|
||||
shellparent = shellpanel = wx.wxPanel(self, -1)
|
||||
else:
|
||||
shellparent = self
|
||||
editorparent = self
|
||||
self.shell = shell.Shell(parent=shellparent,
|
||||
style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER)
|
||||
self.editor = Editor(interp=self.shell.interp, parent=editorparent,
|
||||
filename=filename)
|
||||
shellparent = self
|
||||
self.buffer = Buffer()
|
||||
self.editor = Editor(parent=editorparent)
|
||||
self.buffer.addEditor(self.editor)
|
||||
self.buffer.open(filename)
|
||||
self.shell = Shell(parent=shellparent, locals=self.buffer.interp.locals,
|
||||
style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER)
|
||||
self.buffer.interp.locals.clear()
|
||||
if usePanels:
|
||||
self.AddPage(page=editorpanel, text='File', select=True)
|
||||
self.AddPage(page=editorpanel, text='Editor', select=True)
|
||||
self.AddPage(page=shellpanel, text='Shell')
|
||||
# Setup sizers
|
||||
editorsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
editorsizer.Add(self.editor.window, 1, wx.wxEXPAND)
|
||||
editorpanel.SetSizer(editorsizer)
|
||||
editorpanel.SetAutoLayout(True)
|
||||
shellsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
shellsizer.Add(self.shell, 1, wx.wxEXPAND)
|
||||
shellpanel.SetSizer(shellsizer)
|
||||
shellpanel.SetAutoLayout(True)
|
||||
editorsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
editorsizer.Add(self.editor, 1, wx.wxEXPAND)
|
||||
editorpanel.SetSizer(editorsizer)
|
||||
editorpanel.SetAutoLayout(True)
|
||||
else:
|
||||
self.AddPage(page=self.editor, text='File', select=True)
|
||||
self.AddPage(page=self.editor.window, text='Editor', select=True)
|
||||
self.AddPage(page=self.shell, text='Shell')
|
||||
self.buffer = self.editor.buffer
|
||||
self.editor.SetFocus()
|
||||
self.editor.setFocus()
|
||||
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
|
||||
|
||||
def OnPageChanged(self, event):
|
||||
"""Page changed event handler."""
|
||||
selection = event.GetSelection()
|
||||
self.focus(selection)
|
||||
if selection == 0:
|
||||
self.editor.setFocus()
|
||||
else:
|
||||
self.shell.SetFocus()
|
||||
event.Skip()
|
||||
|
||||
def focus(self, selection):
|
||||
def SetFocus(self):
|
||||
wx.wxNotebook.SetFocus(self)
|
||||
selection = self.GetSelection()
|
||||
if selection == 0:
|
||||
self.editor.SetFocus()
|
||||
self.editor.setFocus()
|
||||
else:
|
||||
self.shell.SetFocus()
|
||||
|
||||
|
||||
class Editor(base.Editor):
|
||||
"""Editor based on StyledTextCtrl."""
|
||||
class Editor:
|
||||
"""Editor having an EditWindow."""
|
||||
|
||||
def __init__(self, interp, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||
size=wx.wxDefaultSize,
|
||||
style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER,
|
||||
filename=None):
|
||||
"""Create a Editor instance."""
|
||||
base.Editor.__init__(self, parent, id, pos, size, style)
|
||||
self.interp = interp
|
||||
# Find out for which keycodes the interpreter will autocomplete.
|
||||
self.autoCompleteKeys = self.interp.getAutoCompleteKeys()
|
||||
style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER):
|
||||
"""Create Editor instance."""
|
||||
self.window = EditWindow(self, parent, id, pos, size, style)
|
||||
self.id = self.window.GetId()
|
||||
self.buffer = None
|
||||
# Assign handlers for keyboard events.
|
||||
wx.EVT_CHAR(self, self.OnChar)
|
||||
wx.EVT_KEY_DOWN(self, self.OnKeyDown)
|
||||
self.buffer = buffer.Buffer(editor=self, interp=self.interp,
|
||||
filename=filename)
|
||||
wx.EVT_CHAR(self.window, self.OnChar)
|
||||
wx.EVT_KEY_DOWN(self.window, self.OnKeyDown)
|
||||
|
||||
def _setBuffer(self, buffer, text):
|
||||
"""Set the editor to a buffer. Private callback called by buffer."""
|
||||
self.buffer = buffer
|
||||
self.autoCompleteKeys = buffer.interp.getAutoCompleteKeys()
|
||||
self.clearAll()
|
||||
self.setText(text)
|
||||
self.emptyUndoBuffer()
|
||||
self.setSavePoint()
|
||||
|
||||
def destroy(self):
|
||||
"""Destroy all editor objects."""
|
||||
self.window.Destroy()
|
||||
|
||||
def clearAll(self):
|
||||
self.window.ClearAll()
|
||||
|
||||
def emptyUndoBuffer(self):
|
||||
self.window.EmptyUndoBuffer()
|
||||
|
||||
def getStatus(self):
|
||||
"""Return (filepath, line, column) status tuple."""
|
||||
pos = self.window.GetCurrentPos()
|
||||
line = self.window.LineFromPosition(pos) + 1
|
||||
col = self.window.GetColumn(pos)
|
||||
if self.buffer:
|
||||
name = self.buffer.doc.filepath or self.buffer.name
|
||||
else:
|
||||
name = ''
|
||||
status = (name, line, col)
|
||||
return status
|
||||
|
||||
def getText(self):
|
||||
"""Return contents of editor."""
|
||||
return self.window.GetText()
|
||||
|
||||
def hasChanged(self):
|
||||
"""Return True if contents have changed."""
|
||||
return self.window.GetModify()
|
||||
|
||||
def setFocus(self):
|
||||
"""Set the input focus to the editor window."""
|
||||
self.window.SetFocus()
|
||||
|
||||
def setSavePoint(self):
|
||||
self.window.SetSavePoint()
|
||||
|
||||
def setText(self, text):
|
||||
"""Set contents of editor."""
|
||||
self.window.SetText(text)
|
||||
|
||||
def OnChar(self, event):
|
||||
"""Keypress event handler.
|
||||
@@ -549,22 +573,22 @@ class Editor(base.Editor):
|
||||
key = event.KeyCode()
|
||||
if key in self.autoCompleteKeys:
|
||||
# Usually the dot (period) key activates auto completion.
|
||||
if self.AutoCompActive():
|
||||
self.AutoCompCancel()
|
||||
self.ReplaceSelection('')
|
||||
self.AddText(chr(key))
|
||||
text, pos = self.GetCurLine()
|
||||
if self.window.AutoCompActive():
|
||||
self.window.AutoCompCancel()
|
||||
self.window.ReplaceSelection('')
|
||||
self.window.AddText(chr(key))
|
||||
text, pos = self.window.GetCurLine()
|
||||
text = text[:pos]
|
||||
if self.autoComplete:
|
||||
if self.window.autoComplete:
|
||||
self.autoCompleteShow(text)
|
||||
elif key == ord('('):
|
||||
# The left paren activates a call tip and cancels an
|
||||
# active auto completion.
|
||||
if self.AutoCompActive():
|
||||
self.AutoCompCancel()
|
||||
self.ReplaceSelection('')
|
||||
self.AddText('(')
|
||||
text, pos = self.GetCurLine()
|
||||
if self.window.AutoCompActive():
|
||||
self.window.AutoCompCancel()
|
||||
self.window.ReplaceSelection('')
|
||||
self.window.AddText('(')
|
||||
text, pos = self.window.GetCurLine()
|
||||
text = text[:pos]
|
||||
self.autoCallTipShow(text)
|
||||
else:
|
||||
@@ -576,7 +600,7 @@ class Editor(base.Editor):
|
||||
|
||||
key = event.KeyCode()
|
||||
# If the auto-complete window is up let it do its thing.
|
||||
if self.AutoCompActive():
|
||||
if self.window.AutoCompActive():
|
||||
event.Skip()
|
||||
return
|
||||
controlDown = event.ControlDown()
|
||||
@@ -599,46 +623,57 @@ class Editor(base.Editor):
|
||||
|
||||
def autoCompleteShow(self, command):
|
||||
"""Display auto-completion popup list."""
|
||||
list = self.interp.getAutoCompleteList(command,
|
||||
includeMagic=self.autoCompleteIncludeMagic,
|
||||
includeSingle=self.autoCompleteIncludeSingle,
|
||||
includeDouble=self.autoCompleteIncludeDouble)
|
||||
list = self.buffer.interp.getAutoCompleteList(command,
|
||||
includeMagic=self.window.autoCompleteIncludeMagic,
|
||||
includeSingle=self.window.autoCompleteIncludeSingle,
|
||||
includeDouble=self.window.autoCompleteIncludeDouble)
|
||||
if list and len(list) < 2000:
|
||||
options = ' '.join(list)
|
||||
offset = 0
|
||||
self.AutoCompShow(offset, options)
|
||||
self.window.AutoCompShow(offset, options)
|
||||
|
||||
def autoCallTipShow(self, command):
|
||||
"""Display argument spec and docstring in a popup window."""
|
||||
if self.CallTipActive():
|
||||
self.CallTipCancel()
|
||||
(name, argspec, tip) = self.interp.getCallTip(command)
|
||||
if self.window.CallTipActive():
|
||||
self.window.CallTipCancel()
|
||||
(name, argspec, tip) = self.buffer.interp.getCallTip(command)
|
||||
if tip:
|
||||
dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip)
|
||||
if not self.autoCallTip:
|
||||
if not self.window.autoCallTip:
|
||||
return
|
||||
if argspec:
|
||||
startpos = self.GetCurrentPos()
|
||||
self.AddText(argspec + ')')
|
||||
endpos = self.GetCurrentPos()
|
||||
self.SetSelection(endpos, startpos)
|
||||
startpos = self.window.GetCurrentPos()
|
||||
self.window.AddText(argspec + ')')
|
||||
endpos = self.window.GetCurrentPos()
|
||||
self.window.SetSelection(endpos, startpos)
|
||||
if tip:
|
||||
curpos = self.GetCurrentPos()
|
||||
curpos = self.window.GetCurrentPos()
|
||||
size = len(name)
|
||||
tippos = curpos - (size + 1)
|
||||
fallback = curpos - self.GetColumn(curpos)
|
||||
fallback = curpos - self.window.GetColumn(curpos)
|
||||
# In case there isn't enough room, only go back to the
|
||||
# fallback.
|
||||
tippos = max(tippos, fallback)
|
||||
self.CallTipShow(tippos, tip)
|
||||
self.CallTipSetHighlight(0, size)
|
||||
self.window.CallTipShow(tippos, tip)
|
||||
self.window.CallTipSetHighlight(0, size)
|
||||
|
||||
|
||||
class EditWindow(editwindow.EditWindow):
|
||||
"""EditWindow based on StyledTextCtrl."""
|
||||
|
||||
def __init__(self, editor, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||
size=wx.wxDefaultSize,
|
||||
style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER):
|
||||
"""Create EditWindow instance."""
|
||||
editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
|
||||
self.editor = editor
|
||||
|
||||
|
||||
class DialogResults:
|
||||
"""DialogResults class."""
|
||||
|
||||
def __init__(self, returned):
|
||||
"""Create a wrapper for the results returned by a dialog."""
|
||||
"""Create wrapper for results returned by dialog."""
|
||||
self.returned = returned
|
||||
self.positive = returned in (wx.wxID_OK, wx.wxID_YES)
|
||||
self.text = self._asString()
|
||||
|
195
wxPython/wxPython/py/editwindow.py
Normal file
195
wxPython/wxPython/py/editwindow.py
Normal file
@@ -0,0 +1,195 @@
|
||||
"""EditWindow class."""
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
from wxPython import wx
|
||||
from wxPython import stc
|
||||
|
||||
import keyword
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
import dispatcher
|
||||
from version import VERSION
|
||||
|
||||
try:
|
||||
True
|
||||
except NameError:
|
||||
True = 1==1
|
||||
False = 1==0
|
||||
|
||||
if wx.wxPlatform == '__WXMSW__':
|
||||
FACES = { 'times' : 'Times New Roman',
|
||||
'mono' : 'Courier New',
|
||||
'helv' : 'Lucida Console',
|
||||
'lucida' : 'Lucida Console',
|
||||
'other' : 'Comic Sans MS',
|
||||
'size' : 10,
|
||||
'lnsize' : 9,
|
||||
'backcol': '#FFFFFF',
|
||||
}
|
||||
else: # GTK
|
||||
FACES = { 'times' : 'Times',
|
||||
'mono' : 'Courier',
|
||||
'helv' : 'Helvetica',
|
||||
'other' : 'new century schoolbook',
|
||||
'size' : 12,
|
||||
'lnsize' : 10,
|
||||
'backcol': '#FFFFFF',
|
||||
}
|
||||
|
||||
|
||||
class EditWindow(stc.wxStyledTextCtrl):
|
||||
"""EditWindow based on StyledTextCtrl."""
|
||||
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||
size=wx.wxDefaultSize, style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER):
|
||||
"""Create EditWindow instance."""
|
||||
stc.wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
|
||||
self.__config()
|
||||
stc.EVT_STC_UPDATEUI(self, id, self.OnUpdateUI)
|
||||
dispatcher.connect(receiver=self._fontsizer, signal='FontIncrease')
|
||||
dispatcher.connect(receiver=self._fontsizer, signal='FontDecrease')
|
||||
dispatcher.connect(receiver=self._fontsizer, signal='FontDefault')
|
||||
|
||||
def _fontsizer(self, signal):
|
||||
"""Receiver for Font* signals."""
|
||||
size = self.GetZoom()
|
||||
if signal == 'FontIncrease':
|
||||
size += 1
|
||||
elif signal == 'FontDecrease':
|
||||
size -= 1
|
||||
elif signal == 'FontDefault':
|
||||
size = 0
|
||||
self.SetZoom(size)
|
||||
|
||||
def __config(self):
|
||||
"""Configure shell based on user preferences."""
|
||||
self.SetMarginType(1, stc.wxSTC_MARGIN_NUMBER)
|
||||
self.SetMarginWidth(1, 40)
|
||||
|
||||
self.SetLexer(stc.wxSTC_LEX_PYTHON)
|
||||
self.SetKeyWords(0, ' '.join(keyword.kwlist))
|
||||
|
||||
self.setStyles(FACES)
|
||||
self.SetViewWhiteSpace(False)
|
||||
self.SetTabWidth(4)
|
||||
self.SetUseTabs(False)
|
||||
# Do we want to automatically pop up command completion options?
|
||||
self.autoComplete = True
|
||||
self.autoCompleteIncludeMagic = True
|
||||
self.autoCompleteIncludeSingle = True
|
||||
self.autoCompleteIncludeDouble = True
|
||||
self.autoCompleteCaseInsensitive = True
|
||||
self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
|
||||
self.AutoCompSetAutoHide(False)
|
||||
self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`')
|
||||
# Do we want to automatically pop up command argument help?
|
||||
self.autoCallTip = True
|
||||
self.CallTipSetBackground(wx.wxColour(255, 255, 232))
|
||||
self.SetWrapMode(False)
|
||||
try:
|
||||
self.SetEndAtLastLine(False)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def setStyles(self, faces):
|
||||
"""Configure font size, typeface and color for lexer."""
|
||||
|
||||
# Default style
|
||||
self.StyleSetSpec(stc.wxSTC_STYLE_DEFAULT,
|
||||
"face:%(mono)s,size:%(size)d,back:%(backcol)s" % \
|
||||
faces)
|
||||
|
||||
self.StyleClearAll()
|
||||
|
||||
# Built in styles
|
||||
self.StyleSetSpec(stc.wxSTC_STYLE_LINENUMBER,
|
||||
"back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
|
||||
self.StyleSetSpec(stc.wxSTC_STYLE_CONTROLCHAR,
|
||||
"face:%(mono)s" % faces)
|
||||
self.StyleSetSpec(stc.wxSTC_STYLE_BRACELIGHT,
|
||||
"fore:#0000FF,back:#FFFF88")
|
||||
self.StyleSetSpec(stc.wxSTC_STYLE_BRACEBAD,
|
||||
"fore:#FF0000,back:#FFFF88")
|
||||
|
||||
# Python styles
|
||||
self.StyleSetSpec(stc.wxSTC_P_DEFAULT,
|
||||
"face:%(mono)s" % faces)
|
||||
self.StyleSetSpec(stc.wxSTC_P_COMMENTLINE,
|
||||
"fore:#007F00,face:%(mono)s" % faces)
|
||||
self.StyleSetSpec(stc.wxSTC_P_NUMBER,
|
||||
"")
|
||||
self.StyleSetSpec(stc.wxSTC_P_STRING,
|
||||
"fore:#7F007F,face:%(mono)s" % faces)
|
||||
self.StyleSetSpec(stc.wxSTC_P_CHARACTER,
|
||||
"fore:#7F007F,face:%(mono)s" % faces)
|
||||
self.StyleSetSpec(stc.wxSTC_P_WORD,
|
||||
"fore:#00007F,bold")
|
||||
self.StyleSetSpec(stc.wxSTC_P_TRIPLE,
|
||||
"fore:#7F0000")
|
||||
self.StyleSetSpec(stc.wxSTC_P_TRIPLEDOUBLE,
|
||||
"fore:#000033,back:#FFFFE8")
|
||||
self.StyleSetSpec(stc.wxSTC_P_CLASSNAME,
|
||||
"fore:#0000FF,bold")
|
||||
self.StyleSetSpec(stc.wxSTC_P_DEFNAME,
|
||||
"fore:#007F7F,bold")
|
||||
self.StyleSetSpec(stc.wxSTC_P_OPERATOR,
|
||||
"")
|
||||
self.StyleSetSpec(stc.wxSTC_P_IDENTIFIER,
|
||||
"")
|
||||
self.StyleSetSpec(stc.wxSTC_P_COMMENTBLOCK,
|
||||
"fore:#7F7F7F")
|
||||
self.StyleSetSpec(stc.wxSTC_P_STRINGEOL,
|
||||
"fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
|
||||
|
||||
def OnUpdateUI(self, event):
|
||||
"""Check for matching braces."""
|
||||
# If the auto-complete window is up let it do its thing.
|
||||
if self.AutoCompActive() or self.CallTipActive():
|
||||
return
|
||||
braceAtCaret = -1
|
||||
braceOpposite = -1
|
||||
charBefore = None
|
||||
caretPos = self.GetCurrentPos()
|
||||
if caretPos > 0:
|
||||
charBefore = self.GetCharAt(caretPos - 1)
|
||||
styleBefore = self.GetStyleAt(caretPos - 1)
|
||||
|
||||
# Check before.
|
||||
if charBefore and chr(charBefore) in '[]{}()' \
|
||||
and styleBefore == stc.wxSTC_P_OPERATOR:
|
||||
braceAtCaret = caretPos - 1
|
||||
|
||||
# Check after.
|
||||
if braceAtCaret < 0:
|
||||
charAfter = self.GetCharAt(caretPos)
|
||||
styleAfter = self.GetStyleAt(caretPos)
|
||||
if charAfter and chr(charAfter) in '[]{}()' \
|
||||
and styleAfter == stc.wxSTC_P_OPERATOR:
|
||||
braceAtCaret = caretPos
|
||||
|
||||
if braceAtCaret >= 0:
|
||||
braceOpposite = self.BraceMatch(braceAtCaret)
|
||||
|
||||
if braceAtCaret != -1 and braceOpposite == -1:
|
||||
self.BraceBadLight(braceAtCaret)
|
||||
else:
|
||||
self.BraceHighlight(braceAtCaret, braceOpposite)
|
||||
|
||||
def CanCut(self):
|
||||
"""Return true if text is selected and can be cut."""
|
||||
return self.CanCopy()
|
||||
|
||||
def CanCopy(self):
|
||||
"""Return true if text is selected and can be copied."""
|
||||
return self.GetSelectionStart() != self.GetSelectionEnd()
|
||||
|
||||
def CanEdit(self):
|
||||
"""Return true if editing should succeed."""
|
||||
return True
|
@@ -7,8 +7,8 @@ __revision__ = "$Revision$"[11:-2]
|
||||
|
||||
from wxPython import wx
|
||||
|
||||
import base
|
||||
import dispatcher
|
||||
import editwindow
|
||||
import inspect
|
||||
import introspect
|
||||
import keyword
|
||||
@@ -245,7 +245,7 @@ class FillingTree(wx.wxTreeCtrl):
|
||||
print text
|
||||
|
||||
|
||||
class FillingText(base.Editor):
|
||||
class FillingText(editwindow.EditWindow):
|
||||
"""FillingText based on StyledTextCtrl."""
|
||||
|
||||
name = 'PyFilling Text'
|
||||
@@ -255,7 +255,7 @@ class FillingText(base.Editor):
|
||||
size=wx.wxDefaultSize, style=wx.wxCLIP_CHILDREN,
|
||||
static=False):
|
||||
"""Create a FillingText instance."""
|
||||
base.Editor.__init__(self, parent, id, pos, size, style)
|
||||
editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
|
||||
# Configure various defaults and user preferences.
|
||||
self.SetReadOnly(True)
|
||||
self.SetWrapMode(True)
|
||||
@@ -269,7 +269,7 @@ class FillingText(base.Editor):
|
||||
|
||||
def SetText(self, *args, **kwds):
|
||||
self.SetReadOnly(False)
|
||||
base.Editor.SetText(self, *args, **kwds)
|
||||
editwindow.EditWindow.SetText(self, *args, **kwds)
|
||||
self.SetReadOnly(True)
|
||||
|
||||
|
||||
|
@@ -18,9 +18,9 @@ import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
import base
|
||||
import buffer
|
||||
from buffer import Buffer
|
||||
import dispatcher
|
||||
import editwindow
|
||||
import frame
|
||||
from pseudo import PseudoFileIn
|
||||
from pseudo import PseudoFileOut
|
||||
@@ -71,6 +71,23 @@ class ShellFrame(frame.Frame):
|
||||
self.shell.destroy()
|
||||
self.Destroy()
|
||||
|
||||
def OnAbout(self, event):
|
||||
"""Display an About window."""
|
||||
title = 'About PyShell'
|
||||
text = 'PyShell %s\n\n' % VERSION + \
|
||||
'Yet another Python shell, only flakier.\n\n' + \
|
||||
'Half-baked by Patrick K. O\'Brien,\n' + \
|
||||
'the other half is still in the oven.\n\n' + \
|
||||
'Shell Revision: %s\n' % self.shell.revision + \
|
||||
'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
|
||||
'Python Version: %s\n' % sys.version.split()[0] + \
|
||||
'wxPython Version: %s\n' % wx.__version__ + \
|
||||
'Platform: %s\n' % sys.platform
|
||||
dialog = wx.wxMessageDialog(self, text, title,
|
||||
wx.wxOK | wx.wxICON_INFORMATION)
|
||||
dialog.ShowModal()
|
||||
dialog.Destroy()
|
||||
|
||||
|
||||
class ShellFacade:
|
||||
"""Simplified interface to all shell-related functionality.
|
||||
@@ -156,7 +173,7 @@ Ctrl+= Default font size.
|
||||
return list
|
||||
|
||||
|
||||
class Shell(base.Editor):
|
||||
class Shell(editwindow.EditWindow):
|
||||
"""PyCrust Shell based on StyledTextCtrl."""
|
||||
|
||||
name = 'PyCrust Shell'
|
||||
@@ -166,7 +183,7 @@ class Shell(base.Editor):
|
||||
size=wx.wxDefaultSize, style=wx.wxCLIP_CHILDREN,
|
||||
introText='', locals=None, InterpClass=None, *args, **kwds):
|
||||
"""Create a PyCrust Shell instance."""
|
||||
base.Editor.__init__(self, parent, id, pos, size, style)
|
||||
editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
|
||||
self.wrap()
|
||||
if locals is None:
|
||||
locals = {}
|
||||
@@ -193,8 +210,7 @@ class Shell(base.Editor):
|
||||
stderr=PseudoFileErr(self.writeErr),
|
||||
*args, **kwds)
|
||||
# Set up the buffer.
|
||||
self.buffer = buffer.Buffer(editor=self, interp=self.interp,
|
||||
filename=None)
|
||||
self.buffer = Buffer()
|
||||
# Find out for which keycodes the interpreter will autocomplete.
|
||||
self.autoCompleteKeys = self.interp.getAutoCompleteKeys()
|
||||
# Keep track of the last non-continuation prompt positions.
|
||||
@@ -231,6 +247,10 @@ class Shell(base.Editor):
|
||||
def destroy(self):
|
||||
del self.interp
|
||||
|
||||
def setFocus(self):
|
||||
"""Set focus to the shell."""
|
||||
self.SetFocus()
|
||||
|
||||
def OnIdle(self, event):
|
||||
"""Free the CPU to do other things."""
|
||||
if self.waiting:
|
||||
@@ -878,7 +898,7 @@ Platform: %s""" % \
|
||||
|
||||
def CanPaste(self):
|
||||
"""Return true if a paste should succeed."""
|
||||
if self.CanEdit() and base.Editor.CanPaste(self):
|
||||
if self.CanEdit() and editwindow.EditWindow.CanPaste(self):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
Reference in New Issue
Block a user