Updated PyCrust contrib from Patrick O'Brian.

Added an enhanced wxEditor from Steve Howell and Adam Feuer.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@12782 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2001-12-01 02:25:39 +00:00
parent 39cc7a0bae
commit 1918b6f789
25 changed files with 1536 additions and 868 deletions

View File

@@ -95,6 +95,8 @@ same document.
Added wxEditableListBox gizmo. Added wxEditableListBox gizmo.
Added a greatly enhanced wxEditor from Steve Howell and Adam Feuer.

View File

@@ -50,6 +50,7 @@ include samples/StyleEditor/*.txt
include samples/StyleEditor/*.cfg include samples/StyleEditor/*.cfg
include samples/pySketch/*.py include samples/pySketch/*.py
include samples/pySketch/images/*.bmp include samples/pySketch/images/*.bmp
include samples/frogedit/*.py
include wxPython/lib/*.py include wxPython/lib/*.py

View File

@@ -1,42 +1,63 @@
from wxPython.wx import * from wxPython.wx import *
from wxPython.lib.editor import wxEditor, wxPyEditor from wxPython.lib.editor import wxEditor
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def runTest(frame, nb, log): def runTest(frame, nb, log):
win = wxPanel(nb, -1) win = wxPanel(nb, -1)
ed = wxEditor(win, -1, style=wxSUNKEN_BORDER) ed = wxEditor(win, -1, style=wxSUNKEN_BORDER)
pyed = wxPyEditor(win, -1, style=wxSUNKEN_BORDER)
box = wxBoxSizer(wxVERTICAL) box = wxBoxSizer(wxVERTICAL)
box.Add(ed, 1, wxALL|wxGROW, 5) box.Add(ed, 1, wxALL|wxGROW, 5)
box.Add(pyed, 1, wxALL|wxGROW, 5)
win.SetSizer(box) win.SetSizer(box)
win.SetAutoLayout(true) win.SetAutoLayout(true)
ed.SetText(["", ed.SetText(["",
"This is a simple text editor, the class name is", "This is a simple text editor, the class name is",
"wxEditor. Type a few lines and try it out.", "wxEditor. Type a few lines and try it out.",
"",
"It uses Windows-style key commands that can be overriden by subclassing.",
"Mouse select works. Here are the key commands:",
"",
"Cursor movement: Arrow keys or mouse",
"Beginning of line: Home",
"End of line: End",
"Beginning of buffer: Control-Home",
"End of the buffer: Control-End",
"Select text: Hold down Shift while moving the cursor",
"Copy: Control-Insert, Control-C",
"Cut: Shift-Delete, Control-X",
"Paste: Shift-Insert, Control-V",
""]) ""])
pyed.SetText(["# This one is a derived class named wxPyEditor.",
"# It adds syntax highlighting, folding (press",
"# F12 on the \"def\" line below) and other stuff.",
"import sys",
"def hello():",
" print 'hello'",
" for x in sys.path:",
" print x",
""])
return win return win
#---------------------------------------------------------------------- #----------------------------------------------------------------------
overview = """
The wxEditor class implements a simple text editor using wxPython. You
can create a custom editor by subclassing wxEditor. Even though much of
the editor is implemented in Python, it runs surprisingly smoothly on
normal hardware with small files.
How to use it
-------------
The demo code (demo/wxEditor.py) shows how to use wxEditor as a simple text
box. Use the SetText() and GetText() methods to set or get text from
the component; these both use a list of strings.
The samples/FrogEdit directory has an example of a simple text editor
application that uses the wxEditor component.
Subclassing
-----------
To add or change functionality, you can subclass this
component. One example of this might be to change the key
Alt key commands. In that case you would (for example) override the
SetAltFuncs() method.
overview = """\
""" """

View File

@@ -151,6 +151,7 @@ Source: "samples\StyleEditor\*.cfg"; DestDir: "{app}\wxPython\samples\
Source: "samples\pySketch\*.py"; DestDir: "{app}\wxPython\samples\pySketch"; Components: samples Source: "samples\pySketch\*.py"; DestDir: "{app}\wxPython\samples\pySketch"; Components: samples
Source: "samples\pySketch\images\*.bmp"; DestDir: "{app}\wxPython\samples\pySketch\images"; Components: samples Source: "samples\pySketch\images\*.bmp"; DestDir: "{app}\wxPython\samples\pySketch\images"; Components: samples
Source: "samples\frogedit\*.py"; DestDir: "{app}\wxPython\samples\frogedit"; Components: samples
;;------------------------------------------------------------ ;;------------------------------------------------------------
@@ -192,6 +193,8 @@ Type: files; Name: "{app}\wxPython\samples\stxview\*.pyc";
Type: files; Name: "{app}\wxPython\samples\stxview\*.pyo"; Type: files; Name: "{app}\wxPython\samples\stxview\*.pyo";
Type: files; Name: "{app}\wxPython\samples\stxview\StructuredText\*.pyc"; Type: files; Name: "{app}\wxPython\samples\stxview\StructuredText\*.pyc";
Type: files; Name: "{app}\wxPython\samples\stxview\StructuredText\*.pyo"; Type: files; Name: "{app}\wxPython\samples\stxview\StructuredText\*.pyo";
Type: files; Name: "{app}\wxPython\samples\frogedit\*.pyc";
Type: files; Name: "{app}\wxPython\samples\frogedit\*.pyo";
''' '''

View File

@@ -0,0 +1,366 @@
#!/usr/local/bin/python
# simple text editor
#
# Copyright 2001 Adam Feuer and Steve Howell
#
# License: Python
import os, string, re
import sys
from wxPython.wx import *
from StatusBar import *
from FrogEditor import FrogEditor
TRUE = 1
FALSE = 0
ABOUT_TEXT = """FrogEdit : Copyright 2001 Adam Feuer and Steve Howell
wxEditor component : Copyright 1999 - 2001 Dirk Holtwic, Robin Dunn, Adam Feuer, Steve Howell
FrogEdit was built using Python, wxPython, and wxWindows."""
##---------------------------------------------------------------------
def chomp(line):
line = string.split(line,'\n')[0]
return string.split(line,'\r')[0]
##---------------------------------------------------------------------
class OutlinerPanel(wxPanel):
def Close(self, event):
self.parent.Close()
wxPanel.Close(self)
##----------------------------------------------------------------------
class FrogEditFrame(wxFrame):
def __init__(self, parent, ID, title, pos=wxDefaultPosition,
size=wxDefaultSize, style=wxDEFAULT_FRAME_STYLE):
wxFrame.__init__(self, parent, ID, title, pos, size, style)
splitter = wxSplitterWindow(self, -1, style=wxNO_3D|wxSP_3D)
win = OutlinerPanel(splitter, -1, style=wxCLIP_CHILDREN)
win.parent = self
log = self.MakeLogWindow(splitter)
self.MakeStatusbar()
self.MakeEditorWindow(win, log)
self.SetUpSplitter(splitter, win, log)
self.MakeMenus()
self.MakeMainWindow(win)
self.RegisterEventHandlers()
self.InitVariables()
##------------- Init Misc
def RegisterEventHandlers(self):
EVT_CLOSE(self,self.OnCloseWindow)
def InitVariables(self):
self.fileName = None
self.edl.UnTouchBuffer()
def MakeMenus(self):
self.MainMenu = wxMenuBar()
self.AddMenus(self.MainMenu)
self.SetMenuBar(self.MainMenu)
##------------- Init Subwindows
def MakeEditorWindow(self, win, log):
self.edl = FrogEditor(win, -1, style=wxSUNKEN_BORDER, statusBar = self.sb)
self.edl.SetControlFuncs = self.SetControlFuncs
self.edl.SetAltFuncs = self.SetAltFuncs
self.edl.SetStatus(log)
def MakeStatusbar(self):
self.sb = CustomStatusBar(self)
self.SetStatusBar(self.sb)
def MakeLogWindow(self, container):
log = wxTextCtrl(container, -1,
style = wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL)
wxLog_SetActiveTarget(wxLogTextCtrl(log))
wxLogMessage('window handle: %s' % self.GetHandle())
return log
def SetUpSplitter(self, splitter, win, log):
splitter.SplitHorizontally(win, log)
splitter.SetSashPosition(360, true)
splitter.SetMinimumPaneSize(40)
def MakeToolbar(self, win):
toolbarBox = wxBoxSizer(wxHORIZONTAL)
self.AddButtons(win, toolbarBox)
return toolbarBox
def MakeMainWindow(self, win):
mainBox = wxBoxSizer(wxVERTICAL)
mainBox.Add(self.MakeToolbar(win))
borderWidth = 5
mainBox.Add(self.edl, 1, wxALL|wxGROW, borderWidth)
win.SetSizer(mainBox)
win.SetAutoLayout(true)
##-------------- Init Menus
# override this to add more menus
def AddMenus(self, menu):
self.AddFileMenu(menu)
self.AddEditMenu(menu)
self.AddHelpMenu(menu)
def AddMenuItem(self, menu, itemText, itemDescription, itemHandler):
menuId = wxNewId()
menu.Append(menuId, itemText, itemDescription)
EVT_MENU(self, menuId, itemHandler)
return menuId
def AddFileMenu(self, menu):
fileMenu = wxMenu()
self.AddMenuItem(fileMenu, '&New File\tCtrl-N', 'New File', self.OnNewFile)
self.AddMenuItem(fileMenu, '&Open File\tCtrl-O', 'Open File', self.OnOpenFile)
self.AddMenuItem(fileMenu, '&Save File\tCtrl-S', 'Save File', self.OnSaveFile)
self.AddMenuItem(fileMenu, 'Save File &As\tCtrl-A', 'Save File As',self.OnSaveFileAs)
self.AddMenuItem(fileMenu, 'E&xit\tAlt-X', 'Exit', self.OnFileExit)
menu.Append(fileMenu, 'File')
def AddEditMenu(self, menu):
editMenu = wxMenu()
self.AddMenuItem(editMenu, 'Cut\tCtrl-X', 'Cut', self.edl.OnCutSelection)
self.AddMenuItem(editMenu, '&Copy\tCtrl-C', 'Copy', self.edl.OnCopySelection)
self.AddMenuItem(editMenu, 'Paste\tCtrl-V', 'Paste', self.edl.OnPaste)
self.AddMenuItem(editMenu, 'Edit preferences', 'Edit Preferences', self.OnEditPreferences)
menu.Append(editMenu, 'Edit')
def AddHelpMenu(self, menu):
helpMenu = wxMenu()
self.AddMenuItem(helpMenu, 'About', 'About the program', self.OnHelpAbout)
menu.Append(helpMenu, 'Help')
##---------------- Init Buttons
def NewButton(self, window, container, name, pos, size, handler):
buttonId = wxNewId()
if pos == None or size == None:
container.Add(wxButton(window, buttonId, name), 0, 0)
else:
container.Add(wxButton(window, buttonId, name, pos, size), 0, 0)
EVT_BUTTON(self, buttonId, handler)
return buttonId
# override this to make more buttons
def AddButtons(self, window, container):
buttonPos = None
buttonSize = None
self.NewButton(window, container, "New", buttonPos, buttonSize, self.OnNewFile)
self.NewButton(window, container, "Open", buttonPos, buttonSize, self.OnOpenFile)
self.NewButton(window, container, "Save", buttonPos, buttonSize, self.OnSaveFile)
##-------------- Init Dialogs
def MessageDialog(self, text, title):
messageDialog = wxMessageDialog(self, text, title, wxOK | wxICON_INFORMATION)
messageDialog.ShowModal()
messageDialog.Destroy()
def OkCancelDialog(self, text, title):
dialog = wxMessageDialog(self, text, title, wxOK | wxCANCEL | wxICON_INFORMATION)
result = dialog.ShowModal()
dialog.Destroy()
if result == wxID_OK:
return TRUE
else:
return FALSE
def SelectFileDialog(self, defaultDir=None, defaultFile=None, wildCard=None):
if defaultDir == None:
defaultDir = "."
if defaultFile == None:
defaultFile = ""
if wildCard == None:
wildCard = "*.*"
fileName = None
fileDialog = wxFileDialog(self, "Choose a file", defaultDir, defaultFile, wildCard, wxOPEN|wxMULTIPLE)
result = fileDialog.ShowModal()
if result == wxID_OK:
fileName = fileDialog.GetPath()
wxLogMessage('You selected: %s\n' % fileName)
fileDialog.Destroy()
return fileName
def OpenFileError(self, fileName):
wxLogMessage('Open file error.')
self.MessageDialog("Error opening file '%s'!" % fileName, "Error")
def SaveFileError(self, fileName):
wxLogMessage('Save file error.')
self.MessageDialog("Error saving file '%s'!" % fileName, "Error")
##---------------- Utility functions
def SetControlFuncs(self, action):
"for overriding editor's keys"
FrogEditor.SetControlFuncs(self.edl, action)
action['a'] = self.OnSaveFileAs
action['o'] = self.OnOpenFile
action['n'] = self.OnNewFile
action['s'] = self.OnSaveFile
def SetAltFuncs(self, action):
FrogEditor.SetAltFuncs(self.edl, action)
action['x'] = self.OnFileExit
def GetCurrentDir(self):
if self.fileName is not None:
return os.path.split(self.fileName)[0]
return "."
def GetFileName(self):
if self.fileName is not None:
return os.path.split(self.fileName)[1]
return ""
def NewFile(self):
self.edl.SetText([""])
self.fileName = None
self.sb.setFileName("")
def SaveFile(self, fileName):
try:
contents = string.join(self.edl.GetText(), '\n')
f = open(fileName, 'w')
f.write(contents)
f.close()
self.edl.UnTouchBuffer()
self.sb.setFileName(fileName)
return TRUE
except:
return FALSE
def OpenFile(self, fileName):
try:
f = open(fileName, 'r')
contents = f.readlines()
f.close()
contents = [chomp(line) for line in contents]
if len(contents) == 0:
contents = [""]
self.edl.SetText(contents)
self.fileName = fileName
self.sb.setFileName(fileName)
return TRUE
except:
return FALSE
##---------------- Event handlers
def OnCloseWindow(self, event):
self.edl.OnCloseWindow(event)
self.Destroy()
def OnNewFile(self, event):
if self.edl.BufferWasTouched():
if not self.OkCancelDialog("New file - abandon changes?", "New File"):
return
self.NewFile()
self.edl.SetFocus()
def OnOpenFile(self, event):
if self.edl.BufferWasTouched():
if not self.OkCancelDialog("Open file - abandon changes?", "Open File"):
return
fileName = self.SelectFileDialog(self.GetCurrentDir())
if fileName is not None:
if self.OpenFile(fileName) is FALSE:
self.OpenFileError(fileName)
self.edl.SetFocus()
def OnSaveFile(self, event):
if self.fileName is None:
return self.OnSaveFileAs(event)
wxLogMessage("Saving %s..." % self.fileName)
if self.SaveFile(self.fileName) is not TRUE:
self.SaveFileError(self.fileName)
self.edl.SetFocus()
def OnSaveFileAs(self, event):
fileName = self.SelectFileDialog(self.GetCurrentDir(),self.GetFileName())
if fileName is not None:
self.fileName = fileName
wxLogMessage("Saving %s..." % self.fileName)
if self.SaveFile(self.fileName) is not TRUE:
self.SaveFileError(self.fileName)
self.edl.SetFocus()
def OnFileExit(self, event):
if self.edl.BufferWasTouched():
if not self.OkCancelDialog("Exit program - abandon changes?", "Exit"):
return
self.OnCloseWindow(event)
def OnEditPreferences(self, event):
self.MessageDialog("Edit preferences is not implemented yet.", "Not implemented.")
pass
def OnHelpAbout(self, event):
self.MessageDialog(ABOUT_TEXT, "About FrogEdit")
pass
def Show(self, show):
wxFrame.Show(self, show)
self.edl.SetFocus()
##------------- Startup stuff
def LoadInitialFile(self, fileName):
if fileName is not None:
if self.OpenFile(fileName) is FALSE:
self.OpenFileError(fileName)
##-------------- Application Launcher utility class
class FrogEditLauncher:
def MakeAppFrame(self):
return FrogEditFrame(None, -1, "FrogEdit", size=(640, 480),
style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
def GetArgvFilename(self):
if len(sys.argv) > 1:
return sys.argv[1]
else:
return None
def Main(self):
win = self.MakeAppFrame()
app = wxPySimpleApp()
win.Show(true)
win.LoadInitialFile(self.GetArgvFilename())
app.MainLoop()
##-------------- Main program
if __name__ == '__main__':
launcher = FrogEditLauncher()
launcher.Main()

View File

@@ -0,0 +1,92 @@
#!/usr/local/bin/python
# simple text editor
#
# Copyright 2001 Adam Feuer and Steve Howell
#
# License: Python
import re
from wxPython.wx import *
from wxPython.lib.editor import wxEditor
#---------------------------------------------------------------------
class FrogEditor(wxEditor):
def __init__(self, parent, id,
pos=wxDefaultPosition, size=wxDefaultSize, style=0, statusBar=None):
self.StatusBar = statusBar
wxEditor.__init__(self, parent, id, pos, size, style)
self.parent = parent
##------------------------------------
def TouchBuffer(self):
wxEditor.TouchBuffer(self)
self.StatusBar.setDirty(1)
def UnTouchBuffer(self):
wxEditor.UnTouchBuffer(self)
self.StatusBar.setDirty(0)
#--------- utility function -------------
# override our base class method
def DrawCursor(self, dc = None):
wxEditor.DrawCursor(self,dc)
self.StatusBar.setRowCol(self.cy,self.cx)
def lastLine(self):
lastline = self.sy + self.sh - 1
return min(lastline, self.LinesInFile() - 1)
def rawLines(self):
return [l.text for l in self.text]
def save(self):
if self.page:
self.ds.store(self.page,self.rawLines())
def SetRawText(self, rawtext=""):
self.rawText= rawtext
self.SetText(self.RenderText())
def RenderText(self):
return(self.rawText)
#---------- logging -------------
def SetStatus(self, log):
self.log = log
self.status = []
def PrintSeparator(self, event):
self.Print("..........................")
def Print(self, data):
self.status.append(data)
if data[-1:] == '\n':
data = data[:-1]
wxLogMessage(data)
#--------- wxEditor keyboard overrides
def SetControlFuncs(self, action):
wxEditor.SetControlFuncs(self, action)
action['-'] = self.PrintSeparator
def SetAltFuncs(self, action):
wxEditor.SetAltFuncs(self, action)
action['x'] = self.Exit
#----------- commands -----------
def OnCloseWindow(self, event):
# xxx - We don't fully understand how exit logic works.
# This event is actually called by our parent frame.
pass
def Exit(self,event):
self.parent.Close(None)

View File

@@ -0,0 +1,22 @@
from wxPython.wx import *
import os.path
class CustomStatusBar(wxStatusBar):
def __init__(self, parent):
wxStatusBar.__init__(self, parent, -1)
self.SetFieldsCount(3)
def setFileName(self, fn):
path, fileName = os.path.split(fn)
self.SetStatusText(fileName, 0)
def setRowCol(self, row, col):
self.SetStatusText("%d,%d" % (row,col), 1)
def setDirty(self, dirty):
if dirty:
self.SetStatusText("...", 2)
else:
self.SetStatusText(" ", 2)

View File

@@ -1,13 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
"""PyCrust is a python shell and namespace browser application.""" """PyCrustApp is a python shell and namespace browser application."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
from wxPython.wx import * from wxPython.wx import *
from crust import CrustFrame from PyCrust.crust import CrustFrame
class App(wxApp): class App(wxApp):
@@ -17,8 +16,6 @@ class App(wxApp):
locals = {'__app__': 'PyCrust Standalone Application'} locals = {'__app__': 'PyCrust Standalone Application'}
self.crustFrame = CrustFrame(locals=locals) self.crustFrame = CrustFrame(locals=locals)
self.crustFrame.Show(true) self.crustFrame.Show(true)
# Set focus to the shell editor.
#self.crustFrame.crust.shell.SetFocus()
self.SetTopWindow(self.crustFrame) self.SetTopWindow(self.crustFrame)
# Add the application object to the sys module's namespace. # Add the application object to the sys module's namespace.
# This allows a shell user to do: # This allows a shell user to do:
@@ -36,3 +33,4 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -1,22 +1,21 @@
#!/usr/bin/env python #!/usr/bin/env python
"""PyFilling is a python namespace inspection application.""" """PyFillingApp is a python namespace inspection application."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "August 21, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
# We use this object to get more introspection when run standalone. # We use this object to get more introspection when run standalone.
application = None application = None
import filling from PyCrust import filling
# These are imported just to have something interesting to inspect. # These are imported just to have something interesting to inspect.
import crust from PyCrust import crust
import interpreter from PyCrust import interpreter
import introspect from PyCrust import introspect
import pseudo from PyCrust import pseudo
import shell from PyCrust import shell
import sys import sys
from wxPython import wx from wxPython import wx
@@ -33,3 +32,4 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -1,13 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
"""PyShell is a python shell application.""" """PyShellApp is a python shell application."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
from wxPython.wx import * from wxPython.wx import *
from shell import ShellFrame from PyCrust.shell import ShellFrame
class App(wxApp): class App(wxApp):
@@ -34,3 +33,5 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -1,6 +1,10 @@
PyCrust - The Flakiest Python Shell PyCrust - The Flakiest Python Shell
Half-baked by Patrick K. O'Brien (pobrien@orbtech.com) Half-baked by Patrick K. O'Brien (pobrien@orbtech.com)
======================================================
==============================================================
* Orbtech - "Your Source For Python Development Services" *
* Sample all our half-baked Python goods at www.orbtech.com. *
==============================================================
What is PyCrust? What is PyCrust?
---------------- ----------------
@@ -20,7 +24,7 @@ shouldn't build a Python program without a PyCrust either.
Where can I get the latest release of PyCrust? Where can I get the latest release of PyCrust?
------------------------------------------------------------ ----------------------------------------------
The latest PyCrust releases are available at: The latest PyCrust releases are available at:
http://sourceforge.net/project/showfiles.php?group_id=31263 http://sourceforge.net/project/showfiles.php?group_id=31263

View File

@@ -2,7 +2,6 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
from wxPython.wx import * from wxPython.wx import *
@@ -46,15 +45,20 @@ class CrustFrame(wxFrame, ShellMenu):
revision = __version__ revision = __version__
def __init__(self, parent=None, id=-1, title='PyCrust', \ def __init__(self, parent=None, id=-1, title='PyCrust', \
pos=wxDefaultPosition, size=wxDefaultSize, \
style=wxDEFAULT_FRAME_STYLE, \
rootObject=None, rootLabel=None, rootIsNamespace=1, \ rootObject=None, rootLabel=None, rootIsNamespace=1, \
locals=None, InterpClass=None, *args, **kwds): locals=None, InterpClass=None, *args, **kwds):
"""Create a PyCrust CrustFrame instance.""" """Create a PyCrust CrustFrame instance."""
wxFrame.__init__(self, parent, id, title) wxFrame.__init__(self, parent, id, title, pos, size, style)
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
intro += '\nSponsored by Orbtech.com <20> Your Source For Python Development Services'
self.CreateStatusBar() self.CreateStatusBar()
self.SetStatusText(intro) self.SetStatusText(intro)
if wxPlatform == '__WXMSW__': if wxPlatform == '__WXMSW__':
icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO) import os
filename = os.path.join(os.path.dirname(__file__), 'PyCrust.ico')
icon = wxIcon(filename, wxBITMAP_TYPE_ICO)
self.SetIcon(icon) self.SetIcon(icon)
self.crust = Crust(parent=self, intro=intro, \ self.crust = Crust(parent=self, intro=intro, \
rootObject=rootObject, \ rootObject=rootObject, \
@@ -75,3 +79,4 @@ class CrustFrame(wxFrame, ShellMenu):
self.createMenus() self.createMenus()

View File

@@ -3,7 +3,6 @@ the local namespace or any object."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "August 21, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
from wxPython.wx import * from wxPython.wx import *
@@ -217,6 +216,7 @@ class FillingText(wxStyledTextCtrl):
self.SetViewWhiteSpace(0) self.SetViewWhiteSpace(0)
self.SetTabWidth(4) self.SetTabWidth(4)
self.SetUseTabs(0) self.SetUseTabs(0)
self.SetReadOnly(1)
def setStyles(self, faces): def setStyles(self, faces):
"""Configure font size, typeface and color for lexer.""" """Configure font size, typeface and color for lexer."""
@@ -248,6 +248,11 @@ class FillingText(wxStyledTextCtrl):
self.StyleSetSpec(wxSTC_P_COMMENTBLOCK, "fore:#7F7F7F") self.StyleSetSpec(wxSTC_P_COMMENTBLOCK, "fore:#7F7F7F")
self.StyleSetSpec(wxSTC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces) self.StyleSetSpec(wxSTC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
def SetText(self, *args, **kwds):
self.SetReadOnly(0)
wxStyledTextCtrl.SetText(self, *args, **kwds)
self.SetReadOnly(1)
class Filling(wxSplitterWindow): class Filling(wxSplitterWindow):
"""PyCrust Filling based on wxSplitterWindow.""" """PyCrust Filling based on wxSplitterWindow."""
@@ -288,7 +293,9 @@ class FillingFrame(wxFrame):
self.CreateStatusBar() self.CreateStatusBar()
self.SetStatusText(intro) self.SetStatusText(intro)
if wxPlatform == '__WXMSW__': if wxPlatform == '__WXMSW__':
icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO) import os
filename = os.path.join(os.path.dirname(__file__), 'PyCrust.ico')
icon = wxIcon(filename, wxBITMAP_TYPE_ICO)
self.SetIcon(icon) self.SetIcon(icon)
self.filling = Filling(parent=self, rootObject=rootObject, \ self.filling = Filling(parent=self, rootObject=rootObject, \
rootLabel=rootLabel, \ rootLabel=rootLabel, \
@@ -308,3 +315,4 @@ class App(wxApp):

View File

@@ -2,7 +2,6 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
import os import os
@@ -103,4 +102,4 @@ class InterpreterAlaCarte(Interpreter):
sys.ps1 = ps1 sys.ps1 = ps1
sys.ps2 = ps2 sys.ps2 = ps2

View File

@@ -3,7 +3,6 @@ like call tips and command auto completion."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "August 8, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
import inspect import inspect
@@ -168,3 +167,4 @@ def getRoot(command, terminator=None):
return root return root

View File

@@ -2,7 +2,6 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
class PseudoKeyword: class PseudoKeyword:
@@ -88,3 +87,4 @@ class PseudoFileErr(PseudoFile):
return 1 return 1

View File

@@ -5,7 +5,6 @@ SourceForge project page at http://sourceforge.net/projects/pycrust/."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
from wxPython.wx import * from wxPython.wx import *
@@ -326,6 +325,20 @@ class Shell(wxStyledTextCtrl):
# If the auto-complete window is up let it do its thing. # If the auto-complete window is up let it do its thing.
elif self.AutoCompActive(): elif self.AutoCompActive():
event.Skip() event.Skip()
# Cut to the clipboard.
elif event.ControlDown() and key in (ord('X'), ord('x')):
self.Cut()
# Copy to the clipboard.
elif event.ControlDown() and not event.ShiftDown() \
and key in (ord('C'), ord('c')):
self.Copy()
# Copy to the clipboard, including prompts.
elif event.ControlDown() and event.ShiftDown() \
and key in (ord('C'), ord('c')):
self.CopyWithPrompts()
# Paste from the clipboard.
elif event.ControlDown() and key in (ord('V'), ord('v')):
self.Paste()
# Retrieve the previous command from the history buffer. # Retrieve the previous command from the history buffer.
elif (event.ControlDown() and key == WXK_UP) \ elif (event.ControlDown() and key == WXK_UP) \
or (event.AltDown() and key in (ord('P'), ord('p'))): or (event.AltDown() and key in (ord('P'), ord('p'))):
@@ -363,6 +376,9 @@ class Shell(wxStyledTextCtrl):
# Don't toggle between insert mode and overwrite mode. # Don't toggle between insert mode and overwrite mode.
elif key == WXK_INSERT: elif key == WXK_INSERT:
pass pass
# Protect the readonly portion of the shell.
elif not self.CanEdit():
pass
else: else:
event.Skip() event.Skip()
@@ -509,22 +525,26 @@ class Shell(wxStyledTextCtrl):
The command may not necessarily be valid Python syntax.""" The command may not necessarily be valid Python syntax."""
if not text: if not text:
text = self.GetCurLine()[0] text = self.GetCurLine()[0]
# XXX Need to extract real prompts here. Need to keep track of the # Strip the prompt off the front of text leaving just the command.
# prompt every time a command is issued. command = self.lstripPrompt(text)
if command == text:
command = '' # Real commands have prompts.
if rstrip:
command = command.rstrip()
return command
def lstripPrompt(self, text):
"""Return text without a leading prompt."""
ps1 = str(sys.ps1) ps1 = str(sys.ps1)
ps1size = len(ps1) ps1size = len(ps1)
ps2 = str(sys.ps2) ps2 = str(sys.ps2)
ps2size = len(ps2) ps2size = len(ps2)
# Strip the prompt off the front of text leaving just the command. # Strip the prompt off the front of text.
if text[:ps1size] == ps1: if text[:ps1size] == ps1:
command = text[ps1size:] text = text[ps1size:]
elif text[:ps2size] == ps2: elif text[:ps2size] == ps2:
command = text[ps2size:] text = text[ps2size:]
else: return text
command = ''
if rstrip:
command = command.rstrip()
return command
def push(self, command): def push(self, command):
"""Send command to the interpreter for execution.""" """Send command to the interpreter for execution."""
@@ -738,6 +758,17 @@ class Shell(wxStyledTextCtrl):
if self.CanCopy(): if self.CanCopy():
command = self.GetSelectedText() command = self.GetSelectedText()
command = command.replace(os.linesep + sys.ps2, os.linesep) command = command.replace(os.linesep + sys.ps2, os.linesep)
command = command.replace(os.linesep + sys.ps1, os.linesep)
command = self.lstripPrompt(text=command)
data = wxTextDataObject(command)
if wxTheClipboard.Open():
wxTheClipboard.SetData(data)
wxTheClipboard.Close()
def CopyWithPrompts(self):
"""Copy selection, including prompts, and place it on the clipboard."""
if self.CanCopy():
command = self.GetSelectedText()
data = wxTextDataObject(command) data = wxTextDataObject(command)
if wxTheClipboard.Open(): if wxTheClipboard.Open():
wxTheClipboard.SetData(data) wxTheClipboard.SetData(data)
@@ -752,6 +783,7 @@ class Shell(wxStyledTextCtrl):
if wxTheClipboard.GetData(data): if wxTheClipboard.GetData(data):
command = data.GetText() command = data.GetText()
command = self.fixLineEndings(command) command = self.fixLineEndings(command)
command = self.lstripPrompt(text=command)
command = command.replace(os.linesep + sys.ps2, '\n') command = command.replace(os.linesep + sys.ps2, '\n')
command = command.replace(os.linesep, '\n') command = command.replace(os.linesep, '\n')
command = command.replace('\n', os.linesep + sys.ps2) command = command.replace('\n', os.linesep + sys.ps2)
@@ -952,10 +984,13 @@ class ShellFrame(wxFrame, ShellMenu):
"""Create a PyCrust ShellFrame instance.""" """Create a PyCrust ShellFrame instance."""
wxFrame.__init__(self, parent, id, title, pos, size, style) wxFrame.__init__(self, parent, id, title, pos, size, style)
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
intro += '\nSponsored by Orbtech.com <20> Your Source For Python Development Services'
self.CreateStatusBar() self.CreateStatusBar()
self.SetStatusText(intro) self.SetStatusText(intro)
if wxPlatform == '__WXMSW__': if wxPlatform == '__WXMSW__':
icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO) import os
filename = os.path.join(os.path.dirname(__file__), 'PyCrust.ico')
icon = wxIcon(filename, wxBITMAP_TYPE_ICO)
self.SetIcon(icon) self.SetIcon(icon)
self.shell = Shell(parent=self, id=-1, introText=intro, \ self.shell = Shell(parent=self, id=-1, introText=intro, \
locals=locals, InterpClass=InterpClass, \ locals=locals, InterpClass=InterpClass, \
@@ -966,3 +1001,4 @@ class ShellFrame(wxFrame, ShellMenu):

View File

@@ -4,7 +4,7 @@ interpreter, each have a revision property based on the CVS Revision."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2] __version__ = "$Revision$"[11:-2]
VERSION = '0.7' VERSION = '0.7'

View File

@@ -1,10 +1,77 @@
PLEASE NOTE: This is experimental code. It needs an overhall in the wxEditor component
drawing and update code, and there is occasionally a ------------------
mysteriously disappearing line...
I am working on a StyledTextEditor that will likely The wxEditor class implements a simple text editor using wxPython. You
render this editor obsolete... But this one is at can create a custom editor by subclassing wxEditor. Even though much of
least somewhat functional now while the other is still the editor is implemented in Python, it runs surprisingly smoothly on
vapor. normal hardware with small files.
- Robin
Keys
----
Keys are similar to Windows-based editors:
Tab: 1 to 4 spaces (to next tab stop)
Cursor movement: Arrow keys
Beginning of line: Home
End of line: End
Beginning of buffer: Control-Home
End of the buffer: Control-End
Select text: Hold down Shift while moving the cursor
Copy: Shift-Insert, Control-C
Cut: Shift-Delete, Control-X
Paste: Control-Insert, Control-V
How to use it
-------------
The demo code (demo/wxEditor.py) shows how to use it as a simple text
box. Use the SetText() and GetText() methods to set or get text from
the component; these both return a list of strings.
The samples/FrogEdit directory has an example of a simple text editor
application that uses the wxEditor component.
Subclassing
-----------
To add or change functionality, you can subclass this
component. One example of this might be to change the key
Alt key commands. In that case you would (for example) override the
SetAltFuncs() method.
History
-------
The original author of this component was Dirk Holtwic. It originally
had limited support for syntax highlighting, but was not a usable text
editor, as it didn't implement select (with keys or mouse), or any of
the usual key sequences you'd expect in an editor. Robin Dunn did some
refactoring work to make it more usable. Steve Howell and Adam Feuer
did a lot of refactoring, and added some functionality, including
keyboard and mouse select, properly working scrollbars, and
overridable keys. Adam and Steve also removed support for
syntax-highlighting while refactoring the code.
To do
-----
Alt/Ctrl Arrow keys move by word
Descriptive help text for keys
Speed improvements
Different fonts/colors
Authors
-------
Steve Howell, Adam Feuer, Dirk Holtwic, Robin Dunn
Contact
-------
You can find the latest code for wxEditor here:
http://www.pobox.com/~adamf/software/
We're not actively maintaining this code, but we can answer
questions about it. You can email us at:
Adam Feuer <adamf at pobox dot com>
Steve Howell <showell at zipcon dot net>
29 November 2001

View File

@@ -15,4 +15,3 @@
# import the main classes into the package namespace. # import the main classes into the package namespace.
from editor import wxEditor from editor import wxEditor
from py_editor import wxPyEditor

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
# images converted with wxPython's img2py.py tool
from wxPython.wx import wxBitmapFromXPMData, wxImageFromBitmap
import cPickle, zlib
##----------- Common Functions
def GetBitmap(ImageData):
return wxBitmapFromXPMData(ImageData)
def GetImage(ImageData):
return wxImageFromBitmap(GetBitmap(ImageData))
##----------- Image Data
EofImageData = cPickle.loads(zlib.decompress(
'x\xda\xd3\xc8)0\xe4\nV7W0W0R0T\xe7J\x0cV\xd7SHVp\xcaIL\xce\x06\xf3\x14\x80<\
\xbf\xfc\xbcT(GA\x0f\x88\xa1l===\x18[\x0f\x04 l=\x08\xc0\x10GQ\x0f7G\x0f\x00\
\xec\xa2\x19\x96' ))

View File

@@ -1,211 +0,0 @@
# (C)opyright by Dirk Holtwick, 1999
# ----------------------------------
# holtwick@spirito.de
# http://www.spirito.de/pyde
from editor import *
from string import *
from keyword import *
from tokenizer import *
"""
This module will be loaded by the main
window. It implements some methods that
are typical for Python sources.
"""
class wxPyEditor(wxEditor):
# ------------------------------------------------------------------
def __init__(self, parent, id,
pos=wxDefaultPosition, size=wxDefaultSize, style=0):
wxEditor.__init__(self, parent, id, pos, size, style)
self.SetFontTab([
wxNamedColour('black'),
wxNamedColour('blue'),
wxNamedColour('red'),
wxNamedColour('darkgreen'),
wxNamedColour('brown')
])
# ------------------------------------------------------------------
def OnUpdateHighlight(self, line = -1):
if line>=0:
t = self.text[line].text
syn = []
toks = Tokenizer(t).tokens()
for type, string, begin, end in toks:
if type == "KEY":
syn.append((begin, 1))
syn.append((end, 0))
elif type == "COMMENT":
syn.append((begin, 2))
elif type == "STRING":
syn.append((begin, 3))
syn.append((end, 0))
elif type == "NUMBER":
syn.append((begin, 4))
syn.append((end, 0))
elif type == "NAME":
if string=="self":
syn.append((begin, 4))
syn.append((end, 0))
else:
pass
self.text[line].syntax = syn
# ------------------------------------------------------------------
def OnUpdateSyntax(self, line = -1):
if line>=0:
"""
tx, syn, m = self.text[line]
pre = 0
for i in range(0,len(tx)):
if tx[i] != " ":
pre = i
break
t = tx[pre:]
t = Tokenizer(t).line()
t = tx[:pre] + t
self.text[line] = t, syn, m
"""
self.OnUpdateHighlight(line)
# ------------------------------------------------------------------
def OnTabulator(self, event):
add = +1
if event.ShiftDown():
add = -1
t = self.GetTextLine(self.cy)
if strip(t):
indent = self.GetIndent(t)
# print indent
t = t[indent:]
tabs = indent / self.tabsize
# for i in range(0,tabs+add):
t = (" " * 4 * (tabs+add)) + t
self.SetTextLine(self.cy, t)
elif add>0:
self.InsertText(" ")
# ------------------------------------------------------------------
def FindQuote(self, lineno, quote_type='"""', direction=1):
"""find line containing the matching quote"""
l =lineno +direction
while (l < len(self.text)-1) and (l >= 0):
if find(self.text[l].text, quote_type) >=0: return l
l =l +direction
return None
def FindNextLine(self, lineno, direction=1):
"""get the next line of code (skipping comment lines and empty lines)"""
l =lineno +direction
while (l < len(self.text)-1) and (l >= 0):
str =lstrip(self.text[l].text)
if (len(str) >0) and (str[0] !="#"): return l
l =l +direction
return None
def Fold(self):
l = self.GetLine(self.cy)
line = self.text[l]
t = line.text
# fold ...
if line.editable:
# 3*quotes
qpos =find(t, '"""')
if qpos >=0: qtype ='"""'
else:
qpos =find(t, "'''")
if qpos >=0: qtype ="'''"
if (qpos >=0) and (find(t[qpos+3:], qtype) <0):
closing_quote =self.FindQuote(l, qtype)
if closing_quote !=None:
line.editable = not line.editable
l =l +1
while l <= closing_quote:
self.text[l].visible =self.text[l].visible +1
l =l +1
else: # try normal fold on leading whitespace
lim = self.GetIndent(t)
lnext =self.FindNextLine(l)
if (lnext !=None) \
and (self.GetIndent(self.text[lnext].text) >lim):
line.editable =FALSE
lstart =l +1
l =self.FindNextLine(l)
while (l !=None) \
and (self.GetIndent(self.text[l].text) >lim):
l =self.FindNextLine(l)
if l ==None:
# fold till the end
l =len(self.text)
for line in self.text[lstart:l]:
line.visible =line.visible +1
# ... or unfold
else:
lim = line.visible + 1
line.editable = not line.editable
l = l + 1
line = self.text[l]
while (l < (len(self.text) -1)) and (line.visible>=lim):
line.visible = line.visible - 1
l = l + 1
line = self.text[l]
def FoldAll(self):
self.CalcLines()
self.cx = 0
self.cy = len(self.lines) - 1
prev_indent =0
# following loop is exited in two cases:
# when self.cy becomes 0 (topmost level is not folded by FoldAll)
# or when FindNextLine() returns None (all remaining lines till
# the beginning of the text are empty or comments)
while self.cy:
t = self.GetTextLine(self.cy)
# indent-based folding
indent =self.GetIndent(t)
if indent <prev_indent:
self.Fold()
prev_indent =indent
# triple-quote folding
qpos =find(t, '"""')
if qpos >=0: qtype ='"""'
else:
qpos =find(t, "'''")
if qpos >=0: qtype ="'''"
if (qpos >=0) and (find(t[qpos+3:], qtype) <0):
closing_quote =self.FindQuote(self.cy, qtype, -1)
if closing_quote !=None:
# XXX potential bug: unmatched triple quotes
self.cy =closing_quote
self.Fold()
self.cy =self.FindNextLine(self.cy, -1)
if self.cy ==None: self.cy =0
# ------------------------------------------------------------------
def OnFold(self):
self.Fold()
# ------------------------------------------------------------------
def OnInit(self):
#self.FoldAll()
pass

View File

@@ -0,0 +1,42 @@
TRUE = 1
FALSE = 0
def RestOfLine(sx, width, data, bool):
if len(data) == 0 and sx == 0:
return [('', bool)]
if sx >= len(data):
return []
return [(data[sx:sx+width], bool)]
def Selection(SelectBegin,SelectEnd, sx, width, line, data):
if SelectEnd is None or SelectBegin is None:
return RestOfLine(sx, width, data, FALSE)
(bRow, bCol) = SelectBegin
(eRow, eCol) = SelectEnd
if (eRow < bRow):
(bRow, bCol) = SelectEnd
(eRow, eCol) = SelectBegin
if (line < bRow or eRow < line):
return RestOfLine(sx, width, data, FALSE)
if (bRow < line and line < eRow):
return RestOfLine(sx, width, data, TRUE)
if (bRow == eRow) and (eCol < bCol):
(bCol, eCol) = (eCol, bCol)
# selection either starts or ends on this line
end = min(sx+width, len(data))
if (bRow < line):
bCol = 0
if (line < eRow):
eCol = end
pieces = []
if (sx < bCol):
if bCol <= end:
pieces += [(data[sx:bCol], FALSE)]
else:
return [(data[sx:end], FALSE)]
pieces += [(data[max(bCol,sx):min(eCol,end)], TRUE)]
if (eCol < end):
pieces += [(data[eCol:end], FALSE)]
return pieces

View File

@@ -1,60 +0,0 @@
from tokenize import *
from keyword import *
from string import *
class Tokenizer:
"""
Simple class to create a list of token-tuples like:
(type, string, first, last)
Example:
t = Tokenizer('def hallo(du): # juchee')
print t.tokens()
"""
def __init__(self, text):
self.text = text
self.toks = []
try:
tokenize(self.readline, self.get)
except TokenError:
pass
def tokens(self):
return self.toks
def get(self, type, string, begin, end, l):
#print begin,end
h1, b = begin
h2, e = end
tname = tok_name[type]
if iskeyword(string):
tname = "KEY"
self.toks.append( (tname, string, b, e) )
def readline(self):
t = self.text
self.text = ""
return t
def line(self):
pre = ""
out = ""
for type, string, begin, end in self.toks:
if (pre in ["NAME","KEY"]) and (not string in [".",",","("]):
out = out + " "
if type in ["NAME","KEY"]:
out = out + string
elif type=="OP":
if string in [",",":"]:
out = out + string + " "
else:
out = out + string
else:
out = out + string
pre = type
return out