📄 pythoneditor.py
字号:
#----------------------------------------------------------------------------# 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 CodeEditorimport wximport wx.lib.docviewimport wx.lib.pydocviewimport stringimport keyword # So it knows what to hiliteimport wx.py # For the Python interpreterimport wx.stc # For the Python interpreterimport cStringIO # For indentimport OutlineServiceimport STCTextEditorimport keyword # for GetAutoCompleteKeywordListimport sys # for GetAutoCompleteKeywordListimport MessageService # for OnCheckCodeimport OutlineServiceimport FindInDirServicefrom UICommon import CaseInsensitiveComparetry: import checker # for pychecker _CHECKER_INSTALLED = Trueexcept ImportError: _CHECKER_INSTALLED = Falseimport os.path # for pychecker_ = wx.GetTranslationif wx.Platform == '__WXMSW__': _WINDOWS = Trueelse: _WINDOWS = FalseVIEW_PYTHON_INTERPRETER_ID = wx.NewId()class PythonDocument(CodeEditor.CodeDocument): passclass 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 Trueclass 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -