]> git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/ide/activegrid/tool/PHPEditor.py
Docview and IDE patch from Morag Hua with fix for bug #1217890
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / PHPEditor.py
1 #----------------------------------------------------------------------------
2 # Name: PHPEditor.py
3 # Purpose: PHP Script Editor for pydocview tbat uses the Styled Text Control
4 #
5 # Author: Morgan Hua
6 #
7 # Created: 1/4/04
8 # CVS-ID: $Id$
9 # Copyright: (c) 2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
12
13 import wx
14 import string
15 import STCTextEditor
16 import CodeEditor
17 import OutlineService
18 import os
19 import re
20
21
22 class PHPDocument(CodeEditor.CodeDocument):
23
24 pass
25
26
27 class PHPView(CodeEditor.CodeView):
28
29
30 def GetCtrlClass(self):
31 """ Used in split window to instantiate new instances """
32 return PHPCtrl
33
34
35 def GetAutoCompleteHint(self):
36 pos = self.GetCtrl().GetCurrentPos()
37 if pos == 0:
38 return None, None
39
40 validLetters = string.letters + string.digits + '_$'
41 word = ''
42 while (True):
43 pos = pos - 1
44 if pos < 0:
45 break
46 char = chr(self.GetCtrl().GetCharAt(pos))
47 if char not in validLetters:
48 break
49 word = char + word
50
51 return None, word
52
53
54 def GetAutoCompleteDefaultKeywords(self):
55 return PHPKEYWORDS
56
57 #----------------------------------------------------------------------------
58 # Methods for OutlineService
59 #----------------------------------------------------------------------------
60
61 def DoLoadOutlineCallback(self, force=False):
62 outlineService = wx.GetApp().GetService(OutlineService.OutlineService)
63 if not outlineService:
64 return False
65
66 outlineView = outlineService.GetView()
67 if not outlineView:
68 return False
69
70 treeCtrl = outlineView.GetTreeCtrl()
71 if not treeCtrl:
72 return False
73
74 view = treeCtrl.GetCallbackView()
75 newCheckSum = self.GenCheckSum()
76 if not force:
77 if view and view is self:
78 if self._checkSum == newCheckSum:
79 return False
80 self._checkSum = newCheckSum
81
82 treeCtrl.DeleteAllItems()
83
84 document = self.GetDocument()
85 if not document:
86 return True
87
88 filename = document.GetFilename()
89 if filename:
90 rootItem = treeCtrl.AddRoot(os.path.basename(filename))
91 treeCtrl.SetDoSelectCallback(rootItem, self, None)
92 else:
93 return True
94
95 text = self.GetValue()
96 if not text:
97 return True
98
99 INTERFACE_PATTERN = 'interface[ \t]+\w+'
100 CLASS_PATTERN = '((final|abstract)[ \t]+)?((public|private|protected)[ \t]+)?(static[ \t]+)?class[ \t]+\w+((implements|extends)\w+)?'
101 FUNCTION_PATTERN = '(abstract[ \t]+)?((public|private|protected)[ \t]+)?(static[ \t]+)?function[ \t]+?\w+\(.*?\)'
102 interfacePat = re.compile(INTERFACE_PATTERN, re.M|re.S)
103 classPat = re.compile(CLASS_PATTERN, re.M|re.S)
104 funcPat= re.compile(FUNCTION_PATTERN, re.M|re.S)
105 pattern = re.compile('^[ \t]*('+ CLASS_PATTERN + '.*?{|' + FUNCTION_PATTERN + '|' + INTERFACE_PATTERN +'\s*?{).*?$', re.M|re.S)
106
107 iter = pattern.finditer(text)
108 indentStack = [(0, rootItem)]
109 for pattern in iter:
110 line = pattern.string[pattern.start(0):pattern.end(0)]
111 foundLine = classPat.search(line)
112 if foundLine:
113 indent = foundLine.start(0)
114 itemStr = foundLine.string[foundLine.start(0):foundLine.end(0)]
115 else:
116 foundLine = funcPat.search(line)
117 if foundLine:
118 indent = foundLine.start(0)
119 itemStr = foundLine.string[foundLine.start(0):foundLine.end(0)]
120 else:
121 foundLine = interfacePat.search(line)
122 if foundLine:
123 indent = foundLine.start(0)
124 itemStr = foundLine.string[foundLine.start(0):foundLine.end(0)]
125
126 if indent == 0:
127 parentItem = rootItem
128 else:
129 lastItem = indentStack.pop()
130 while lastItem[0] >= indent:
131 lastItem = indentStack.pop()
132 indentStack.append(lastItem)
133 parentItem = lastItem[1]
134
135 item = treeCtrl.AppendItem(parentItem, itemStr)
136 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
137 indentStack.append((indent, item))
138
139 treeCtrl.Expand(rootItem)
140
141 return True
142
143
144 class PHPService(CodeEditor.CodeService):
145
146
147 def __init__(self):
148 CodeEditor.CodeService.__init__(self)
149
150
151 class PHPCtrl(CodeEditor.CodeCtrl):
152
153
154 def __init__(self, parent, id=-1, style=wx.NO_FULL_REPAINT_ON_RESIZE):
155 CodeEditor.CodeCtrl.__init__(self, parent, id, style)
156 self.SetLexer(wx.stc.STC_LEX_PHP)
157 self.SetStyleBits(7)
158 self.SetKeyWords(4, string.join(PHPKEYWORDS))
159 self.SetProperty("fold.html", "1")
160
161
162 def CanWordWrap(self):
163 return True
164
165
166 def SetViewDefaults(self):
167 CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "PHP", hasWordWrap = True, hasTabs = True)
168
169
170 def GetFontAndColorFromConfig(self):
171 return CodeEditor.CodeCtrl.GetFontAndColorFromConfig(self, configPrefix = "PHP")
172
173
174 def UpdateStyles(self):
175 CodeEditor.CodeCtrl.UpdateStyles(self)
176
177 if not self.GetFont():
178 return
179
180 faces = { 'font' : self.GetFont().GetFaceName(),
181 'size' : self.GetFont().GetPointSize(),
182 'size2': self.GetFont().GetPointSize() - 2,
183 'color' : "%02x%02x%02x" % (self.GetFontColor().Red(), self.GetFontColor().Green(), self.GetFontColor().Blue())
184 }
185
186
187 # HTML Styles
188 # White space
189 self.StyleSetSpec(wx.stc.STC_H_DEFAULT, "face:%(font)s,fore:#000000,face:%(font)s,size:%(size)d" % faces)
190 # Comment
191 self.StyleSetSpec(wx.stc.STC_H_COMMENT, "face:%(font)s,fore:#007F00,italic,face:%(font)s,size:%(size)d" % faces)
192 # Number
193 self.StyleSetSpec(wx.stc.STC_H_NUMBER, "face:%(font)s,fore:#007F7F,size:%(size)d" % faces)
194 # String
195 self.StyleSetSpec(wx.stc.STC_H_SINGLESTRING, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces)
196 self.StyleSetSpec(wx.stc.STC_H_DOUBLESTRING, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces)
197 # Tag
198 self.StyleSetSpec(wx.stc.STC_H_TAG, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces)
199 # Attributes
200 self.StyleSetSpec(wx.stc.STC_H_ATTRIBUTE, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces)
201
202
203 # PHP Styles
204 self.StyleSetSpec(wx.stc.STC_HPHP_DEFAULT, "face:%(font)s,fore:#000000,face:%(font)s,size:%(size)d" % faces)
205 self.StyleSetSpec(wx.stc.STC_HPHP_COMMENT, "face:%(font)s,fore:#007F00,italic,face:%(font)s,size:%(size)d" % faces)
206 self.StyleSetSpec(wx.stc.STC_HPHP_COMMENTLINE, "face:%(font)s,fore:#007F00,italic,face:%(font)s,size:%(size)d" % faces)
207 self.StyleSetSpec(wx.stc.STC_HPHP_NUMBER, "face:%(font)s,fore:#007F7F,size:%(size)d" % faces)
208 self.StyleSetSpec(wx.stc.STC_HPHP_SIMPLESTRING, "face:%(font)s,fore:#7F007F,size:%(size)d" % faces)
209 self.StyleSetSpec(wx.stc.STC_HPHP_HSTRING, "face:%(font)s,fore7F007F,face:%(font)s,size:%(size)d" % faces)
210 self.StyleSetSpec(wx.stc.STC_HPHP_HSTRING_VARIABLE, "face:%(font)s,fore:#007F7F,italic,bold,face:%(font)s,size:%(size)d" % faces)
211 self.StyleSetSpec(wx.stc.STC_HPHP_VARIABLE, "face:%(font)s,fore:#000000,face:%(font)s,size:%(size)d" % faces)
212 self.StyleSetSpec(wx.stc.STC_HPHP_OPERATOR, "face:%(font)s,size:%(size)d" % faces)
213 self.StyleSetSpec(wx.stc.STC_HPHP_WORD, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces) # keyword
214
215
216 class PHPOptionsPanel(STCTextEditor.TextOptionsPanel):
217
218 def __init__(self, parent, id):
219 STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "PHP", label = "PHP", hasWordWrap = True, hasTabs = True)
220
221
222 PHPKEYWORDS = [
223 "and", "or", "xor", "__FILE__", "exception", "__LINE__", "array", "as", "break", "case",
224 "class", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif",
225 "empty", "enddeclare", "endfor", "endforeach", "endif", "endswith", "endwhile", "eval",
226 "exit", "extends", "for", "foreach", "function", "global", "if", "include", "include_once",
227 "isset", "list", "new", "print", "require", "require_once", "return", "static", "switch",
228 "unset", "use", "var", "while", "__FUNCTION__", "__CLASS__", "__METHOD__", "final", "php_user_filter",
229 "interface", "implements", "extends", "public", "private", "protected", "abstract", "clone", "try", "catch",
230 "throw", "cfunction", "old_function",
231 "$_SERVER", "$_ENV", "$_COOKIE", "$_GET", "$_POST", "$_FILES", "$_REQUEST", "$_SESSION", "$GLOBALS", "$php_errormsg",
232 "PHP_VERSION", "PHP_OS", "PHP_EOL", "DEFAULT_INCLUDE_PATH", "PEAR_INSTALL_DIR", "PEAR_EXTENSION_DIR",
233 "PHP_EXTENSION_DIR", "PHP_BINDIR", "PHP_LIBDIR", "PHP_DATADIR", "PHP_SYSCONFDIR", "PHP_LOCALSTATEDIR",
234 "PHP_CONFIG_FILE_PATH", "PHP_OUTPUT_HANDLER_START", "PHP_OUTPUT_HANDLER_CONT", "PHP_OUTPUT_HANDLER_END",
235 "E_ERROR", "E_WARNING", "E_PARSE", "E_NOTICE", "E_CORE_ERROR", "E_CORE_WARNING", "E_COMPILE_ERROR",
236 "E_COMPILE_WARNING", "E_USER_ERROR", "E_USER_WARNING", "E_USER_NOTICE", "E_ALL", "E_STRICT",
237 "TRUE", "FALSE", "NULL", "ZEND_THREAD_SAFE",
238 "EXTR_OVERWRITE", "EXTR_SKIP", "EXTR_PREFIX_SAME", "EXTR_PREFIX_ALL", "EXTR_PREFIX_INVALID",
239 "EXTR_PREFIX_IF_EXISTS", "EXTR_IF_EXISTS", "SORT_ASC", "SORT_DESC", "SORT_REGULAR", "SORT_NUMERIC",
240 "SORT_STRING", "CASE_LOWER", "CASE_UPPER", "COUNT_NORMAL", "COUNT_RECURSIVE", "ASSERT_ACTIVE",
241 "ASSERT_CALLBACK", "ASSERT_BAIL", "ASSERT_WARNING", "ASSERT_QUIET_EVAL", "CONNECTION_ABORTED",
242 "CONNECTION_NORMAL", "CONNECTION_TIMEOUT", "INI_USER", "INI_PERDIR", "INI_SYSTEM", "INI_ALL",
243 "M_E", "M_LOG2E", "M_LOG10E", "M_LN2", "M_LN10", "M_PI", "M_PI_2", "M_PI_4", "M_1_PI", "M_2_PI",
244 "M_2_SQRTPI", "M_SQRT2", "M_SQRT1_2", "CRYPT_SALT_LENGTH", "CRYPT_STD_DES", "CRYPT_EXT_DES", "CRYPT_MD5",
245 "CRYPT_BLOWFISH", "DIRECTORY_SEPARATOR", "SEEK_SET", "SEEK_CUR", "SEEK_END", "LOCK_SH", "LOCK_EX", "LOCK_UN",
246 "LOCK_NB", "HTML_SPECIALCHARS", "HTML_ENTITIES", "ENT_COMPAT", "ENT_QUOTES", "ENT_NOQUOTES", "INFO_GENERAL",
247 "INFO_CREDITS", "INFO_CONFIGURATION", "INFO_MODULES", "INFO_ENVIRONMENT", "INFO_VARIABLES", "INFO_LICENSE",
248 "INFO_ALL", "CREDITS_GROUP", "CREDITS_GENERAL", "CREDITS_SAPI", "CREDITS_MODULES", "CREDITS_DOCS",
249 "CREDITS_FULLPAGE", "CREDITS_QA", "CREDITS_ALL", "STR_PAD_LEFT", "STR_PAD_RIGHT", "STR_PAD_BOTH",
250 "PATHINFO_DIRNAME", "PATHINFO_BASENAME", "PATHINFO_EXTENSION", "PATH_SEPARATOR", "CHAR_MAX", "LC_CTYPE",
251 "LC_NUMERIC", "LC_TIME", "LC_COLLATE", "LC_MONETARY", "LC_ALL", "LC_MESSAGES", "ABDAY_1", "ABDAY_2",
252 "ABDAY_3", "ABDAY_4", "ABDAY_5", "ABDAY_6", "ABDAY_7", "DAY_1", "DAY_2", "DAY_3", "DAY_4", "DAY_5",
253 "DAY_6", "DAY_7", "ABMON_1", "ABMON_2", "ABMON_3", "ABMON_4", "ABMON_5", "ABMON_6", "ABMON_7", "ABMON_8",
254 "ABMON_9", "ABMON_10", "ABMON_11", "ABMON_12", "MON_1", "MON_2", "MON_3", "MON_4", "MON_5", "MON_6", "MON_7",
255 "MON_8", "MON_9", "MON_10", "MON_11", "MON_12", "AM_STR", "PM_STR", "D_T_FMT", "D_FMT", "T_FMT", "T_FMT_AMPM",
256 "ERA", "ERA_YEAR", "ERA_D_T_FMT", "ERA_D_FMT", "ERA_T_FMT", "ALT_DIGITS", "INT_CURR_SYMBOL", "CURRENCY_SYMBOL",
257 "CRNCYSTR", "MON_DECIMAL_POINT", "MON_THOUSANDS_SEP", "MON_GROUPING", "POSITIVE_SIGN", "NEGATIVE_SIGN",
258 "INT_FRAC_DIGITS", "FRAC_DIGITS", "P_CS_PRECEDES", "P_SEP_BY_SPACE", "N_CS_PRECEDES", "N_SEP_BY_SPACE",
259 "P_SIGN_POSN", "N_SIGN_POSN", "DECIMAL_POINT", "RADIXCHAR", "THOUSANDS_SEP", "THOUSEP", "GROUPING",
260 "YESEXPR", "NOEXPR", "YESSTR", "NOSTR", "CODESET", "LOG_EMERG", "LOG_ALERT", "LOG_CRIT", "LOG_ERR",
261 "LOG_WARNING", "LOG_NOTICE", "LOG_INFO", "LOG_DEBUG", "LOG_KERN", "LOG_USER", "LOG_MAIL", "LOG_DAEMON",
262 "LOG_AUTH", "LOG_SYSLOG", "LOG_LPR", "LOG_NEWS", "LOG_UUCP", "LOG_CRON", "LOG_AUTHPRIV", "LOG_LOCAL0",
263 "LOG_LOCAL1", "LOG_LOCAL2", "LOG_LOCAL3", "LOG_LOCAL4", "LOG_LOCAL5", "LOG_LOCAL6", "LOG_LOCAL7",
264 "LOG_PID", "LOG_CONS", "LOG_ODELAY", "LOG_NDELAY", "LOG_NOWAIT", "LOG_PERROR"
265 ]
266
267
268 #----------------------------------------------------------------------------
269 # Icon Bitmaps - generated by encode_bitmaps.py
270 #----------------------------------------------------------------------------
271 from wx import ImageFromStream, BitmapFromImage
272 import cStringIO
273
274
275 def getPHPData():
276 return \
277 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
278 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
279 \x00\x00{IDAT8\x8dclh8\xf0\x9f\x81\x02\xc0D\x89f\xaa\x18\xc0\x82M0<\\\x1c\
280 \xce^\xb9\xf2%y.\xd0\xd4\xd4$\xde\x05\xf8l\x0c\x0f\x17\x87\x8baS\xc7x\xfd\
281 \xfa\xf5\xff\xc8\xb6]\xbf~\x1d\xc3\x05\xf8\xc4\x98\x90\x05\xae_\xbf\x8e\xa1\
282 \x88\x90\xd8 \x8aF\x98\x93`~\xc3\x05\xd0\xd5\xc1\r\x80\t\xc0B\xf7\xfa\xf5\
283 \xeb(l\\\xeaP\xbc\x80\x1c\x85\xb8\xd8\xe8|&b\x9c\x8dn;2`\x1c\xf0\xdc\x08\x00\
284 \x8e\xf2S\xed\xb0\xbe\xaa\xbc\x00\x00\x00\x00IEND\xaeB`\x82'
285
286 def getPHPBitmap():
287 return BitmapFromImage(getPHPImage())
288
289 def getPHPImage():
290 stream = cStringIO.StringIO(getPHPData())
291 return ImageFromStream(stream)
292
293 def getPHPIcon():
294 return wx.IconFromBitmap(getPHPBitmap())