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

@@ -1,10 +1,77 @@
PLEASE NOTE: This is experimental code. It needs an overhall in the
drawing and update code, and there is occasionally a
mysteriously disappearing line...
wxEditor component
------------------
I am working on a StyledTextEditor that will likely
render this editor obsolete... But this one is at
least somewhat functional now while the other is still
vapor.
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.
- 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.
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