📄 codeeditor.py
字号:
#----------------------------------------------------------------------------# Name: CodeEditor.py# Purpose: Abstract Code Editor for pydocview tbat uses the Styled Text Control## Author: Peter Yared## Created: 8/10/03# CVS-ID: $Id: CodeEditor.py,v 1.6 2006/04/20 06:26:01 RD Exp $# Copyright: (c) 2004-2005 ActiveGrid, Inc.# License: wxWindows License#----------------------------------------------------------------------------import STCTextEditorimport wximport wx.lib.docviewimport OutlineServiceimport osimport reimport stringimport sysimport MarkerServicefrom UICommon import CaseInsensitiveCompare_ = wx.GetTranslationif wx.Platform == '__WXMSW__': _WINDOWS = Trueelse: _WINDOWS = FalseEXPAND_TEXT_ID = wx.NewId()COLLAPSE_TEXT_ID = wx.NewId()EXPAND_TOP_ID = wx.NewId()COLLAPSE_TOP_ID = wx.NewId()EXPAND_ALL_ID = wx.NewId()COLLAPSE_ALL_ID = wx.NewId()CHECK_CODE_ID = wx.NewId()AUTO_COMPLETE_ID = wx.NewId()CLEAN_WHITESPACE = wx.NewId()COMMENT_LINES_ID = wx.NewId()UNCOMMENT_LINES_ID = wx.NewId()INDENT_LINES_ID = wx.NewId()DEDENT_LINES_ID = wx.NewId()USE_TABS_ID = wx.NewId()SET_INDENT_WIDTH_ID = wx.NewId()FOLDING_ID = wx.NewId()class CodeDocument(STCTextEditor.TextDocument): pass class CodeView(STCTextEditor.TextView): #---------------------------------------------------------------------------- # Overridden methods #---------------------------------------------------------------------------- def GetCtrlClass(self): """ Used in split window to instantiate new instances """ return CodeCtrl def ProcessEvent(self, event): id = event.GetId() if id == EXPAND_TEXT_ID: self.GetCtrl().ToggleFold(self.GetCtrl().GetCurrentLine()) return True elif id == COLLAPSE_TEXT_ID: self.GetCtrl().ToggleFold(self.GetCtrl().GetCurrentLine()) return True elif id == EXPAND_TOP_ID: self.GetCtrl().ToggleFoldAll(expand = True, topLevelOnly = True) return True elif id == COLLAPSE_TOP_ID: self.GetCtrl().ToggleFoldAll(expand = False, topLevelOnly = True) return True elif id == EXPAND_ALL_ID: self.GetCtrl().ToggleFoldAll(expand = True) return True elif id == COLLAPSE_ALL_ID: self.GetCtrl().ToggleFoldAll(expand = False) return True elif id == CHECK_CODE_ID: self.OnCheckCode() return True elif id == AUTO_COMPLETE_ID: self.OnAutoComplete() return True elif id == CLEAN_WHITESPACE: self.OnCleanWhiteSpace() return True elif id == SET_INDENT_WIDTH_ID: self.OnSetIndentWidth() return True elif id == USE_TABS_ID: self.GetCtrl().SetUseTabs(not self.GetCtrl().GetUseTabs()) return True elif id == INDENT_LINES_ID: self.GetCtrl().CmdKeyExecute(wx.stc.STC_CMD_TAB) return True elif id == DEDENT_LINES_ID: self.GetCtrl().CmdKeyExecute(wx.stc.STC_CMD_BACKTAB) return True elif id == COMMENT_LINES_ID: self.OnCommentLines() return True elif id == UNCOMMENT_LINES_ID: self.OnUncommentLines() return True else: return STCTextEditor.TextView.ProcessEvent(self, event) def ProcessUpdateUIEvent(self, event): if not self.GetCtrl(): return False id = event.GetId() if id == EXPAND_TEXT_ID: if self.GetCtrl().GetViewFolding(): event.Enable(self.GetCtrl().CanLineExpand(self.GetCtrl().GetCurrentLine())) else: event.Enable(False) return True elif id == COLLAPSE_TEXT_ID: if self.GetCtrl().GetViewFolding(): event.Enable(self.GetCtrl().CanLineCollapse(self.GetCtrl().GetCurrentLine())) else: event.Enable(False) return True elif (id == EXPAND_TOP_ID or id == COLLAPSE_TOP_ID or id == EXPAND_ALL_ID or id == COLLAPSE_ALL_ID): if self.GetCtrl().GetViewFolding(): event.Enable(self.GetCtrl().GetTextLength() > 0) else: event.Enable(False) return True elif (id == AUTO_COMPLETE_ID or id == CLEAN_WHITESPACE or id == INDENT_LINES_ID or id == DEDENT_LINES_ID or id == COMMENT_LINES_ID or id == UNCOMMENT_LINES_ID): event.Enable(self.GetCtrl().GetTextLength() > 0) return True elif id == CHECK_CODE_ID: event.Enable(False) return True elif id == SET_INDENT_WIDTH_ID: event.Enable(True) return True elif id == FOLDING_ID: event.Enable(self.GetCtrl().GetViewFolding()) return True elif id == USE_TABS_ID: event.Enable(True) event.Check(self.GetCtrl().GetUseTabs()) return True else: return STCTextEditor.TextView.ProcessUpdateUIEvent(self, event) #---------------------------------------------------------------------------- # Methods for OutlineService #---------------------------------------------------------------------------- def OnChangeFilename(self): wx.lib.docview.View.OnChangeFilename(self) self.LoadOutline(force=True) def ClearOutline(self): outlineService = wx.GetApp().GetService(OutlineService.OutlineService) if not outlineService: return outlineView = outlineService.GetView() if not outlineView: return outlineView.ClearTreeCtrl() def LoadOutline(self, force=False): outlineService = wx.GetApp().GetService(OutlineService.OutlineService) if not outlineService: return outlineService.LoadOutline(self, force=force) def DoLoadOutlineCallback(self, force=False): outlineService = wx.GetApp().GetService(OutlineService.OutlineService) if not outlineService: return False outlineView = outlineService.GetView() if not outlineView: return False treeCtrl = outlineView.GetTreeCtrl() if not treeCtrl: return False view = treeCtrl.GetCallbackView() newCheckSum = self.GenCheckSum() if not force: if view and view is self: if self._checkSum == newCheckSum: return False self._checkSum = newCheckSum treeCtrl.DeleteAllItems() document = self.GetDocument() if not document: return True filename = document.GetFilename() if filename: rootItem = treeCtrl.AddRoot(os.path.basename(filename)) treeCtrl.SetDoSelectCallback(rootItem, self, (0,0)) else: return True text = self.GetValue() if not text: return True CLASS_PATTERN = 'class[ \t]+\w+.*?:' DEF_PATTERN = 'def[ \t]+\w+\(.*?\)' classPat = re.compile(CLASS_PATTERN, re.M|re.S) defPat= re.compile(DEF_PATTERN, re.M|re.S) pattern = re.compile('^[ \t]*((' + CLASS_PATTERN + ')|('+ DEF_PATTERN +'.*?:)).*?$', re.M|re.S) iter = pattern.finditer(text) indentStack = [(0, rootItem)] for pattern in iter: line = pattern.string[pattern.start(0):pattern.end(0)] classLine = classPat.search(line) if classLine: indent = classLine.start(0) itemStr = classLine.string[classLine.start(0):classLine.end(0)-1] # don't take the closing ':' itemStr = itemStr.replace("\n", "").replace("\r", "").replace(",\\", ",").replace(" ", "") # remove line continuations and spaces from outline view else: defLine = defPat.search(line) if defLine: indent = defLine.start(0) itemStr = defLine.string[defLine.start(0):defLine.end(0)] itemStr = itemStr.replace("\n", "").replace("\r", "").replace(",\\", ",").replace(" ", "") # remove line continuations and spaces from outline view if indent == 0: parentItem = rootItem else: lastItem = indentStack.pop() while lastItem[0] >= indent: lastItem = indentStack.pop() indentStack.append(lastItem) parentItem = lastItem[1] item = treeCtrl.AppendItem(parentItem, itemStr) treeCtrl.SetDoSelectCallback(item, self, (pattern.end(0), pattern.start(0) + indent)) # select in reverse order because we want the cursor to be at the start of the line so it wouldn't scroll to the right indentStack.append((indent, item)) treeCtrl.Expand(rootItem) return True def DoSelectCallback(self, data): if data: self.EnsureVisibleEnforcePolicy(self.LineFromPosition(data[0])) # wxBug: need to select in reverse order (end, start) to place cursor at begining of line, # otherwise, display is scrolled over to the right hard and is hard to view self.SetSelection(data[1], data[0])## def checksum(self, bytes): ## def rotate_right(c):## if c&1:## return (c>>1)|0x8000## else:## return c>>1## ## result = 0## for ch in bytes:## ch = ord(ch) & 0xFF## result = (rotate_right(result)+ch) & 0xFFFF## return result## def GenCheckSum(self): """ Poor man's checksum. We'll assume most changes will change the length of the file. """ text = self.GetValue() if text: return len(text) else: return 0 #---------------------------------------------------------------------------- # Format methods #---------------------------------------------------------------------------- def OnCheckCode(self): """ Need to overshadow this for each specific subclass """ if 0: try: code = self.GetCtrl().GetText() codeObj = compile(code, self.GetDocument().GetFilename(), 'exec') self._GetParentFrame().SetStatusText(_("The file successfully compiled")) except SyntaxError, (message, (fileName, line, col, text)): pos = self.GetCtrl().PositionFromLine(line - 1) + col - 1 self.GetCtrl().SetSelection(pos, pos) self._GetParentFrame().SetStatusText(_("Syntax Error: %s") % message) except: self._GetParentFrame().SetStatusText("%s: %s" % (sys.exc_info()[0], sys.exc_info()[1])) def OnAutoComplete(self): self.GetCtrl().AutoCompCancel()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -