pythoneditor.py
来自「Wxpython Implemented on Windows CE, Sou」· Python 代码 · 共 691 行 · 第 1/2 页
PY
691 行
#----------------------------------------------------------------------------
# Name: PythonEditor.py
# Purpose: PythonEditor for wx.lib.pydocview tbat uses the Styled Text Control
#
# Author: Peter Yared
#
# Created: 8/15/03
# CVS-ID: $Id: PythonEditor.py,v 1.5 2006/04/20 06:25:58 RD Exp $
# Copyright: (c) 2004-2005 ActiveGrid, Inc.
# License: wxWindows License
#----------------------------------------------------------------------------
import CodeEditor
import wx
import wx.lib.docview
import wx.lib.pydocview
import string
import keyword # So it knows what to hilite
import wx.py # For the Python interpreter
import wx.stc # For the Python interpreter
import cStringIO # For indent
import OutlineService
import STCTextEditor
import keyword # for GetAutoCompleteKeywordList
import sys # for GetAutoCompleteKeywordList
import MessageService # for OnCheckCode
import OutlineService
import FindInDirService
from UICommon import CaseInsensitiveCompare
try:
import checker # for pychecker
_CHECKER_INSTALLED = True
except ImportError:
_CHECKER_INSTALLED = False
import os.path # for pychecker
_ = wx.GetTranslation
if wx.Platform == '__WXMSW__':
_WINDOWS = True
else:
_WINDOWS = False
VIEW_PYTHON_INTERPRETER_ID = wx.NewId()
class PythonDocument(CodeEditor.CodeDocument):
pass
class PythonView(CodeEditor.CodeView):
def GetCtrlClass(self):
""" Used in split window to instantiate new instances """
return PythonCtrl
def ProcessUpdateUIEvent(self, event):
if not self.GetCtrl():
return False
id = event.GetId()
if id == CodeEditor.CHECK_CODE_ID:
hasText = self.GetCtrl().GetTextLength() > 0
event.Enable(hasText)
return True
return CodeEditor.CodeView.ProcessUpdateUIEvent(self, event)
def OnActivateView(self, activate, activeView, deactiveView):
STCTextEditor.TextView.OnActivateView(self, activate, activeView, deactiveView)
if activate and self.GetCtrl():
if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
self.LoadOutline()
else:
wx.CallAfter(self.LoadOutline) # need CallAfter because document isn't loaded yet
def OnClose(self, deleteWindow = True):
status = STCTextEditor.TextView.OnClose(self, deleteWindow)
wx.CallAfter(self.ClearOutline) # need CallAfter because when closing the document, it is Activated and then Close, so need to match OnActivateView's CallAfter
return status
def GetAutoCompleteKeywordList(self, context, hint):
obj = None
try:
if context and len(context):
obj = eval(context, globals(), locals())
except:
if not hint or len(hint) == 0: # context isn't valid, maybe it was the hint
hint = context
if obj is None:
kw = keyword.kwlist[:]
else:
symTbl = dir(obj)
kw = filter(lambda item: item[0] != '_', symTbl) # remove local variables and methods
if hint and len(hint):
lowerHint = hint.lower()
filterkw = filter(lambda item: item.lower().startswith(lowerHint), kw) # remove variables and methods that don't match hint
kw = filterkw
kw.sort(CaseInsensitiveCompare)
if hint:
replaceLen = len(hint)
else:
replaceLen = 0
return " ".join(kw), replaceLen
def OnCheckCode(self):
if not _CHECKER_INSTALLED:
wx.MessageBox(_("pychecker not found. Please install pychecker."), _("Check Code"))
return
filename = os.path.basename(self.GetDocument().GetFilename())
# pychecker only works on files, doesn't take a stream or string input
if self.GetDocument().IsModified():
dlg = wx.MessageDialog(self.GetFrame(), _("'%s' has been modfied and must be saved first. Save file and check code?") % filename, _("Check Code"))
dlg.CenterOnParent()
val = dlg.ShowModal()
dlg.Destroy()
if val == wx.ID_OK:
self.GetDocument().Save()
else:
return
messageService = wx.GetApp().GetService(MessageService.MessageService)
messageService.ShowWindow()
view = messageService.GetView()
if not view:
return
view.ClearLines()
view.SetCallback(self.OnJumpToFoundLine)
# Set cursor to Wait cursor
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
try:
# This takes a while for involved code
checker.checkSyntax(self.GetDocument().GetFilename(), view)
finally:
# Set cursor to Default cursor
wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
def OnJumpToFoundLine(self, event):
messageService = wx.GetApp().GetService(MessageService.MessageService)
lineText, pos = messageService.GetView().GetCurrLine()
lineEnd = lineText.find(".py:")
if lineEnd == -1:
return
lineStart = lineEnd + len(".py:")
lineEnd = lineText.find(":", lineStart)
lineNum = int(lineText[lineStart:lineEnd])
filename = lineText[0:lineStart - 1]
foundView = None
openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
for openDoc in openDocs:
if openDoc.GetFilename() == filename:
foundView = openDoc.GetFirstView()
break
if not foundView:
doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE)
foundView = doc.GetFirstView()
if foundView:
foundView.GetFrame().SetFocus()
foundView.Activate()
foundView.GotoLine(lineNum)
startPos = foundView.PositionFromLine(lineNum)
endPos = foundView.GetLineEndPosition(lineNum)
# wxBug: Need to select in reverse order, (end, start) to put cursor at head of line so positioning is correct
# Also, if we use the correct positioning order (start, end), somehow, when we open a edit window for the first
# time, we don't see the selection, it is scrolled off screen
foundView.SetSelection(endPos, startPos)
wx.GetApp().GetService(OutlineService.OutlineService).LoadOutline(foundView, position=startPos)
class PythonInterpreterView(wx.lib.docview.View):
def OnCreate(self, doc, flags):
frame = wx.GetApp().CreateDocumentFrame(self, doc, flags)
sizer = wx.BoxSizer()
self._pyCrust = wx.py.crust.Crust(frame)
sizer.Add(self._pyCrust, 1, wx.EXPAND, 0)
frame.SetSizer(sizer)
frame.Layout()
self.Activate()
frame.Show()
return True
def ProcessEvent(self, event):
if not hasattr(self, "_pyCrust") or not self._pyCrust:
return wx.lib.docview.View.ProcessEvent(self, event)
stcControl = wx.Window_FindFocus()
if not isinstance(stcControl, wx.stc.StyledTextCtrl):
return wx.lib.docview.View.ProcessEvent(self, event)
id = event.GetId()
if id == wx.ID_UNDO:
stcControl.Undo()
return True
elif id == wx.ID_REDO:
stcControl.Redo()
return True
elif id == wx.ID_CUT:
stcControl.Cut()
return True
elif id == wx.ID_COPY:
stcControl.Copy()
return True
elif id == wx.ID_PASTE:
stcControl.Paste()
return True
elif id == wx.ID_CLEAR:
stcControl.Clear()
return True
elif id == wx.ID_SELECTALL:
stcControl.SetSelection(0, -1)
return True
else:
return wx.lib.docview.View.ProcessEvent(self, event)
def ProcessUpdateUIEvent(self, event):
if not hasattr(self, "_pyCrust") or not self._pyCrust:
return wx.lib.docview.View.ProcessUpdateUIEvent(self, event)
stcControl = wx.Window_FindFocus()
if not isinstance(stcControl, wx.stc.StyledTextCtrl):
return wx.lib.docview.View.ProcessUpdateUIEvent(self, event)
id = event.GetId()
if id == wx.ID_UNDO:
event.Enable(stcControl.CanUndo())
return True
elif id == wx.ID_REDO:
event.Enable(stcControl.CanRedo())
return True
elif id == wx.ID_CUT:
event.Enable(stcControl.CanCut())
return True
elif id == wx.ID_COPY:
event.Enable(stcControl.CanCopy())
return True
elif id == wx.ID_PASTE:
event.Enable(stcControl.CanPaste())
return True
elif id == wx.ID_CLEAR:
event.Enable(True) # wxBug: should be stcControl.CanCut()) but disabling clear item means del key doesn't work in control as expected
return True
elif id == wx.ID_SELECTALL:
event.Enable(stcControl.GetTextLength() > 0)
return True
else:
return wx.lib.docview.View.ProcessUpdateUIEvent(self, event)
def OnClose(self, deleteWindow=True):
if deleteWindow and self.GetFrame():
self.GetFrame().Destroy()
return True
class PythonInterpreterDocument(wx.lib.docview.Document):
""" Generate Unique Doc Type """
pass
class PythonService(CodeEditor.CodeService):
def __init__(self):
CodeEditor.CodeService.__init__(self)
docManager = wx.GetApp().GetDocumentManager()
pythonInterpreterTemplate = wx.lib.docview.DocTemplate(docManager,
_("Python Interpreter"),
"*.Foobar",
"Foobar",
".Foobar",
_("Python Interpreter Document"),
_("Python Interpreter View"),
PythonInterpreterDocument,
PythonInterpreterView,
flags = wx.lib.docview.TEMPLATE_INVISIBLE,
icon = getPythonIcon())
docManager.AssociateTemplate(pythonInterpreterTemplate)
def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
CodeEditor.CodeService.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
if document and document.GetDocumentTemplate().GetDocumentType() != PythonDocument:
return
if not document and wx.GetApp().GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
return
viewMenu = menuBar.GetMenu(menuBar.FindMenu(_("&View")))
viewStatusBarItemPos = self.GetMenuItemPos(viewMenu, wx.lib.pydocview.VIEW_STATUSBAR_ID)
viewMenu.InsertCheckItem(viewStatusBarItemPos + 1, VIEW_PYTHON_INTERPRETER_ID, _("Python &Interpreter"), _("Shows or hides the Python interactive window"))
wx.EVT_MENU(frame, VIEW_PYTHON_INTERPRETER_ID, frame.ProcessEvent)
wx.EVT_UPDATE_UI(frame, VIEW_PYTHON_INTERPRETER_ID, frame.ProcessUpdateUIEvent)
def ProcessEvent(self, event):
id = event.GetId()
if id == VIEW_PYTHON_INTERPRETER_ID:
self.OnViewPythonInterpreter(event)
return True
else:
return CodeEditor.CodeService.ProcessEvent(self, event)
def ProcessUpdateUIEvent(self, event):
id = event.GetId()
if id == VIEW_PYTHON_INTERPRETER_ID:
event.Enable(True)
docManager = wx.GetApp().GetDocumentManager()
event.Check(False)
for doc in docManager.GetDocuments():
if isinstance(doc, PythonInterpreterDocument):
event.Check(True)
break
return True
else:
return CodeEditor.CodeService.ProcessUpdateUIEvent(self, event)
def OnViewPythonInterpreter(self, event):
for doc in wx.GetApp().GetDocumentManager().GetDocuments():
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?