This commit was manufactured by cvs2svn to create tag
'DEBIAN_2_4_3_1_SARGE_v_2_4_2_4'. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/tags/DEBIAN_2_4_3_1_SARGE_v_2_4_2_4@34395 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,3 @@
|
||||
.DS_Store
|
||||
build
|
||||
dist
|
||||
|
@@ -6,11 +6,11 @@ can do simple drawings upon.
|
||||
"""
|
||||
|
||||
|
||||
from wxPython.wx import *
|
||||
import wx # This module uses the new wx namespace
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
class DoodleWindow(wxWindow):
|
||||
class DoodleWindow(wx.Window):
|
||||
menuColours = { 100 : 'Black',
|
||||
101 : 'Yellow',
|
||||
102 : 'Red',
|
||||
@@ -32,7 +32,7 @@ class DoodleWindow(wxWindow):
|
||||
|
||||
|
||||
def __init__(self, parent, ID):
|
||||
wxWindow.__init__(self, parent, ID, style=wxNO_FULL_REPAINT_ON_RESIZE)
|
||||
wx.Window.__init__(self, parent, ID, style=wx.NO_FULL_REPAINT_ON_RESIZE)
|
||||
self.SetBackgroundColour("WHITE")
|
||||
self.listeners = []
|
||||
self.thickness = 1
|
||||
@@ -44,20 +44,20 @@ class DoodleWindow(wxWindow):
|
||||
self.InitBuffer()
|
||||
|
||||
# hook some mouse events
|
||||
EVT_LEFT_DOWN(self, self.OnLeftDown)
|
||||
EVT_LEFT_UP(self, self.OnLeftUp)
|
||||
EVT_RIGHT_UP(self, self.OnRightUp)
|
||||
EVT_MOTION(self, self.OnMotion)
|
||||
wx.EVT_LEFT_DOWN(self, self.OnLeftDown)
|
||||
wx.EVT_LEFT_UP(self, self.OnLeftUp)
|
||||
wx.EVT_RIGHT_UP(self, self.OnRightUp)
|
||||
wx.EVT_MOTION(self, self.OnMotion)
|
||||
|
||||
# the window resize event and idle events for managing the buffer
|
||||
EVT_SIZE(self, self.OnSize)
|
||||
EVT_IDLE(self, self.OnIdle)
|
||||
wx.EVT_SIZE(self, self.OnSize)
|
||||
wx.EVT_IDLE(self, self.OnIdle)
|
||||
|
||||
# and the refresh event
|
||||
EVT_PAINT(self, self.OnPaint)
|
||||
wx.EVT_PAINT(self, self.OnPaint)
|
||||
|
||||
# When the window is destroyed, clean up resources.
|
||||
EVT_WINDOW_DESTROY(self, self.Cleanup)
|
||||
wx.EVT_WINDOW_DESTROY(self, self.Cleanup)
|
||||
|
||||
|
||||
def Cleanup(self, evt):
|
||||
@@ -69,25 +69,25 @@ class DoodleWindow(wxWindow):
|
||||
def InitBuffer(self):
|
||||
"""Initialize the bitmap used for buffering the display."""
|
||||
size = self.GetClientSize()
|
||||
self.buffer = wxEmptyBitmap(size.width, size.height)
|
||||
dc = wxBufferedDC(None, self.buffer)
|
||||
dc.SetBackground(wxBrush(self.GetBackgroundColour()))
|
||||
self.buffer = wx.EmptyBitmap(size.width, size.height)
|
||||
dc = wx.BufferedDC(None, self.buffer)
|
||||
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
|
||||
dc.Clear()
|
||||
self.DrawLines(dc)
|
||||
self.reInitBuffer = false
|
||||
self.reInitBuffer = False
|
||||
|
||||
|
||||
def SetColour(self, colour):
|
||||
"""Set a new colour and make a matching pen"""
|
||||
self.colour = colour
|
||||
self.pen = wxPen(wxNamedColour(self.colour), self.thickness, wxSOLID)
|
||||
self.pen = wx.Pen(self.colour, self.thickness, wx.SOLID)
|
||||
self.Notify()
|
||||
|
||||
|
||||
def SetThickness(self, num):
|
||||
"""Set a new line thickness and make a matching pen"""
|
||||
self.thickness = num
|
||||
self.pen = wxPen(wxNamedColour(self.colour), self.thickness, wxSOLID)
|
||||
self.pen = wx.Pen(self.colour, self.thickness, wx.SOLID)
|
||||
self.Notify()
|
||||
|
||||
|
||||
@@ -103,20 +103,20 @@ class DoodleWindow(wxWindow):
|
||||
|
||||
def MakeMenu(self):
|
||||
"""Make a menu that can be popped up later"""
|
||||
menu = wxMenu()
|
||||
menu = wx.Menu()
|
||||
keys = self.menuColours.keys()
|
||||
keys.sort()
|
||||
for k in keys:
|
||||
text = self.menuColours[k]
|
||||
menu.Append(k, text, kind=wxITEM_CHECK)
|
||||
EVT_MENU_RANGE(self, 100, 200, self.OnMenuSetColour)
|
||||
EVT_UPDATE_UI_RANGE(self, 100, 200, self.OnCheckMenuColours)
|
||||
menu.Append(k, text, kind=wx.ITEM_CHECK)
|
||||
wx.EVT_MENU_RANGE(self, 100, 200, self.OnMenuSetColour)
|
||||
wx.EVT_UPDATE_UI_RANGE(self, 100, 200, self.OnCheckMenuColours)
|
||||
menu.Break()
|
||||
|
||||
for x in range(1, self.maxThickness+1):
|
||||
menu.Append(x, str(x), kind=wxITEM_CHECK)
|
||||
EVT_MENU_RANGE(self, 1, self.maxThickness, self.OnMenuSetThickness)
|
||||
EVT_UPDATE_UI_RANGE(self, 1, self.maxThickness, self.OnCheckMenuThickness)
|
||||
menu.Append(x, str(x), kind=wx.ITEM_CHECK)
|
||||
wx.EVT_MENU_RANGE(self, 1, self.maxThickness, self.OnMenuSetThickness)
|
||||
wx.EVT_UPDATE_UI_RANGE(self, 1, self.maxThickness, self.OnCheckMenuThickness)
|
||||
self.menu = menu
|
||||
|
||||
|
||||
@@ -125,14 +125,17 @@ class DoodleWindow(wxWindow):
|
||||
def OnCheckMenuColours(self, event):
|
||||
text = self.menuColours[event.GetId()]
|
||||
if text == self.colour:
|
||||
event.Check(true)
|
||||
event.Check(True)
|
||||
event.SetText(text.upper())
|
||||
else:
|
||||
event.Check(false)
|
||||
event.Check(False)
|
||||
event.SetText(text)
|
||||
|
||||
def OnCheckMenuThickness(self, event):
|
||||
if event.GetId() == self.thickness:
|
||||
event.Check(true)
|
||||
event.Check(True)
|
||||
else:
|
||||
event.Check(false)
|
||||
event.Check(False)
|
||||
|
||||
|
||||
def OnLeftDown(self, event):
|
||||
@@ -164,7 +167,7 @@ class DoodleWindow(wxWindow):
|
||||
current one. Save the coordinants for redraws.
|
||||
"""
|
||||
if event.Dragging() and event.LeftIsDown():
|
||||
dc = wxBufferedDC(wxClientDC(self), self.buffer)
|
||||
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
|
||||
dc.BeginDrawing()
|
||||
dc.SetPen(self.pen)
|
||||
pos = event.GetPositionTuple()
|
||||
@@ -180,7 +183,7 @@ class DoodleWindow(wxWindow):
|
||||
Called when the window is resized. We set a flag so the idle
|
||||
handler will resize the buffer.
|
||||
"""
|
||||
self.reInitBuffer = true
|
||||
self.reInitBuffer = True
|
||||
|
||||
|
||||
def OnIdle(self, event):
|
||||
@@ -192,7 +195,7 @@ class DoodleWindow(wxWindow):
|
||||
"""
|
||||
if self.reInitBuffer:
|
||||
self.InitBuffer()
|
||||
self.Refresh(FALSE)
|
||||
self.Refresh(False)
|
||||
|
||||
|
||||
def OnPaint(self, event):
|
||||
@@ -200,10 +203,10 @@ class DoodleWindow(wxWindow):
|
||||
Called when the window is exposed.
|
||||
"""
|
||||
# Create a buffered paint DC. It will create the real
|
||||
# wxPaintDC and then blit the bitmap to it when dc is
|
||||
# wx.PaintDC and then blit the bitmap to it when dc is
|
||||
# deleted. Since we don't need to draw anything else
|
||||
# here that's all there is to it.
|
||||
dc = wxBufferedPaintDC(self, self.buffer)
|
||||
dc = wx.BufferedPaintDC(self, self.buffer)
|
||||
|
||||
|
||||
def DrawLines(self, dc):
|
||||
@@ -212,7 +215,7 @@ class DoodleWindow(wxWindow):
|
||||
"""
|
||||
dc.BeginDrawing()
|
||||
for colour, thickness, line in self.lines:
|
||||
pen = wxPen(wxNamedColour(colour), thickness, wxSOLID)
|
||||
pen = wx.Pen(colour, thickness, wx.SOLID)
|
||||
dc.SetPen(pen)
|
||||
for coords in line:
|
||||
apply(dc.DrawLine, coords)
|
||||
@@ -240,17 +243,17 @@ class DoodleWindow(wxWindow):
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
class DoodleFrame(wxFrame):
|
||||
class DoodleFrame(wx.Frame):
|
||||
def __init__(self, parent):
|
||||
wxFrame.__init__(self, parent, -1, "Doodle Frame", size=(800,600),
|
||||
style=wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
|
||||
wx.Frame.__init__(self, parent, -1, "Doodle Frame", size=(800,600),
|
||||
style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
|
||||
doodle = DoodleWindow(self, -1)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = wxPySimpleApp()
|
||||
app = wx.PySimpleApp()
|
||||
frame = DoodleFrame(None)
|
||||
frame.Show(true)
|
||||
frame.Show(True)
|
||||
app.MainLoop()
|
||||
|
||||
|
@@ -4008,4 +4008,261 @@ I472
|
||||
I599
|
||||
I473
|
||||
tatp56
|
||||
a(S'Red'
|
||||
p57
|
||||
I4
|
||||
(lp58
|
||||
(I503
|
||||
I412
|
||||
I503
|
||||
I411
|
||||
ta(I503
|
||||
I411
|
||||
I504
|
||||
I411
|
||||
ta(I504
|
||||
I411
|
||||
I504
|
||||
I410
|
||||
ta(I504
|
||||
I410
|
||||
I505
|
||||
I410
|
||||
ta(I505
|
||||
I410
|
||||
I505
|
||||
I409
|
||||
ta(I505
|
||||
I409
|
||||
I506
|
||||
I409
|
||||
ta(I506
|
||||
I409
|
||||
I507
|
||||
I409
|
||||
ta(I507
|
||||
I409
|
||||
I507
|
||||
I408
|
||||
ta(I507
|
||||
I408
|
||||
I508
|
||||
I408
|
||||
ta(I508
|
||||
I408
|
||||
I509
|
||||
I408
|
||||
ta(I509
|
||||
I408
|
||||
I510
|
||||
I408
|
||||
ta(I510
|
||||
I408
|
||||
I511
|
||||
I408
|
||||
ta(I511
|
||||
I408
|
||||
I511
|
||||
I409
|
||||
ta(I511
|
||||
I409
|
||||
I511
|
||||
I410
|
||||
ta(I511
|
||||
I410
|
||||
I512
|
||||
I410
|
||||
ta(I512
|
||||
I410
|
||||
I512
|
||||
I411
|
||||
ta(I512
|
||||
I411
|
||||
I512
|
||||
I412
|
||||
ta(I512
|
||||
I412
|
||||
I512
|
||||
I413
|
||||
ta(I512
|
||||
I413
|
||||
I512
|
||||
I414
|
||||
ta(I512
|
||||
I414
|
||||
I512
|
||||
I415
|
||||
ta(I512
|
||||
I415
|
||||
I511
|
||||
I415
|
||||
ta(I511
|
||||
I415
|
||||
I511
|
||||
I416
|
||||
ta(I511
|
||||
I416
|
||||
I510
|
||||
I416
|
||||
ta(I510
|
||||
I416
|
||||
I510
|
||||
I417
|
||||
ta(I510
|
||||
I417
|
||||
I509
|
||||
I417
|
||||
ta(I509
|
||||
I417
|
||||
I508
|
||||
I418
|
||||
ta(I508
|
||||
I418
|
||||
I508
|
||||
I419
|
||||
ta(I508
|
||||
I419
|
||||
I507
|
||||
I420
|
||||
ta(I507
|
||||
I420
|
||||
I506
|
||||
I421
|
||||
ta(I506
|
||||
I421
|
||||
I505
|
||||
I421
|
||||
ta(I505
|
||||
I421
|
||||
I504
|
||||
I422
|
||||
ta(I504
|
||||
I422
|
||||
I503
|
||||
I423
|
||||
ta(I503
|
||||
I423
|
||||
I503
|
||||
I424
|
||||
ta(I503
|
||||
I424
|
||||
I502
|
||||
I425
|
||||
ta(I502
|
||||
I425
|
||||
I502
|
||||
I426
|
||||
tatp59
|
||||
a(g57
|
||||
I4
|
||||
(lp60
|
||||
(I503
|
||||
I414
|
||||
I502
|
||||
I414
|
||||
ta(I502
|
||||
I414
|
||||
I502
|
||||
I413
|
||||
ta(I502
|
||||
I413
|
||||
I501
|
||||
I413
|
||||
ta(I501
|
||||
I413
|
||||
I499
|
||||
I412
|
||||
ta(I499
|
||||
I412
|
||||
I498
|
||||
I412
|
||||
ta(I498
|
||||
I412
|
||||
I497
|
||||
I412
|
||||
ta(I497
|
||||
I412
|
||||
I496
|
||||
I412
|
||||
ta(I496
|
||||
I412
|
||||
I495
|
||||
I412
|
||||
ta(I495
|
||||
I412
|
||||
I494
|
||||
I412
|
||||
ta(I494
|
||||
I412
|
||||
I493
|
||||
I413
|
||||
ta(I493
|
||||
I413
|
||||
I493
|
||||
I414
|
||||
ta(I493
|
||||
I414
|
||||
I493
|
||||
I415
|
||||
ta(I493
|
||||
I415
|
||||
I493
|
||||
I416
|
||||
ta(I493
|
||||
I416
|
||||
I493
|
||||
I417
|
||||
ta(I493
|
||||
I417
|
||||
I493
|
||||
I418
|
||||
ta(I493
|
||||
I418
|
||||
I493
|
||||
I419
|
||||
ta(I493
|
||||
I419
|
||||
I493
|
||||
I420
|
||||
ta(I493
|
||||
I420
|
||||
I494
|
||||
I421
|
||||
ta(I494
|
||||
I421
|
||||
I495
|
||||
I422
|
||||
ta(I495
|
||||
I422
|
||||
I496
|
||||
I422
|
||||
ta(I496
|
||||
I422
|
||||
I497
|
||||
I423
|
||||
ta(I497
|
||||
I423
|
||||
I498
|
||||
I423
|
||||
ta(I498
|
||||
I423
|
||||
I498
|
||||
I424
|
||||
ta(I498
|
||||
I424
|
||||
I499
|
||||
I424
|
||||
ta(I499
|
||||
I424
|
||||
I500
|
||||
I424
|
||||
ta(I500
|
||||
I424
|
||||
I500
|
||||
I425
|
||||
ta(I500
|
||||
I425
|
||||
I501
|
||||
I425
|
||||
tatp61
|
||||
a.
|
@@ -7,10 +7,12 @@ intelligent Frame. This one has a menu and a statusbar, is able to
|
||||
save and reload doodles, clear the workspace, and has a simple control
|
||||
panel for setting color and line thickness in addition to the popup
|
||||
menu that DoodleWindow provides. There is also a nice About dialog
|
||||
implmented using an wxHtmlWindow.
|
||||
implmented using an wx.html.HtmlWindow.
|
||||
"""
|
||||
|
||||
from wxPython.wx import *
|
||||
import wx # This module uses the new wx namespace
|
||||
import wx.html
|
||||
from wx.lib import buttons # for generic button classes
|
||||
from doodle import DoodleWindow
|
||||
|
||||
import os, cPickle
|
||||
@@ -18,25 +20,28 @@ import os, cPickle
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
idNEW = 11001
|
||||
idOPEN = 11002
|
||||
idSAVE = 11003
|
||||
idSAVEAS = 11004
|
||||
idCLEAR = 11005
|
||||
idEXIT = 11006
|
||||
idABOUT = 11007
|
||||
wx.RegisterId(5000) # Give a high starting value for the IDs, just for kicks
|
||||
|
||||
idNEW = wx.NewId()
|
||||
idOPEN = wx.NewId()
|
||||
idSAVE = wx.NewId()
|
||||
idSAVEAS = wx.NewId()
|
||||
idCLEAR = wx.NewId()
|
||||
idEXIT = wx.NewId()
|
||||
idABOUT = wx.NewId()
|
||||
|
||||
|
||||
class DoodleFrame(wxFrame):
|
||||
|
||||
class DoodleFrame(wx.Frame):
|
||||
"""
|
||||
A DoodleFrame contains a DoodleWindow and a ControlPanel and manages
|
||||
their layout with a wxBoxSizer. A menu and associated event handlers
|
||||
their layout with a wx.BoxSizer. A menu and associated event handlers
|
||||
provides for saving a doodle to a file, etc.
|
||||
"""
|
||||
title = "Do a doodle"
|
||||
def __init__(self, parent):
|
||||
wxFrame.__init__(self, parent, -1, self.title, size=(800,600),
|
||||
style=wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
|
||||
wx.Frame.__init__(self, parent, -1, self.title, size=(800,600),
|
||||
style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
|
||||
self.CreateStatusBar()
|
||||
self.MakeMenu()
|
||||
self.filename = None
|
||||
@@ -47,13 +52,13 @@ class DoodleFrame(wxFrame):
|
||||
# Create a sizer to layout the two windows side-by-side.
|
||||
# Both will grow vertically, the doodle window will grow
|
||||
# horizontally as well.
|
||||
box = wxBoxSizer(wxHORIZONTAL)
|
||||
box.Add(cPanel, 0, wxEXPAND)
|
||||
box.Add(self.doodle, 1, wxEXPAND)
|
||||
box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
box.Add(cPanel, 0, wx.EXPAND)
|
||||
box.Add(self.doodle, 1, wx.EXPAND)
|
||||
|
||||
# Tell the frame that it should layout itself in response to
|
||||
# size events.
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(box)
|
||||
|
||||
|
||||
@@ -73,15 +78,19 @@ class DoodleFrame(wxFrame):
|
||||
f.close()
|
||||
self.doodle.SetLinesData(data)
|
||||
except cPickle.UnpicklingError:
|
||||
wxMessageBox("%s is not a doodle file." % self.filename,
|
||||
"oops!", style=wxOK|wxICON_EXCLAMATION)
|
||||
wx.MessageBox("%s is not a doodle file." % self.filename,
|
||||
"oops!", style=wx.OK|wx.ICON_EXCLAMATION)
|
||||
|
||||
|
||||
def MakeMenu(self):
|
||||
# create the file menu
|
||||
menu1 = wxMenu()
|
||||
menu1.Append(idOPEN, "&Open", "Open a doodle file")
|
||||
menu1.Append(idSAVE, "&Save", "Save the doodle")
|
||||
menu1 = wx.Menu()
|
||||
|
||||
# Using the "\tKeyName" syntax automatically creates a
|
||||
# wx.AcceleratorTable for this frame and binds the keys to
|
||||
# the menu items.
|
||||
menu1.Append(idOPEN, "&Open\tCtrl-O", "Open a doodle file")
|
||||
menu1.Append(idSAVE, "&Save\tCtrl-S", "Save the doodle")
|
||||
menu1.Append(idSAVEAS, "Save &As", "Save the doodle in a new file")
|
||||
menu1.AppendSeparator()
|
||||
menu1.Append(idCLEAR, "&Clear", "Clear the current doodle")
|
||||
@@ -89,30 +98,30 @@ class DoodleFrame(wxFrame):
|
||||
menu1.Append(idEXIT, "E&xit", "Terminate the application")
|
||||
|
||||
# and the help menu
|
||||
menu2 = wxMenu()
|
||||
menu2.Append(idABOUT, "&About", "Display the gratuitous 'about this app' thingamajig")
|
||||
menu2 = wx.Menu()
|
||||
menu2.Append(idABOUT, "&About\tCtrl-H", "Display the gratuitous 'about this app' thingamajig")
|
||||
|
||||
# and add them to a menubar
|
||||
menuBar = wxMenuBar()
|
||||
menuBar = wx.MenuBar()
|
||||
menuBar.Append(menu1, "&File")
|
||||
menuBar.Append(menu2, "&Help")
|
||||
self.SetMenuBar(menuBar)
|
||||
|
||||
EVT_MENU(self, idOPEN, self.OnMenuOpen)
|
||||
EVT_MENU(self, idSAVE, self.OnMenuSave)
|
||||
EVT_MENU(self, idSAVEAS, self.OnMenuSaveAs)
|
||||
EVT_MENU(self, idCLEAR, self.OnMenuClear)
|
||||
EVT_MENU(self, idEXIT, self.OnMenuExit)
|
||||
EVT_MENU(self, idABOUT, self.OnMenuAbout)
|
||||
wx.EVT_MENU(self, idOPEN, self.OnMenuOpen)
|
||||
wx.EVT_MENU(self, idSAVE, self.OnMenuSave)
|
||||
wx.EVT_MENU(self, idSAVEAS, self.OnMenuSaveAs)
|
||||
wx.EVT_MENU(self, idCLEAR, self.OnMenuClear)
|
||||
wx.EVT_MENU(self, idEXIT, self.OnMenuExit)
|
||||
wx.EVT_MENU(self, idABOUT, self.OnMenuAbout)
|
||||
|
||||
|
||||
|
||||
wildcard = "Doodle files (*.ddl)|*.ddl|All files (*.*)|*.*"
|
||||
|
||||
def OnMenuOpen(self, event):
|
||||
dlg = wxFileDialog(self, "Open doodle file...", os.getcwd(),
|
||||
style=wxOPEN, wildcard = self.wildcard)
|
||||
if dlg.ShowModal() == wxID_OK:
|
||||
dlg = wx.FileDialog(self, "Open doodle file...", os.getcwd(),
|
||||
style=wx.OPEN, wildcard = self.wildcard)
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
self.filename = dlg.GetPath()
|
||||
self.ReadFile()
|
||||
self.SetTitle(self.title + ' -- ' + self.filename)
|
||||
@@ -127,10 +136,10 @@ class DoodleFrame(wxFrame):
|
||||
|
||||
|
||||
def OnMenuSaveAs(self, event):
|
||||
dlg = wxFileDialog(self, "Save doodle as...", os.getcwd(),
|
||||
style=wxSAVE | wxOVERWRITE_PROMPT,
|
||||
dlg = wx.FileDialog(self, "Save doodle as...", os.getcwd(),
|
||||
style=wx.SAVE | wx.OVERWRITE_PROMPT,
|
||||
wildcard = self.wildcard)
|
||||
if dlg.ShowModal() == wxID_OK:
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
filename = dlg.GetPath()
|
||||
if not os.path.splitext(filename)[1]:
|
||||
filename = filename + '.ddl'
|
||||
@@ -159,7 +168,7 @@ class DoodleFrame(wxFrame):
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
class ControlPanel(wxPanel):
|
||||
class ControlPanel(wx.Panel):
|
||||
"""
|
||||
This class implements a very simple control panel for the DoodleWindow.
|
||||
It creates buttons for each of the colours and thickneses supported by
|
||||
@@ -167,36 +176,51 @@ class ControlPanel(wxPanel):
|
||||
also a little window that shows an example doodleLine in the selected
|
||||
values. Nested sizers are used for layout.
|
||||
"""
|
||||
|
||||
BMP_SIZE = 16
|
||||
BMP_BORDER = 3
|
||||
|
||||
def __init__(self, parent, ID, doodle):
|
||||
wxPanel.__init__(self, parent, ID, style=wxRAISED_BORDER)
|
||||
wx.Panel.__init__(self, parent, ID, style=wx.RAISED_BORDER)
|
||||
|
||||
numCols = 4
|
||||
spacing = 4
|
||||
|
||||
btnSize = wx.Size(self.BMP_SIZE + 2*self.BMP_BORDER,
|
||||
self.BMP_SIZE + 2*self.BMP_BORDER)
|
||||
|
||||
# Make a grid of buttons for each colour. Attach each button
|
||||
# event to self.OnSetColour. The button ID is the same as the
|
||||
# key in the colour dictionary.
|
||||
self.clrBtns = {}
|
||||
colours = doodle.menuColours
|
||||
keys = colours.keys()
|
||||
keys.sort()
|
||||
cGrid = wxGridSizer(cols=numCols, hgap=2, vgap=2)
|
||||
cGrid = wx.GridSizer(cols=numCols, hgap=2, vgap=2)
|
||||
for k in keys:
|
||||
bmp = self.MakeBitmap(wxNamedColour(colours[k]))
|
||||
b = wxBitmapButton(self, k, bmp)
|
||||
EVT_BUTTON(self, k, self.OnSetColour)
|
||||
bmp = self.MakeBitmap(colours[k])
|
||||
b = buttons.GenBitmapToggleButton(self, k, bmp, size=btnSize )
|
||||
b.SetBezelWidth(1)
|
||||
b.SetUseFocusIndicator(False)
|
||||
wx.EVT_BUTTON(self, k, self.OnSetColour)
|
||||
cGrid.Add(b, 0)
|
||||
self.clrBtns[colours[k]] = b
|
||||
self.clrBtns[colours[keys[0]]].SetToggle(True)
|
||||
|
||||
# Save the button size so we can use it for the number buttons
|
||||
btnSize = b.GetSize()
|
||||
|
||||
# Make a grid of buttons for the thicknesses. Attach each button
|
||||
# event to self.OnSetThickness. The button ID is the same as the
|
||||
# thickness value.
|
||||
tGrid = wxGridSizer(cols=numCols, hgap=2, vgap=2)
|
||||
self.thknsBtns = {}
|
||||
tGrid = wx.GridSizer(cols=numCols, hgap=2, vgap=2)
|
||||
for x in range(1, doodle.maxThickness+1):
|
||||
b = wxButton(self, x, str(x), size=btnSize)
|
||||
EVT_BUTTON(self, x, self.OnSetThickness)
|
||||
b = buttons.GenToggleButton(self, x, str(x), size=btnSize)
|
||||
b.SetBezelWidth(1)
|
||||
b.SetUseFocusIndicator(False)
|
||||
wx.EVT_BUTTON(self, x, self.OnSetThickness)
|
||||
tGrid.Add(b, 0)
|
||||
self.thknsBtns[x] = b
|
||||
self.thknsBtns[1].SetToggle(True)
|
||||
|
||||
# Make a colour indicator window, it is registerd as a listener
|
||||
# with the doodle window so it will be notified when the settings
|
||||
@@ -208,12 +232,12 @@ class ControlPanel(wxPanel):
|
||||
|
||||
# Make a box sizer and put the two grids and the indicator
|
||||
# window in it.
|
||||
box = wxBoxSizer(wxVERTICAL)
|
||||
box.Add(cGrid, 0, wxALL, spacing)
|
||||
box.Add(tGrid, 0, wxALL, spacing)
|
||||
box.Add(ci, 0, wxEXPAND|wxALL, spacing)
|
||||
box = wx.BoxSizer(wx.VERTICAL)
|
||||
box.Add(cGrid, 0, wx.ALL, spacing)
|
||||
box.Add(tGrid, 0, wx.ALL, spacing)
|
||||
box.Add(ci, 0, wx.EXPAND|wx.ALL, spacing)
|
||||
self.SetSizer(box)
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
|
||||
# Resize this window so it is just large enough for the
|
||||
# minimum requirements of the sizer.
|
||||
@@ -224,15 +248,15 @@ class ControlPanel(wxPanel):
|
||||
def MakeBitmap(self, colour):
|
||||
"""
|
||||
We can create a bitmap of whatever we want by simply selecting
|
||||
it into a wxMemoryDC and drawing on it. In this case we just set
|
||||
it into a wx.MemoryDC and drawing on it. In this case we just set
|
||||
a background brush and clear the dc.
|
||||
"""
|
||||
bmp = wxEmptyBitmap(16,16)
|
||||
dc = wxMemoryDC()
|
||||
bmp = wx.EmptyBitmap(self.BMP_SIZE, self.BMP_SIZE)
|
||||
dc = wx.MemoryDC()
|
||||
dc.SelectObject(bmp)
|
||||
dc.SetBackground(wxBrush(colour))
|
||||
dc.SetBackground(wx.Brush(colour))
|
||||
dc.Clear()
|
||||
dc.SelectObject(wxNullBitmap)
|
||||
dc.SelectObject(wx.NullBitmap)
|
||||
return bmp
|
||||
|
||||
|
||||
@@ -241,6 +265,10 @@ class ControlPanel(wxPanel):
|
||||
Use the event ID to get the colour, set that colour in the doodle.
|
||||
"""
|
||||
colour = self.doodle.menuColours[event.GetId()]
|
||||
if colour != self.doodle.colour:
|
||||
# untoggle the old colour button
|
||||
self.clrBtns[self.doodle.colour].SetToggle(False)
|
||||
# set the new colour
|
||||
self.doodle.SetColour(colour)
|
||||
|
||||
|
||||
@@ -248,22 +276,28 @@ class ControlPanel(wxPanel):
|
||||
"""
|
||||
Use the event ID to set the thickness in the doodle.
|
||||
"""
|
||||
self.doodle.SetThickness(event.GetId())
|
||||
thickness = event.GetId()
|
||||
if thickness != self.doodle.thickness:
|
||||
# untoggle the old thickness button
|
||||
self.thknsBtns[self.doodle.thickness].SetToggle(False)
|
||||
# set the new colour
|
||||
self.doodle.SetThickness(thickness)
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
class ColourIndicator(wxWindow):
|
||||
class ColourIndicator(wx.Window):
|
||||
"""
|
||||
An instance of this class is used on the ControlPanel to show
|
||||
a sample of what the current doodle line will look like.
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
wxWindow.__init__(self, parent, -1, style=wxSUNKEN_BORDER)
|
||||
self.SetBackgroundColour(wxWHITE)
|
||||
self.SetSize(wxSize(-1, 45))
|
||||
wx.Window.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
|
||||
self.SetBackgroundColour(wx.WHITE)
|
||||
self.SetSize( (-1, 45) )
|
||||
self.colour = self.thickness = None
|
||||
EVT_PAINT(self, self.OnPaint)
|
||||
wx.EVT_PAINT(self, self.OnPaint)
|
||||
|
||||
|
||||
def Update(self, colour, thickness):
|
||||
@@ -281,10 +315,10 @@ class ColourIndicator(wxWindow):
|
||||
This method is called when all or part of the window needs to be
|
||||
redrawn.
|
||||
"""
|
||||
dc = wxPaintDC(self)
|
||||
dc = wx.PaintDC(self)
|
||||
if self.colour:
|
||||
sz = self.GetClientSize()
|
||||
pen = wxPen(wxNamedColour(self.colour), self.thickness)
|
||||
pen = wx.Pen(self.colour, self.thickness)
|
||||
dc.BeginDrawing()
|
||||
dc.SetPen(pen)
|
||||
dc.DrawLine(10, sz.height/2, sz.width-10, sz.height/2)
|
||||
@@ -293,7 +327,7 @@ class ColourIndicator(wxWindow):
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
class DoodleAbout(wxDialog):
|
||||
class DoodleAbout(wx.Dialog):
|
||||
""" An about box that uses an HTML window """
|
||||
|
||||
text = '''
|
||||
@@ -318,49 +352,48 @@ instructions: </p>
|
||||
|
||||
<p><b>SuperDoodle</b> and <b>wxPython</b> are brought to you by
|
||||
<b>Robin Dunn</b> and <b>Total Control Software</b>, Copyright
|
||||
© 1997-2001.</p>
|
||||
© 1997-2003.</p>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
def __init__(self, parent):
|
||||
wxDialog.__init__(self, parent, -1, 'About SuperDoodle',
|
||||
size=wxSize(420, 380))
|
||||
from wxPython.html import wxHtmlWindow
|
||||
wx.Dialog.__init__(self, parent, -1, 'About SuperDoodle',
|
||||
size=(420, 380) )
|
||||
|
||||
html = wxHtmlWindow(self, -1)
|
||||
html = wx.html.HtmlWindow(self, -1)
|
||||
html.SetPage(self.text)
|
||||
button = wxButton(self, wxID_OK, "Okay")
|
||||
button = wx.Button(self, wx.ID_OK, "Okay")
|
||||
|
||||
# constraints for the html window
|
||||
lc = wxLayoutConstraints()
|
||||
lc.top.SameAs(self, wxTop, 5)
|
||||
lc.left.SameAs(self, wxLeft, 5)
|
||||
lc.bottom.SameAs(button, wxTop, 5)
|
||||
lc.right.SameAs(self, wxRight, 5)
|
||||
lc = wx.LayoutConstraints()
|
||||
lc.top.SameAs(self, wx.Top, 5)
|
||||
lc.left.SameAs(self, wx.Left, 5)
|
||||
lc.bottom.SameAs(button, wx.Top, 5)
|
||||
lc.right.SameAs(self, wx.Right, 5)
|
||||
html.SetConstraints(lc)
|
||||
|
||||
# constraints for the button
|
||||
lc = wxLayoutConstraints()
|
||||
lc.bottom.SameAs(self, wxBottom, 5)
|
||||
lc.centreX.SameAs(self, wxCentreX)
|
||||
lc = wx.LayoutConstraints()
|
||||
lc.bottom.SameAs(self, wx.Bottom, 5)
|
||||
lc.centreX.SameAs(self, wx.CentreX)
|
||||
lc.width.AsIs()
|
||||
lc.height.AsIs()
|
||||
button.SetConstraints(lc)
|
||||
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.Layout()
|
||||
self.CentreOnParent(wxBOTH)
|
||||
self.CentreOnParent(wx.BOTH)
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
class DoodleApp(wxApp):
|
||||
class DoodleApp(wx.App):
|
||||
def OnInit(self):
|
||||
frame = DoodleFrame(None)
|
||||
frame.Show(true)
|
||||
frame.Show(True)
|
||||
self.SetTopWindow(frame)
|
||||
return true
|
||||
return True
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
@@ -42,7 +42,7 @@ public:
|
||||
virtual ~MyApp();
|
||||
void Init_wxPython();
|
||||
private:
|
||||
PyThreadState* main_tstate;
|
||||
PyThreadState* m_mainTState;
|
||||
};
|
||||
|
||||
|
||||
@@ -83,16 +83,22 @@ void MyApp::Init_wxPython()
|
||||
// module and sets a pointer to a function table located there.
|
||||
wxPyCoreAPI_IMPORT();
|
||||
|
||||
// Ensure that the new classes defined in the wxPython wrappers are
|
||||
// recognised by the wx RTTI system. (If you don't use wxWindows in
|
||||
// your C++ app you won't need to do this.)
|
||||
wxClassInfo::CleanUpClasses();
|
||||
wxClassInfo::InitializeClasses();
|
||||
|
||||
// Save the current Python thread state and release the
|
||||
// Global Interpreter Lock.
|
||||
main_tstate = wxPyBeginAllowThreads();
|
||||
m_mainTState = wxPyBeginAllowThreads();
|
||||
}
|
||||
|
||||
|
||||
MyApp::~MyApp()
|
||||
{
|
||||
// Restore the thread state and tell Python to cleanup after itself.
|
||||
wxPyEndAllowThreads(main_tstate);
|
||||
wxPyEndAllowThreads(m_mainTState);
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
@@ -167,7 +173,7 @@ void MyFrame::OnPyFrame(wxCommandEvent& event)
|
||||
// C++ code in any way, you can execute it with PyRun_SimpleString.
|
||||
|
||||
|
||||
// First, whenever you do anyting with Python objects or code, you
|
||||
// First, whenever you do anything with Python objects or code, you
|
||||
// *MUST* aquire the Global Interpreter Lock and block other
|
||||
// Python threads from running.
|
||||
wxPyBeginBlockThreads();
|
||||
|
@@ -12,8 +12,6 @@ from wxPython.wx import *
|
||||
from StatusBar import *
|
||||
from FrogEditor import FrogEditor
|
||||
|
||||
TRUE = 1
|
||||
FALSE = 0
|
||||
|
||||
ABOUT_TEXT = """FrogEdit : Copyright 2001 Adam Feuer and Steve Howell
|
||||
wxEditor component : Copyright 1999 - 2001 Dirk Holtwic, Robin Dunn, Adam Feuer, Steve Howell
|
||||
@@ -95,7 +93,7 @@ class FrogEditFrame(wxFrame):
|
||||
|
||||
def SetUpSplitter(self, splitter, win, log):
|
||||
splitter.SplitHorizontally(win, log)
|
||||
splitter.SetSashPosition(360, true)
|
||||
splitter.SetSashPosition(360, True)
|
||||
splitter.SetMinimumPaneSize(40)
|
||||
|
||||
def MakeToolbar(self, win):
|
||||
@@ -109,7 +107,7 @@ class FrogEditFrame(wxFrame):
|
||||
borderWidth = 5
|
||||
mainBox.Add(self.edl, 1, wxALL|wxGROW, borderWidth)
|
||||
win.SetSizer(mainBox)
|
||||
win.SetAutoLayout(true)
|
||||
win.SetAutoLayout(True)
|
||||
|
||||
##-------------- Init Menus
|
||||
|
||||
@@ -180,9 +178,9 @@ class FrogEditFrame(wxFrame):
|
||||
result = dialog.ShowModal()
|
||||
dialog.Destroy()
|
||||
if result == wxID_OK:
|
||||
return TRUE
|
||||
return True
|
||||
else:
|
||||
return FALSE
|
||||
return False
|
||||
|
||||
def SelectFileDialog(self, defaultDir=None, defaultFile=None, wildCard=None):
|
||||
if defaultDir == None:
|
||||
@@ -247,9 +245,9 @@ class FrogEditFrame(wxFrame):
|
||||
f.close()
|
||||
self.edl.UnTouchBuffer()
|
||||
self.sb.setFileName(fileName)
|
||||
return TRUE
|
||||
return True
|
||||
except:
|
||||
return FALSE
|
||||
return False
|
||||
|
||||
def OpenFile(self, fileName):
|
||||
try:
|
||||
@@ -262,9 +260,9 @@ class FrogEditFrame(wxFrame):
|
||||
self.edl.SetText(contents)
|
||||
self.fileName = fileName
|
||||
self.sb.setFileName(fileName)
|
||||
return TRUE
|
||||
return True
|
||||
except:
|
||||
return FALSE
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@@ -288,7 +286,7 @@ class FrogEditFrame(wxFrame):
|
||||
return
|
||||
fileName = self.SelectFileDialog(self.GetCurrentDir())
|
||||
if fileName is not None:
|
||||
if self.OpenFile(fileName) is FALSE:
|
||||
if self.OpenFile(fileName) is False:
|
||||
self.OpenFileError(fileName)
|
||||
self.edl.SetFocus()
|
||||
|
||||
@@ -296,7 +294,7 @@ class FrogEditFrame(wxFrame):
|
||||
if self.fileName is None:
|
||||
return self.OnSaveFileAs(event)
|
||||
wxLogMessage("Saving %s..." % self.fileName)
|
||||
if self.SaveFile(self.fileName) is not TRUE:
|
||||
if self.SaveFile(self.fileName) is not True:
|
||||
self.SaveFileError(self.fileName)
|
||||
self.edl.SetFocus()
|
||||
|
||||
@@ -305,7 +303,7 @@ class FrogEditFrame(wxFrame):
|
||||
if fileName is not None:
|
||||
self.fileName = fileName
|
||||
wxLogMessage("Saving %s..." % self.fileName)
|
||||
if self.SaveFile(self.fileName) is not TRUE:
|
||||
if self.SaveFile(self.fileName) is not True:
|
||||
self.SaveFileError(self.fileName)
|
||||
self.edl.SetFocus()
|
||||
|
||||
@@ -331,7 +329,7 @@ class FrogEditFrame(wxFrame):
|
||||
|
||||
def LoadInitialFile(self, fileName):
|
||||
if fileName is not None:
|
||||
if self.OpenFile(fileName) is FALSE:
|
||||
if self.OpenFile(fileName) is False:
|
||||
self.OpenFileError(fileName)
|
||||
|
||||
|
||||
@@ -354,7 +352,7 @@ class FrogEditLauncher:
|
||||
def Main(self):
|
||||
app = wxPySimpleApp()
|
||||
win = self.MakeAppFrame()
|
||||
win.Show(true)
|
||||
win.Show(True)
|
||||
win.LoadInitialFile(self.GetArgvFilename())
|
||||
app.MainLoop()
|
||||
|
||||
|
468
wxPython/samples/hangman/hangman.py
Normal file
468
wxPython/samples/hangman/hangman.py
Normal file
@@ -0,0 +1,468 @@
|
||||
"""Hangman.py, a simple wxPython game, inspired by the
|
||||
old bsd game by Ken Arnold.
|
||||
From the original man page:
|
||||
|
||||
In hangman, the computer picks a word from the on-line
|
||||
word list and you must try to guess it. The computer
|
||||
keeps track of which letters have been guessed and how
|
||||
many wrong guesses you have made on the screen in a
|
||||
graphic fashion.
|
||||
|
||||
That says it all, doesn't it?
|
||||
|
||||
Have fun with it,
|
||||
|
||||
Harm van der Heijden (H.v.d.Heijden@phys.tue.nl)"""
|
||||
|
||||
import random,re
|
||||
from wxPython.wx import *
|
||||
|
||||
|
||||
|
||||
class WordFetcher:
|
||||
builtin_words = ' albatros banana electrometer eggshell'
|
||||
|
||||
def __init__(self, filename, min_length = 5):
|
||||
self.min_length = min_length
|
||||
print "Trying to open file %s" % (filename,)
|
||||
try:
|
||||
f = open(filename, "r")
|
||||
except:
|
||||
print "Couldn't open dictionary file %s, using builtins" % (filename,)
|
||||
self.words = self.builtin_words
|
||||
self.filename = None
|
||||
return
|
||||
self.words = f.read()
|
||||
self.filename = filename
|
||||
print "Got %d bytes." % (len(self.words),)
|
||||
|
||||
def SetMinLength(min_length):
|
||||
self.min_length = min_length
|
||||
|
||||
def Get(self):
|
||||
reg = re.compile('\s+([a-zA-Z]+)\s+')
|
||||
n = 50 # safety valve; maximum number of tries to find a suitable word
|
||||
while n:
|
||||
index = int(random.random()*len(self.words))
|
||||
m = reg.search(self.words[index:])
|
||||
if m and len(m.groups()[0]) >= self.min_length: break
|
||||
n = n - 1
|
||||
if n: return m.groups()[0].lower()
|
||||
return "error"
|
||||
|
||||
|
||||
|
||||
def stdprint(x):
|
||||
print x
|
||||
|
||||
|
||||
|
||||
class URLWordFetcher(WordFetcher):
|
||||
def __init__(self, url):
|
||||
self.OpenURL(url)
|
||||
WordFetcher.__init__(self, "hangman_dict.txt")
|
||||
|
||||
def logprint(self,x):
|
||||
print x
|
||||
|
||||
def RetrieveAsFile(self, host, path=''):
|
||||
from httplib import HTTP
|
||||
try:
|
||||
h = HTTP(host)
|
||||
except:
|
||||
self.logprint("Failed to create HTTP connection to %s... is the network available?" % (host))
|
||||
return None
|
||||
h.putrequest('GET',path)
|
||||
h.putheader('Accept','text/html')
|
||||
h.putheader('Accept','text/plain')
|
||||
h.endheaders()
|
||||
errcode, errmsg, headers = h.getreply()
|
||||
if errcode != 200:
|
||||
self.logprint("HTTP error code %d: %s" % (errcode, errmsg))
|
||||
return None
|
||||
f = h.getfile()
|
||||
return f
|
||||
|
||||
def OpenURL(self,url):
|
||||
from htmllib import HTMLParser
|
||||
import formatter
|
||||
self.url = url
|
||||
m = re.match('http://([^/]+)(/\S*)\s*', url)
|
||||
if m:
|
||||
host = m.groups()[0]
|
||||
path = m.groups()[1]
|
||||
else:
|
||||
m = re.match('http://(\S+)\s*', url)
|
||||
if not m:
|
||||
# Invalid URL
|
||||
self.logprint("Invalid or unsupported URL: %s" % (url))
|
||||
return
|
||||
host = m.groups()[0]
|
||||
path = ''
|
||||
f = self.RetrieveAsFile(host,path)
|
||||
if not f:
|
||||
self.logprint("Could not open %s" % (url))
|
||||
return
|
||||
self.logprint("Receiving data...")
|
||||
data = f.read()
|
||||
tmp = open('hangman_dict.txt','w')
|
||||
fmt = formatter.AbstractFormatter(formatter.DumbWriter(tmp))
|
||||
p = HTMLParser(fmt)
|
||||
self.logprint("Parsing data...")
|
||||
p.feed(data)
|
||||
p.close()
|
||||
tmp.close()
|
||||
|
||||
|
||||
|
||||
class HangmanWnd(wxWindow):
|
||||
def __init__(self, parent, id, pos=wxDefaultPosition, size=wxDefaultSize):
|
||||
wxWindow.__init__(self, parent, id, pos, size)
|
||||
self.SetBackgroundColour(wxNamedColour('white'))
|
||||
if wxPlatform == '__WXGTK__':
|
||||
self.font = wxFont(12, wxMODERN, wxNORMAL, wxNORMAL)
|
||||
else:
|
||||
self.font = wxFont(10, wxMODERN, wxNORMAL, wxNORMAL)
|
||||
self.SetFocus()
|
||||
EVT_PAINT(self, self.OnPaint)
|
||||
|
||||
|
||||
def StartGame(self, word):
|
||||
self.word = word
|
||||
self.guess = []
|
||||
self.tries = 0
|
||||
self.misses = 0
|
||||
self.Draw()
|
||||
|
||||
def EndGame(self):
|
||||
self.misses = 7;
|
||||
self.guess = map(chr, range(ord('a'),ord('z')+1))
|
||||
self.Draw()
|
||||
|
||||
def HandleKey(self, key):
|
||||
self.message = ""
|
||||
if self.guess.count(key):
|
||||
self.message = 'Already guessed %s' % (key,)
|
||||
return 0
|
||||
self.guess.append(key)
|
||||
self.guess.sort()
|
||||
self.tries = self.tries+1
|
||||
if not key in self.word:
|
||||
self.misses = self.misses+1
|
||||
if self.misses == 7:
|
||||
self.EndGame()
|
||||
return 1
|
||||
has_won = 1
|
||||
for letter in self.word:
|
||||
if not self.guess.count(letter):
|
||||
has_won = 0
|
||||
break
|
||||
if has_won:
|
||||
self.Draw()
|
||||
return 2
|
||||
self.Draw()
|
||||
return 0
|
||||
|
||||
def Draw(self, dc = None):
|
||||
if not dc:
|
||||
dc = wxClientDC(self)
|
||||
dc.SetFont(self.font)
|
||||
dc.Clear()
|
||||
(x,y) = self.GetSizeTuple()
|
||||
x1 = x-200; y1 = 20
|
||||
for letter in self.word:
|
||||
if self.guess.count(letter):
|
||||
dc.DrawText(letter, x1, y1)
|
||||
else:
|
||||
dc.DrawText('.', x1, y1)
|
||||
x1 = x1 + 10
|
||||
x1 = x-200
|
||||
dc.DrawText("tries %d misses %d" % (self.tries,self.misses),x1,50)
|
||||
guesses = ""
|
||||
for letter in self.guess:
|
||||
guesses = guesses + letter
|
||||
dc.DrawText("guessed:", x1, 70)
|
||||
dc.DrawText(guesses[:13], x1+80, 70)
|
||||
dc.DrawText(guesses[13:], x1+80, 90)
|
||||
dc.SetUserScale(x/1000.0, y/1000.0)
|
||||
self.DrawVictim(dc)
|
||||
|
||||
def DrawVictim(self, dc):
|
||||
dc.SetPen(wxPen(wxNamedColour('black'), 20))
|
||||
dc.DrawLines([(10, 980), (10,900), (700,900), (700,940), (720,940),
|
||||
(720,980), (900,980)])
|
||||
dc.DrawLines([(100,900), (100, 100), (300,100)])
|
||||
dc.DrawLine(100,200,200,100)
|
||||
if ( self.misses == 0 ): return
|
||||
dc.SetPen(wxPen(wxNamedColour('blue'), 10))
|
||||
dc.DrawLine(300,100,300,200)
|
||||
if ( self.misses == 1 ): return
|
||||
dc.DrawEllipse(250,200,100,100)
|
||||
if ( self.misses == 2 ): return
|
||||
dc.DrawLine(300,300,300,600)
|
||||
if ( self.misses == 3) : return
|
||||
dc.DrawLine(300,300,250,550)
|
||||
if ( self.misses == 4) : return
|
||||
dc.DrawLine(300,300,350,550)
|
||||
if ( self.misses == 5) : return
|
||||
dc.DrawLine(300,600,350,850)
|
||||
if ( self.misses == 6) : return
|
||||
dc.DrawLine(300,600,250,850)
|
||||
|
||||
def OnPaint(self, event):
|
||||
dc = wxPaintDC(self)
|
||||
self.Draw(dc)
|
||||
|
||||
|
||||
|
||||
class HangmanDemo(HangmanWnd):
|
||||
def __init__(self, wf, parent, id, pos, size):
|
||||
HangmanWnd.__init__(self, parent, id, pos, size)
|
||||
self.StartGame("dummy")
|
||||
self.start_new = 1
|
||||
self.wf = wf
|
||||
self.delay = 500
|
||||
self.timer = self.PlayTimer(self.MakeMove)
|
||||
|
||||
def MakeMove(self):
|
||||
self.timer.Stop()
|
||||
if self.start_new:
|
||||
self.StartGame(self.wf.Get())
|
||||
self.start_new = 0
|
||||
self.left = list('aaaabcdeeeeefghiiiiijklmnnnoooopqrssssttttuuuuvwxyz')
|
||||
else:
|
||||
key = self.left[int(random.random()*len(self.left))]
|
||||
while self.left.count(key): self.left.remove(key)
|
||||
self.start_new = self.HandleKey(key)
|
||||
self.timer.Start(self.delay)
|
||||
|
||||
def Stop(self):
|
||||
self.timer.Stop()
|
||||
|
||||
class PlayTimer(wxTimer):
|
||||
def __init__(self,func):
|
||||
wxTimer.__init__(self)
|
||||
self.func = func
|
||||
self.Start(1000)
|
||||
|
||||
def Notify(self):
|
||||
apply(self.func, ())
|
||||
|
||||
|
||||
|
||||
class HangmanDemoFrame(wxFrame):
|
||||
def __init__(self, wf, parent, id, pos, size):
|
||||
wxFrame.__init__(self, parent, id, "Hangman demo", pos, size)
|
||||
self.demo = HangmanDemo(wf, self, -1, wxDefaultPosition, wxDefaultSize)
|
||||
EVT_CLOSE(self, self.OnCloseWindow)
|
||||
|
||||
def OnCloseWindow(self, event):
|
||||
self.demo.timer.Stop()
|
||||
self.Destroy()
|
||||
|
||||
|
||||
|
||||
class AboutBox(wxDialog):
|
||||
def __init__(self, parent,wf):
|
||||
wxDialog.__init__(self, parent, -1, "About Hangman", wxDefaultPosition, wxSize(350,450))
|
||||
self.wnd = HangmanDemo(wf, self, -1, wxPoint(1,1), wxSize(350,150))
|
||||
self.static = wxStaticText(self, -1, __doc__, wxPoint(1,160), wxSize(350, 250))
|
||||
self.button = wxButton(self, 2001, "OK", wxPoint(150,420), wxSize(50,-1))
|
||||
EVT_BUTTON(self, 2001, self.OnOK)
|
||||
|
||||
def OnOK(self, event):
|
||||
self.wnd.Stop()
|
||||
self.EndModal(wxID_OK)
|
||||
|
||||
|
||||
|
||||
class MyFrame(wxFrame):
|
||||
def __init__(self, parent, wf):
|
||||
self.wf = wf
|
||||
wxFrame.__init__(self, parent, -1, "hangman", wxDefaultPosition, wxSize(400,300))
|
||||
self.wnd = HangmanWnd(self, -1)
|
||||
menu = wxMenu()
|
||||
menu.Append(1001, "New")
|
||||
menu.Append(1002, "End")
|
||||
menu.AppendSeparator()
|
||||
menu.Append(1003, "Reset")
|
||||
menu.Append(1004, "Demo...")
|
||||
menu.AppendSeparator()
|
||||
menu.Append(1005, "Exit")
|
||||
menubar = wxMenuBar()
|
||||
menubar.Append(menu, "Game")
|
||||
menu = wxMenu()
|
||||
#menu.Append(1010, "Internal", "Use internal dictionary", True)
|
||||
menu.Append(1011, "ASCII File...")
|
||||
urls = [ 'wxPython home', 'http://wxPython.org/',
|
||||
'slashdot.org', 'http://slashdot.org/',
|
||||
'cnn.com', 'http://cnn.com',
|
||||
'The New York Times', 'http://www.nytimes.com',
|
||||
'De Volkskrant', 'http://www.volkskrant.nl/frameless/25000006.html',
|
||||
'Gnu GPL', 'http://www.fsf.org/copyleft/gpl.html',
|
||||
'Bijbel: Genesis', 'http://www.coas.com/bijbel/gn1.htm']
|
||||
urlmenu = wxMenu()
|
||||
for item in range(0,len(urls),2):
|
||||
urlmenu.Append(1020+item/2, urls[item], urls[item+1])
|
||||
urlmenu.Append(1080, 'Other...', 'Enter an URL')
|
||||
menu.AppendMenu(1012, 'URL', urlmenu, 'Use a webpage')
|
||||
menu.Append(1013, 'Dump', 'Write contents to stdout')
|
||||
menubar.Append(menu, "Dictionary")
|
||||
self.urls = urls
|
||||
self.urloffset = 1020
|
||||
menu = wxMenu()
|
||||
menu.Append(1090, "About...")
|
||||
menubar.Append(menu, "Help")
|
||||
self.SetMenuBar(menubar)
|
||||
self.CreateStatusBar(2)
|
||||
EVT_MENU(self, 1001, self.OnGameNew)
|
||||
EVT_MENU(self, 1002, self.OnGameEnd)
|
||||
EVT_MENU(self, 1003, self.OnGameReset)
|
||||
EVT_MENU(self, 1004, self.OnGameDemo)
|
||||
EVT_MENU(self, 1005, self.OnWindowClose)
|
||||
EVT_MENU(self, 1011, self.OnDictFile)
|
||||
EVT_MENU_RANGE(self, 1020, 1020+len(urls)/2, self.OnDictURL)
|
||||
EVT_MENU(self, 1080, self.OnDictURLSel)
|
||||
EVT_MENU(self, 1013, self.OnDictDump)
|
||||
EVT_MENU(self, 1090, self.OnHelpAbout)
|
||||
EVT_CHAR(self.wnd, self.OnChar)
|
||||
self.OnGameReset()
|
||||
|
||||
def OnGameNew(self, event):
|
||||
word = self.wf.Get()
|
||||
self.in_progress = 1
|
||||
self.SetStatusText("",0)
|
||||
self.wnd.StartGame(word)
|
||||
|
||||
def OnGameEnd(self, event):
|
||||
self.UpdateAverages(0)
|
||||
self.in_progress = 0
|
||||
self.SetStatusText("",0)
|
||||
self.wnd.EndGame()
|
||||
|
||||
def OnGameReset(self, event=None):
|
||||
self.played = 0
|
||||
self.won = 0
|
||||
self.history = []
|
||||
self.average = 0.0
|
||||
self.OnGameNew(None)
|
||||
|
||||
def OnGameDemo(self, event):
|
||||
frame = HangmanDemoFrame(self.wf, self, -1, wxDefaultPosition, self.GetSize())
|
||||
frame.Show(True)
|
||||
|
||||
def OnDictFile(self, event):
|
||||
fd = wxFileDialog(self)
|
||||
if (self.wf.filename):
|
||||
fd.SetFilename(self.wf.filename)
|
||||
if fd.ShowModal() == wxID_OK:
|
||||
file = fd.GetPath()
|
||||
self.wf = WordFetcher(file)
|
||||
|
||||
def OnDictURL(self, event):
|
||||
item = (event.GetId() - self.urloffset)*2
|
||||
print "Trying to open %s at %s" % (self.urls[item], self.urls[item+1])
|
||||
self.wf = URLWordFetcher(self.urls[item+1])
|
||||
|
||||
def OnDictURLSel(self, event):
|
||||
msg = wxTextEntryDialog(self, "Enter the URL of the dictionary document", "Enter URL")
|
||||
if msg.ShowModal() == wxID_OK:
|
||||
url = msg.GetValue()
|
||||
self.wf = URLWordFetcher(url)
|
||||
def OnDictDump(self, event):
|
||||
print self.wf.words
|
||||
|
||||
def OnHelpAbout(self, event):
|
||||
about = AboutBox(self, self.wf)
|
||||
about.ShowModal()
|
||||
about.wnd.Stop() # that damn timer won't stop!
|
||||
|
||||
def UpdateAverages(self, has_won):
|
||||
if has_won:
|
||||
self.won = self.won + 1
|
||||
self.played = self.played+1
|
||||
self.history.append(self.wnd.misses) # ugly
|
||||
total = 0.0
|
||||
for m in self.history:
|
||||
total = total + m
|
||||
self.average = float(total/len(self.history))
|
||||
|
||||
def OnChar(self, event):
|
||||
if not self.in_progress:
|
||||
#print "new"
|
||||
self.OnGameNew(None)
|
||||
return
|
||||
key = event.KeyCode();
|
||||
#print key
|
||||
if key >= ord('A') and key <= ord('Z'):
|
||||
key = key + ord('a') - ord('A')
|
||||
key = chr(key)
|
||||
if key < 'a' or key > 'z':
|
||||
event.Skip()
|
||||
return
|
||||
res = self.wnd.HandleKey(key)
|
||||
if res == 0:
|
||||
self.SetStatusText(self.wnd.message)
|
||||
elif res == 1:
|
||||
self.UpdateAverages(0)
|
||||
self.SetStatusText("Too bad, you're dead!",0)
|
||||
self.in_progress = 0
|
||||
elif res == 2:
|
||||
self.in_progress = 0
|
||||
self.UpdateAverages(1)
|
||||
self.SetStatusText("Congratulations!",0)
|
||||
if self.played:
|
||||
percent = (100.*self.won)/self.played
|
||||
else:
|
||||
percent = 0.0
|
||||
self.SetStatusText("p %d, w %d (%g %%), av %g" % (self.played,self.won, percent, self.average),1)
|
||||
|
||||
def OnWindowClose(self, event):
|
||||
self.Destroy()
|
||||
|
||||
|
||||
|
||||
class MyApp(wxApp):
|
||||
def OnInit(self):
|
||||
if wxPlatform == '__WXGTK__':
|
||||
defaultfile = "/usr/share/games/hangman-words"
|
||||
elif wxPlatform == '__WXMSW__':
|
||||
defaultfile = "c:\\windows\\hardware.txt"
|
||||
else:
|
||||
defaultfile = ""
|
||||
wf = WordFetcher(defaultfile)
|
||||
frame = MyFrame(None, wf)
|
||||
self.SetTopWindow(frame)
|
||||
frame.Show(True)
|
||||
return True
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = MyApp(0)
|
||||
app.MainLoop()
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
overview = __doc__
|
||||
|
||||
|
||||
def runTest(frame, nb, log):
|
||||
if wxPlatform == '__WXGTK__' or wxPlatform == '__WXMOTIF__':
|
||||
defaultfile = "/usr/share/games/hangman-words"
|
||||
elif wxPlatform == '__WXMSW__':
|
||||
defaultfile = "c:\\windows\\hardware.txt"
|
||||
else:
|
||||
defaultfile = ""
|
||||
wf = WordFetcher(defaultfile)
|
||||
win = MyFrame(frame, wf)
|
||||
frame.otherWin = win
|
||||
win.Show(True)
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
|
||||
This sample is a simple StructuredText viewer/editor.
|
||||
|
@@ -1,684 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import re, ST, STDOM
|
||||
from string import split, join, replace, expandtabs, strip, find
|
||||
from STletters import letters,lettpunc,punctuations
|
||||
|
||||
StringType=type('')
|
||||
ListType=type([])
|
||||
|
||||
class StructuredTextExample(ST.StructuredTextParagraph):
|
||||
"""Represents a section of document with literal text, as for examples"""
|
||||
|
||||
def __init__(self, subs, **kw):
|
||||
t=[]; a=t.append
|
||||
for s in subs: a(s.getNodeValue())
|
||||
apply(ST.StructuredTextParagraph.__init__,
|
||||
(self, join(t,'\n\n'), ()),
|
||||
kw)
|
||||
|
||||
def getColorizableTexts(self): return ()
|
||||
def setColorizableTexts(self, src): pass # never color examples
|
||||
|
||||
class StructuredTextBullet(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextNumbered(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextDescriptionTitle(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextDescriptionBody(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextDescription(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
def __init__(self, title, src, subs, **kw):
|
||||
apply(ST.StructuredTextParagraph.__init__, (self, src, subs), kw)
|
||||
self._title=title
|
||||
|
||||
def getColorizableTexts(self): return self._title, self._src
|
||||
def setColorizableTexts(self, src): self._title, self._src = src
|
||||
|
||||
def getChildren(self):
|
||||
return (StructuredTextDescriptionTitle(self._title),
|
||||
StructuredTextDescriptionBody(self._src, self._subs))
|
||||
|
||||
class StructuredTextSectionTitle(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextSection(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
def __init__(self, src, subs=None, **kw):
|
||||
apply(ST.StructuredTextParagraph.__init__,
|
||||
(self, StructuredTextSectionTitle(src), subs),
|
||||
kw)
|
||||
|
||||
def getColorizableTexts(self):
|
||||
return self._src.getColorizableTexts()
|
||||
|
||||
def setColorizableTexts(self,src):
|
||||
self._src.setColorizableTexts(src)
|
||||
|
||||
# a StructuredTextTable holds StructuredTextRows
|
||||
class StructuredTextTable(ST.StructuredTextDocument):
|
||||
"""
|
||||
rows is a list of lists containing tuples, which
|
||||
represent the columns/cells in each rows.
|
||||
EX
|
||||
rows = [[('row 1:column1',1)],[('row2:column1',1)]]
|
||||
"""
|
||||
|
||||
def __init__(self, rows, src, subs, **kw):
|
||||
apply(ST.StructuredTextDocument.__init__,(self,subs),kw)
|
||||
self._rows = []
|
||||
for row in rows:
|
||||
if row:
|
||||
self._rows.append(StructuredTextRow(row,kw))
|
||||
|
||||
def getRows(self):
|
||||
return [self._rows]
|
||||
|
||||
def _getRows(self):
|
||||
return self.getRows()
|
||||
|
||||
def getColorizableTexts(self):
|
||||
"""
|
||||
return a tuple where each item is a column/cell's
|
||||
contents. The tuple, result, will be of this format.
|
||||
("r1 col1", "r1=col2", "r2 col1", "r2 col2")
|
||||
"""
|
||||
|
||||
#result = ()
|
||||
result = []
|
||||
for row in self._rows:
|
||||
for column in row.getColumns()[0]:
|
||||
#result = result[:] + (column.getColorizableTexts(),)
|
||||
result.append(column.getColorizableTexts()[0])
|
||||
return result
|
||||
|
||||
def setColorizableTexts(self,texts):
|
||||
"""
|
||||
texts is going to a tuple where each item is the
|
||||
result of being mapped to the colortext function.
|
||||
Need to insert the results appropriately into the
|
||||
individual columns/cells
|
||||
"""
|
||||
for row_index in range(len(self._rows)):
|
||||
for column_index in range(len(self._rows[row_index]._columns)):
|
||||
self._rows[row_index]._columns[column_index].setColorizableTexts((texts[0],))
|
||||
texts = texts[1:]
|
||||
|
||||
def _getColorizableTexts(self):
|
||||
return self.getColorizableTexts()
|
||||
|
||||
def _setColorizableTexts(self):
|
||||
return self.setColorizableTexts()
|
||||
|
||||
# StructuredTextRow holds StructuredTextColumns
|
||||
class StructuredTextRow(ST.StructuredTextDocument):
|
||||
|
||||
def __init__(self,row,kw):
|
||||
"""
|
||||
row is a list of tuples, where each tuple is
|
||||
the raw text for a cell/column and the span
|
||||
of that cell/column".
|
||||
EX
|
||||
[('this is column one',1), ('this is column two',1)]
|
||||
"""
|
||||
|
||||
apply(ST.StructuredTextDocument.__init__,(self,[]),kw)
|
||||
self._columns = []
|
||||
for column in row:
|
||||
self._columns.append(StructuredTextColumn(column[0],column[1],kw))
|
||||
def getColumns(self):
|
||||
return [self._columns]
|
||||
|
||||
def _getColumns(self):
|
||||
return [self._columns]
|
||||
|
||||
# this holds the raw text of a table cell
|
||||
class StructuredTextColumn(ST.StructuredTextParagraph):
|
||||
"""
|
||||
StructuredTextColumn is a cell/column in a table.
|
||||
This contains the actual text of a column and is
|
||||
thus a StructuredTextParagraph. A StructuredTextColumn
|
||||
also holds the span of its column
|
||||
"""
|
||||
|
||||
def __init__(self,text,span,kw):
|
||||
apply(ST.StructuredTextParagraph.__init__,(self,text,[]),kw)
|
||||
self._span = span
|
||||
|
||||
def getSpan(self):
|
||||
return self._span
|
||||
|
||||
def _getSpan(self):
|
||||
return self._span
|
||||
|
||||
class StructuredTextMarkup(STDOM.Element):
|
||||
|
||||
def __init__(self, v, **kw):
|
||||
self._value=v
|
||||
self._attributes=kw.keys()
|
||||
for k, v in kw.items(): setattr(self, k, v)
|
||||
|
||||
def getChildren(self, type=type, lt=type([])):
|
||||
v=self._value
|
||||
if type(v) is not lt: v=[v]
|
||||
return v
|
||||
|
||||
def getColorizableTexts(self): return self._value,
|
||||
def setColorizableTexts(self, v): self._value=v[0]
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (self.__class__.__name__, `self._value`)
|
||||
|
||||
class StructuredTextLiteral(StructuredTextMarkup):
|
||||
def getColorizableTexts(self): return ()
|
||||
def setColorizableTexts(self, v): pass
|
||||
|
||||
class StructuredTextEmphasis(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextStrong(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextInnerLink(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextNamedLink(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextUnderline(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextLink(StructuredTextMarkup):
|
||||
"A simple hyperlink"
|
||||
|
||||
class DocumentClass:
|
||||
"""
|
||||
Class instance calls [ex.=> x()] require a structured text
|
||||
structure. Doc will then parse each paragraph in the structure
|
||||
and will find the special structures within each paragraph.
|
||||
Each special structure will be stored as an instance. Special
|
||||
structures within another special structure are stored within
|
||||
the 'top' structure
|
||||
EX : '-underline this-' => would be turned into an underline
|
||||
instance. '-underline **this**' would be stored as an underline
|
||||
instance with a strong instance stored in its string
|
||||
"""
|
||||
|
||||
paragraph_types = [
|
||||
'doc_bullet',
|
||||
'doc_numbered',
|
||||
'doc_description',
|
||||
'doc_header',
|
||||
'doc_table',
|
||||
]
|
||||
|
||||
text_types = [
|
||||
'doc_href',
|
||||
'doc_strong',
|
||||
'doc_emphasize',
|
||||
'doc_literal',
|
||||
'doc_inner_link',
|
||||
'doc_named_link',
|
||||
'doc_underline',
|
||||
]
|
||||
|
||||
def __call__(self, doc):
|
||||
if type(doc) is type(''):
|
||||
doc=ST.StructuredText(doc)
|
||||
doc.setSubparagraphs(self.color_paragraphs(
|
||||
doc.getSubparagraphs()))
|
||||
else:
|
||||
doc=ST.StructuredTextDocument(self.color_paragraphs(
|
||||
doc.getSubparagraphs()))
|
||||
return doc
|
||||
|
||||
def parse(self, raw_string, text_type,
|
||||
type=type, st=type(''), lt=type([])):
|
||||
|
||||
"""
|
||||
Parse accepts a raw_string, an expr to test the raw_string,
|
||||
and the raw_string's subparagraphs.
|
||||
|
||||
Parse will continue to search through raw_string until
|
||||
all instances of expr in raw_string are found.
|
||||
|
||||
If no instances of expr are found, raw_string is returned.
|
||||
Otherwise a list of substrings and instances is returned
|
||||
"""
|
||||
|
||||
tmp = [] # the list to be returned if raw_string is split
|
||||
append=tmp.append
|
||||
|
||||
if type(text_type) is st: text_type=getattr(self, text_type)
|
||||
|
||||
while 1:
|
||||
t = text_type(raw_string)
|
||||
if not t: break
|
||||
#an instance of expr was found
|
||||
t, start, end = t
|
||||
|
||||
if start: append(raw_string[0:start])
|
||||
|
||||
tt=type(t)
|
||||
if tt is st:
|
||||
# if we get a string back, add it to text to be parsed
|
||||
raw_string = t+raw_string[end:len(raw_string)]
|
||||
else:
|
||||
if tt is lt:
|
||||
# is we get a list, append it's elements
|
||||
tmp[len(tmp):]=t
|
||||
else:
|
||||
# normal case, an object
|
||||
append(t)
|
||||
raw_string = raw_string[end:len(raw_string)]
|
||||
|
||||
if not tmp: return raw_string # nothing found
|
||||
|
||||
if raw_string: append(raw_string)
|
||||
elif len(tmp)==1: return tmp[0]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
def color_text(self, str, types=None):
|
||||
"""Search the paragraph for each special structure
|
||||
"""
|
||||
if types is None: types=self.text_types
|
||||
|
||||
for text_type in types:
|
||||
|
||||
if type(str) is StringType:
|
||||
str = self.parse(str, text_type)
|
||||
elif type(str) is ListType:
|
||||
r=[]; a=r.append
|
||||
for s in str:
|
||||
if type(s) is StringType:
|
||||
s=self.parse(s, text_type)
|
||||
if type(s) is ListType: r[len(r):]=s
|
||||
else: a(s)
|
||||
else:
|
||||
s.setColorizableTexts(
|
||||
map(self.color_text,
|
||||
s.getColorizableTexts()
|
||||
))
|
||||
a(s)
|
||||
str=r
|
||||
else:
|
||||
r=[]; a=r.append; color=self.color_text
|
||||
for s in str.getColorizableTexts():
|
||||
color(s, (text_type,))
|
||||
a(s)
|
||||
|
||||
str.setColorizableTexts(r)
|
||||
|
||||
return str
|
||||
|
||||
def color_paragraphs(self, raw_paragraphs,
|
||||
type=type, sequence_types=(type([]), type(())),
|
||||
st=type('')):
|
||||
result=[]
|
||||
for paragraph in raw_paragraphs:
|
||||
|
||||
if paragraph.getNodeName() != 'StructuredTextParagraph':
|
||||
result.append(paragraph)
|
||||
continue
|
||||
|
||||
for pt in self.paragraph_types:
|
||||
if type(pt) is st:
|
||||
# grab the corresponding function
|
||||
pt=getattr(self, pt)
|
||||
# evaluate the paragraph
|
||||
r=pt(paragraph)
|
||||
if r:
|
||||
if type(r) not in sequence_types:
|
||||
r=r,
|
||||
new_paragraphs=r
|
||||
for paragraph in new_paragraphs:
|
||||
paragraph.setSubparagraphs(self.color_paragraphs(paragraph.getSubparagraphs()))
|
||||
break
|
||||
else:
|
||||
new_paragraphs=ST.StructuredTextParagraph(paragraph.getColorizableTexts()[0],
|
||||
self.color_paragraphs(paragraph.getSubparagraphs()),
|
||||
indent=paragraph.indent),
|
||||
# color the inline StructuredText types
|
||||
# for each StructuredTextParagraph
|
||||
for paragraph in new_paragraphs:
|
||||
paragraph.setColorizableTexts(
|
||||
map(self.color_text,
|
||||
paragraph.getColorizableTexts()
|
||||
))
|
||||
result.append(paragraph)
|
||||
|
||||
return result
|
||||
|
||||
def doc_table(self,paragraph, expr = re.compile('(\s*)([||]+)').match):
|
||||
#print "paragraph=>", type(paragraph), paragraph, paragraph._src
|
||||
text = paragraph.getColorizableTexts()[0]
|
||||
m = expr(text)
|
||||
|
||||
if not (m):
|
||||
return None
|
||||
rows = []
|
||||
|
||||
# initial split
|
||||
for row in split(text,"\n"):
|
||||
rows.append(row)
|
||||
|
||||
# clean up the rows
|
||||
for index in range(len(rows)):
|
||||
tmp = []
|
||||
rows[index] = strip(rows[index])
|
||||
l = len(rows[index])-2
|
||||
result = split(rows[index][:l],"||")
|
||||
for text in result:
|
||||
if text:
|
||||
tmp.append(text)
|
||||
tmp.append('')
|
||||
else:
|
||||
tmp.append(text)
|
||||
rows[index] = tmp
|
||||
# remove trailing '''s
|
||||
for index in range(len(rows)):
|
||||
l = len(rows[index])-1
|
||||
rows[index] = rows[index][:l]
|
||||
|
||||
result = []
|
||||
for row in rows:
|
||||
cspan = 0
|
||||
tmp = []
|
||||
for item in row:
|
||||
if item:
|
||||
tmp.append((item,cspan))
|
||||
cspan = 0
|
||||
else:
|
||||
cspan = cspan + 1
|
||||
result.append(tmp)
|
||||
|
||||
subs = paragraph.getSubparagraphs()
|
||||
indent=paragraph.indent
|
||||
return StructuredTextTable(result,text,subs,indent=paragraph.indent)
|
||||
|
||||
def doc_bullet(self, paragraph, expr = re.compile('\s*[-*o]\s+').match):
|
||||
top=paragraph.getColorizableTexts()[0]
|
||||
m=expr(top)
|
||||
|
||||
if not m:
|
||||
return None
|
||||
|
||||
subs=paragraph.getSubparagraphs()
|
||||
if top[-2:]=='::':
|
||||
subs=[StructuredTextExample(subs)]
|
||||
top=top[:-1]
|
||||
return StructuredTextBullet(top[m.span()[1]:], subs,
|
||||
indent=paragraph.indent,
|
||||
bullet=top[:m.span()[1]]
|
||||
)
|
||||
|
||||
def doc_numbered(
|
||||
self, paragraph,
|
||||
expr = re.compile('(\s*[%s]+\.)|(\s*[0-9]+\.)|(\s*[0-9]+\s+)' % letters).match):
|
||||
|
||||
# This is the old expression. It had a nasty habit
|
||||
# of grabbing paragraphs that began with a single
|
||||
# letter word even if there was no following period.
|
||||
|
||||
#expr = re.compile('\s*'
|
||||
# '(([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.)*'
|
||||
# '([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.?'
|
||||
# '\s+').match):
|
||||
|
||||
top=paragraph.getColorizableTexts()[0]
|
||||
m=expr(top)
|
||||
if not m: return None
|
||||
subs=paragraph.getSubparagraphs()
|
||||
if top[-2:]=='::':
|
||||
subs=[StructuredTextExample(subs)]
|
||||
top=top[:-1]
|
||||
return StructuredTextNumbered(top[m.span()[1]:], subs,
|
||||
indent=paragraph.indent,
|
||||
number=top[:m.span()[1]])
|
||||
|
||||
def doc_description(
|
||||
self, paragraph,
|
||||
delim = re.compile('\s+--\s+').search,
|
||||
nb=re.compile(r'[^\000- ]').search,
|
||||
):
|
||||
|
||||
top=paragraph.getColorizableTexts()[0]
|
||||
d=delim(top)
|
||||
if not d: return None
|
||||
start, end = d.span()
|
||||
title=top[:start]
|
||||
if find(title, '\n') >= 0: return None
|
||||
if not nb(title): return None
|
||||
d=top[start:end]
|
||||
top=top[end:]
|
||||
|
||||
subs=paragraph.getSubparagraphs()
|
||||
if top[-2:]=='::':
|
||||
subs=[StructuredTextExample(subs)]
|
||||
top=top[:-1]
|
||||
|
||||
return StructuredTextDescription(
|
||||
title, top, subs,
|
||||
indent=paragraph.indent,
|
||||
delim=d)
|
||||
|
||||
def doc_header(self, paragraph,
|
||||
expr = re.compile('[ %s0-9.:/,-_*<>\?\'\"]+' % letters).match
|
||||
):
|
||||
subs=paragraph.getSubparagraphs()
|
||||
if not subs: return None
|
||||
top=paragraph.getColorizableTexts()[0]
|
||||
if not strip(top): return None
|
||||
if top[-2:]=='::':
|
||||
subs=StructuredTextExample(subs)
|
||||
if strip(top)=='::': return subs
|
||||
return ST.StructuredTextParagraph(top[:-1],
|
||||
[subs],
|
||||
indent=paragraph.indent,
|
||||
level=paragraph.level)
|
||||
|
||||
if find(top,'\n') >= 0: return None
|
||||
return StructuredTextSection(top, subs, indent=paragraph.indent, level=paragraph.level)
|
||||
|
||||
def doc_literal(
|
||||
self, s,
|
||||
expr=re.compile(
|
||||
"(?:\s|^)'" # open
|
||||
"([^ \t\n\r\f\v']|[^ \t\n\r\f\v'][^\n']*[^ \t\n\r\f\v'])" # contents
|
||||
"'(?:\s|[,.;:!?]|$)" # close
|
||||
).search):
|
||||
|
||||
r=expr(s)
|
||||
if r:
|
||||
start, end = r.span(1)
|
||||
return (StructuredTextLiteral(s[start:end]), start-1, end+1)
|
||||
else:
|
||||
return None
|
||||
|
||||
def doc_emphasize(
|
||||
self, s,
|
||||
expr = re.compile('\s*\*([ \n%s0-9]+)\*(?!\*|-)' % lettpunc).search
|
||||
):
|
||||
|
||||
r=expr(s)
|
||||
if r:
|
||||
start, end = r.span(1)
|
||||
return (StructuredTextEmphasis(s[start:end]), start-1, end+1)
|
||||
else:
|
||||
return None
|
||||
|
||||
def doc_inner_link(self,
|
||||
s,
|
||||
expr1 = re.compile("\.\.\s*").search,
|
||||
expr2 = re.compile("\[[%s0-9]+\]" % letters).search):
|
||||
|
||||
# make sure we dont grab a named link
|
||||
if expr2(s) and expr1(s):
|
||||
start1,end1 = expr1(s).span()
|
||||
start2,end2 = expr2(s).span()
|
||||
if end1 == start2:
|
||||
# uh-oh, looks like a named link
|
||||
return None
|
||||
else:
|
||||
# the .. is somewhere else, ignore it
|
||||
return (StructuredTextInnerLink(s[start2+1:end2-1]),start2,end2)
|
||||
return None
|
||||
elif expr2(s) and not expr1(s):
|
||||
start,end = expr2(s).span()
|
||||
return (StructuredTextInnerLink(s[start+1:end-1]),start,end)
|
||||
return None
|
||||
|
||||
def doc_named_link(self,
|
||||
s,
|
||||
expr=re.compile("(\.\.\s)(\[[%s0-9]+\])" % letters).search):
|
||||
|
||||
result = expr(s)
|
||||
if result:
|
||||
start,end = result.span(2)
|
||||
a,b = result.span(1)
|
||||
str = strip(s[a:b]) + s[start:end]
|
||||
str = s[start+1:end-1]
|
||||
st,en = result.span()
|
||||
return (StructuredTextNamedLink(str),st,en)
|
||||
#return (StructuredTextNamedLink(s[st:en]),st,en)
|
||||
return None
|
||||
|
||||
def doc_underline(self,
|
||||
s,
|
||||
expr=re.compile("\s+\_([0-9%s ]+)\_" % lettpunc).search):
|
||||
|
||||
result = expr(s)
|
||||
if result:
|
||||
start,end = result.span(1)
|
||||
st,e = result.span()
|
||||
return (StructuredTextUnderline(s[start:end]),st,e)
|
||||
else:
|
||||
return None
|
||||
|
||||
def doc_strong(self,
|
||||
s,
|
||||
expr = re.compile('\s*\*\*([ \n%s0-9]+)\*\*' % lettpunc).search
|
||||
):
|
||||
|
||||
r=expr(s)
|
||||
if r:
|
||||
start, end = r.span(1)
|
||||
return (StructuredTextStrong(s[start:end]), start-2, end+2)
|
||||
else:
|
||||
return None
|
||||
|
||||
def doc_href(
|
||||
|
||||
self, s,
|
||||
expr1 = re.compile("(\"[ %s0-9\n\-\.\,\;\(\)\/\:\/\*\']+\")(:)([a-zA-Z0-9\@\.\,\?\!\/\:\;\-\#\~]+)([,]*\s*)" % letters).search,
|
||||
expr2 = re.compile('(\"[ %s0-9\n\-\.\:\;\(\)\/\*\']+\")([,]+\s+)([a-zA-Z0-9\@\.\,\?\!\/\:\;\-\#\~]+)(\s*)' % letters).search):
|
||||
|
||||
r=expr1(s) or expr2(s)
|
||||
|
||||
if r:
|
||||
# need to grab the href part and the
|
||||
# beginning part
|
||||
|
||||
start,e = r.span(1)
|
||||
name = s[start:e]
|
||||
name = replace(name,'"','',2)
|
||||
st,end = r.span(3)
|
||||
|
||||
if s[end-1:end] in punctuations: end-=1
|
||||
link = s[st:end]
|
||||
|
||||
# name is the href title, link is the target
|
||||
# of the href
|
||||
return (StructuredTextLink(name, href=link),
|
||||
start, end)
|
||||
|
||||
|
||||
else:
|
||||
return None
|
@@ -1,625 +0,0 @@
|
||||
#! /usr/bin/env python -- # -*- python -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
'''Structured Text Manipulation
|
||||
|
||||
Parse a structured text string into a form that can be used with
|
||||
structured formats, like html.
|
||||
|
||||
Structured text is text that uses indentation and simple
|
||||
symbology to indicate the structure of a document.
|
||||
|
||||
A structured string consists of a sequence of paragraphs separated by
|
||||
one or more blank lines. Each paragraph has a level which is defined
|
||||
as the minimum indentation of the paragraph. A paragraph is a
|
||||
sub-paragraph of another paragraph if the other paragraph is the last
|
||||
preceding paragraph that has a lower level.
|
||||
|
||||
Special symbology is used to indicate special constructs:
|
||||
|
||||
- A single-line paragraph whose immediately succeeding paragraphs are lower
|
||||
level is treated as a header.
|
||||
|
||||
- A paragraph that begins with a '-', '*', or 'o' is treated as an
|
||||
unordered list (bullet) element.
|
||||
|
||||
- A paragraph that begins with a sequence of digits followed by a
|
||||
white-space character is treated as an ordered list element.
|
||||
|
||||
- A paragraph that begins with a sequence of sequences, where each
|
||||
sequence is a sequence of digits or a sequence of letters followed
|
||||
by a period, is treated as an ordered list element.
|
||||
|
||||
- A paragraph with a first line that contains some text, followed by
|
||||
some white-space and '--' is treated as
|
||||
a descriptive list element. The leading text is treated as the
|
||||
element title.
|
||||
|
||||
- Sub-paragraphs of a paragraph that ends in the word 'example' or the
|
||||
word 'examples', or '::' is treated as example code and is output as is.
|
||||
|
||||
- Text enclosed single quotes (with white-space to the left of the
|
||||
first quote and whitespace or punctuation to the right of the second quote)
|
||||
is treated as example code.
|
||||
|
||||
- Text surrounded by '*' characters (with white-space to the left of the
|
||||
first '*' and whitespace or punctuation to the right of the second '*')
|
||||
is emphasized.
|
||||
|
||||
- Text surrounded by '**' characters (with white-space to the left of the
|
||||
first '**' and whitespace or punctuation to the right of the second '**')
|
||||
is made strong.
|
||||
|
||||
- Text surrounded by '_' underscore characters (with whitespace to the left
|
||||
and whitespace or punctuation to the right) is made underlined.
|
||||
|
||||
- Text encloded by double quotes followed by a colon, a URL, and concluded
|
||||
by punctuation plus white space, *or* just white space, is treated as a
|
||||
hyper link. For example:
|
||||
|
||||
"Zope":http://www.zope.org/ is ...
|
||||
|
||||
Is interpreted as '<a href="http://www.zope.org/">Zope</a> is ....'
|
||||
Note: This works for relative as well as absolute URLs.
|
||||
|
||||
- Text enclosed by double quotes followed by a comma, one or more spaces,
|
||||
an absolute URL and concluded by punctuation plus white space, or just
|
||||
white space, is treated as a hyper link. For example:
|
||||
|
||||
"mail me", mailto:amos@digicool.com.
|
||||
|
||||
Is interpreted as '<a href="mailto:amos@digicool.com">mail me</a>.'
|
||||
|
||||
- Text enclosed in brackets which consists only of letters, digits,
|
||||
underscores and dashes is treated as hyper links within the document.
|
||||
For example:
|
||||
|
||||
As demonstrated by Smith [12] this technique is quite effective.
|
||||
|
||||
Is interpreted as '... by Smith <a href="#12">[12]</a> this ...'. Together
|
||||
with the next rule this allows easy coding of references or end notes.
|
||||
|
||||
- Text enclosed in brackets which is preceded by the start of a line, two
|
||||
periods and a space is treated as a named link. For example:
|
||||
|
||||
.. [12] "Effective Techniques" Smith, Joe ...
|
||||
|
||||
Is interpreted as '<a name="12">[12]</a> "Effective Techniques" ...'.
|
||||
Together with the previous rule this allows easy coding of references or
|
||||
end notes.
|
||||
|
||||
|
||||
- A paragraph that has blocks of text enclosed in '||' is treated as a
|
||||
table. The text blocks correspond to table cells and table rows are
|
||||
denoted by newlines. By default the cells are center aligned. A cell
|
||||
can span more than one column by preceding a block of text with an
|
||||
equivalent number of cell separators '||'. Newlines and '|' cannot
|
||||
be a part of the cell text. For example:
|
||||
|
||||
|||| **Ingredients** ||
|
||||
|| *Name* || *Amount* ||
|
||||
||Spam||10||
|
||||
||Eggs||3||
|
||||
|
||||
is interpreted as::
|
||||
|
||||
<TABLE BORDER=1 CELLPADDING=2>
|
||||
<TR>
|
||||
<TD ALIGN=CENTER COLSPAN=2> <strong>Ingredients</strong> </TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN=CENTER COLSPAN=1> <em>Name</em> </TD>
|
||||
<TD ALIGN=CENTER COLSPAN=1> <em>Amount</em> </TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN=CENTER COLSPAN=1>Spam</TD>
|
||||
<TD ALIGN=CENTER COLSPAN=1>10</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN=CENTER COLSPAN=1>Eggs</TD>
|
||||
<TD ALIGN=CENTER COLSPAN=1>3</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
'''
|
||||
|
||||
import ts_regex
|
||||
import regex
|
||||
from ts_regex import gsub
|
||||
from string import split, join, strip, find
|
||||
import string,re
|
||||
|
||||
|
||||
def untabify(aString,
|
||||
indent_tab=ts_regex.compile('\(\n\|^\)\( *\)\t').search_group,
|
||||
):
|
||||
'''\
|
||||
Convert indentation tabs to spaces.
|
||||
'''
|
||||
result=''
|
||||
rest=aString
|
||||
while 1:
|
||||
ts_results = indent_tab(rest, (1,2))
|
||||
if ts_results:
|
||||
start, grps = ts_results
|
||||
lnl=len(grps[0])
|
||||
indent=len(grps[1])
|
||||
result=result+rest[:start]
|
||||
rest="\n%s%s" % (' ' * ((indent/8+1)*8),
|
||||
rest[start+indent+1+lnl:])
|
||||
else:
|
||||
return result+rest
|
||||
|
||||
def indent(aString, indent=2):
|
||||
"""Indent a string the given number of spaces"""
|
||||
r=split(untabify(aString),'\n')
|
||||
if not r: return ''
|
||||
if not r[-1]: del r[-1]
|
||||
tab=' '*level
|
||||
return "%s%s\n" % (tab,join(r,'\n'+tab))
|
||||
|
||||
def reindent(aString, indent=2, already_untabified=0):
|
||||
"reindent a block of text, so that the minimum indent is as given"
|
||||
|
||||
if not already_untabified: aString=untabify(aString)
|
||||
|
||||
l=indent_level(aString)[0]
|
||||
if indent==l: return aString
|
||||
|
||||
r=[]
|
||||
|
||||
append=r.append
|
||||
|
||||
if indent > l:
|
||||
tab=' ' * (indent-l)
|
||||
for s in split(aString,'\n'): append(tab+s)
|
||||
else:
|
||||
l=l-indent
|
||||
for s in split(aString,'\n'): append(s[l:])
|
||||
|
||||
return join(r,'\n')
|
||||
|
||||
def indent_level(aString,
|
||||
indent_space=ts_regex.compile('\n\( *\)').search_group,
|
||||
):
|
||||
'''\
|
||||
Find the minimum indentation for a string, not counting blank lines.
|
||||
'''
|
||||
start=0
|
||||
text='\n'+aString
|
||||
indent=l=len(text)
|
||||
while 1:
|
||||
|
||||
ts_results = indent_space(text, (1,2), start)
|
||||
if ts_results:
|
||||
start, grps = ts_results
|
||||
i=len(grps[0])
|
||||
start=start+i+1
|
||||
if start < l and text[start] != '\n': # Skip blank lines
|
||||
if not i: return (0,aString)
|
||||
if i < indent: indent = i
|
||||
else:
|
||||
return (indent,aString)
|
||||
|
||||
def paragraphs(list,start):
|
||||
l=len(list)
|
||||
level=list[start][0]
|
||||
i=start+1
|
||||
while i < l and list[i][0] > level: i=i+1
|
||||
return i-1-start
|
||||
|
||||
def structure(list):
|
||||
if not list: return []
|
||||
i=0
|
||||
l=len(list)
|
||||
r=[]
|
||||
while i < l:
|
||||
sublen=paragraphs(list,i)
|
||||
i=i+1
|
||||
r.append((list[i-1][1],structure(list[i:i+sublen])))
|
||||
i=i+sublen
|
||||
return r
|
||||
|
||||
|
||||
class Table:
|
||||
CELL=' <TD ALIGN=CENTER COLSPAN=%i>%s</TD>\n'
|
||||
ROW=' <TR>\n%s </TR>\n'
|
||||
TABLE='\n<TABLE BORDER=1 CELLPADDING=2>\n%s</TABLE>'
|
||||
|
||||
def create(self,aPar,
|
||||
td_reg=re.compile(r'[ \t\n]*\|\|([^\0x00|]*)')
|
||||
):
|
||||
'''parses a table and returns nested list representing the
|
||||
table'''
|
||||
self.table=[]
|
||||
text=filter(None,split(aPar,'\n'))
|
||||
for line in text:
|
||||
row=[]
|
||||
while 1:
|
||||
mo = td_reg.match(line)
|
||||
if not mo: return 0
|
||||
pos = mo.end(1)
|
||||
row.append(mo.group(1))
|
||||
if pos==len(line):break
|
||||
line=line[pos:]
|
||||
self.table.append(row)
|
||||
return 1
|
||||
|
||||
def html(self):
|
||||
'''Creates an HTML representation of table'''
|
||||
htmltable=[]
|
||||
for row in self.table:
|
||||
htmlrow=[]
|
||||
colspan=1
|
||||
for cell in row:
|
||||
if cell=='':
|
||||
colspan=colspan+1
|
||||
continue
|
||||
else:
|
||||
htmlrow.append(self.CELL%(colspan,cell))
|
||||
colspan=1
|
||||
htmltable.append(self.ROW%join(htmlrow,''))
|
||||
return self.TABLE%join(htmltable,'')
|
||||
|
||||
table=Table()
|
||||
|
||||
class StructuredText:
|
||||
|
||||
"""Model text as structured collection of paragraphs.
|
||||
|
||||
Structure is implied by the indentation level.
|
||||
|
||||
This class is intended as a base classes that do actual text
|
||||
output formatting.
|
||||
"""
|
||||
|
||||
def __init__(self, aStructuredString, level=0,
|
||||
paragraph_divider=regex.compile('\(\r?\n *\)+\r?\n'),
|
||||
):
|
||||
'''Convert a structured text string into a structured text object.
|
||||
|
||||
Aguments:
|
||||
|
||||
aStructuredString -- The string to be parsed.
|
||||
level -- The level of top level headings to be created.
|
||||
'''
|
||||
|
||||
|
||||
pat = ' \"([%s0-9-_,./?=@~&]*)\":' % string.letters+ \
|
||||
'([-:%s0-9_,./?=@#~&]*?)' % string.letters + \
|
||||
'([.:?;] )'
|
||||
|
||||
p_reg = re.compile(pat,re.M)
|
||||
|
||||
aStructuredString = p_reg.sub(r'<a href="\2">\1</a>\3 ' , aStructuredString)
|
||||
|
||||
pat = ' \"([%s0-9-_,./?=@~&]*)\", ' % string.letters+ \
|
||||
'([-:%s0-9_,./?=@#~&]*?)' % string.letters + \
|
||||
'([.:?;] )'
|
||||
|
||||
p_reg = re.compile(pat,re.M)
|
||||
|
||||
aStructuredString = p_reg.sub(r'<a href="\2">\1</a>\3 ' , aStructuredString)
|
||||
|
||||
|
||||
protoless = find(aStructuredString, '<a href=":')
|
||||
if protoless != -1:
|
||||
aStructuredString = re.sub('<a href=":', '<a href="',
|
||||
aStructuredString)
|
||||
|
||||
self.level=level
|
||||
paragraphs=ts_regex.split(untabify(aStructuredString),
|
||||
paragraph_divider)
|
||||
paragraphs=map(indent_level,paragraphs)
|
||||
|
||||
self.structure=structure(paragraphs)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return str(self.structure)
|
||||
|
||||
|
||||
ctag_prefix=r'([\x00- \\(]|^)'
|
||||
ctag_suffix=r'([\x00- ,.:;!?\\)]|$)'
|
||||
ctag_middle=r'[%s]([^\x00- %s][^%s]*[^\x00- %s]|[^%s])[%s]'
|
||||
ctag_middl2=r'[%s][%s]([^\x00- %s][^%s]*[^\x00- %s]|[^%s])[%s][%s]'
|
||||
|
||||
def ctag(s,
|
||||
em=re.compile(
|
||||
ctag_prefix+(ctag_middle % (("*",)*6) )+ctag_suffix),
|
||||
strong=re.compile(
|
||||
ctag_prefix+(ctag_middl2 % (("*",)*8))+ctag_suffix),
|
||||
under=re.compile(
|
||||
ctag_prefix+(ctag_middle % (("_",)*6) )+ctag_suffix),
|
||||
code=re.compile(
|
||||
ctag_prefix+(ctag_middle % (("\'",)*6))+ctag_suffix),
|
||||
):
|
||||
if s is None: s=''
|
||||
s=strong.sub(r'\1<strong>\2</strong>\3',s)
|
||||
s=under.sub( r'\1<u>\2</u>\3',s)
|
||||
s=code.sub( r'\1<code>\2</code>\3',s)
|
||||
s=em.sub( r'\1<em>\2</em>\3',s)
|
||||
return s
|
||||
|
||||
class HTML(StructuredText):
|
||||
|
||||
'''\
|
||||
An HTML structured text formatter.
|
||||
'''\
|
||||
|
||||
def __str__(self,
|
||||
extra_dl=re.compile("</dl>\n<dl>"),
|
||||
extra_ul=re.compile("</ul>\n<ul>"),
|
||||
extra_ol=re.compile("</ol>\n<ol>"),
|
||||
):
|
||||
'''\
|
||||
Return an HTML string representation of the structured text data.
|
||||
|
||||
'''
|
||||
s=self._str(self.structure,self.level)
|
||||
s=extra_dl.sub('\n',s)
|
||||
s=extra_ul.sub('\n',s)
|
||||
s=extra_ol.sub('\n',s)
|
||||
return s
|
||||
|
||||
def ul(self, before, p, after):
|
||||
if p: p="<p>%s</p>" % strip(ctag(p))
|
||||
return ('%s<ul><li>%s\n%s\n</li></ul>\n'
|
||||
% (before,p,after))
|
||||
|
||||
def ol(self, before, p, after):
|
||||
if p: p="<p>%s</p>" % strip(ctag(p))
|
||||
return ('%s<ol><li>%s\n%s\n</li></ol>\n'
|
||||
% (before,p,after))
|
||||
|
||||
def dl(self, before, t, d, after):
|
||||
return ('%s<dl><dt>%s</dt><dd><p>%s</p>\n%s\n</dd></dl>\n'
|
||||
% (before,ctag(t),ctag(d),after))
|
||||
|
||||
def head(self, before, t, level, d):
|
||||
if level > 0 and level < 6:
|
||||
return ('%s<h%d>%s</h%d>\n%s\n'
|
||||
% (before,level,strip(ctag(t)),level,d))
|
||||
|
||||
t="<p><strong>%s</strong></p>" % strip(ctag(t))
|
||||
return ('%s<dl><dt>%s\n</dt><dd>%s\n</dd></dl>\n'
|
||||
% (before,t,d))
|
||||
|
||||
def normal(self,before,p,after):
|
||||
return '%s<p>%s</p>\n%s\n' % (before,ctag(p),after)
|
||||
|
||||
def pre(self,structure,tagged=0):
|
||||
if not structure: return ''
|
||||
if tagged:
|
||||
r=''
|
||||
else:
|
||||
r='<PRE>\n'
|
||||
for s in structure:
|
||||
r="%s%s\n\n%s" % (r,html_quote(s[0]),self.pre(s[1],1))
|
||||
if not tagged: r=r+'</PRE>\n'
|
||||
return r
|
||||
|
||||
def table(self,before,table,after):
|
||||
return '%s<p>%s</p>\n%s\n' % (before,ctag(table),after)
|
||||
|
||||
def _str(self,structure,level,
|
||||
# Static
|
||||
bullet=ts_regex.compile('[ \t\n]*[o*-][ \t\n]+\([^\0]*\)'
|
||||
).match_group,
|
||||
example=ts_regex.compile('[\0- ]examples?:[\0- ]*$'
|
||||
).search,
|
||||
dl=ts_regex.compile('\([^\n]+\)[ \t]+--[ \t\n]+\([^\0]*\)'
|
||||
).match_group,
|
||||
nl=ts_regex.compile('\n').search,
|
||||
ol=ts_regex.compile(
|
||||
'[ \t]*\(\([0-9]+\|[%s]+\)[.)]\)+[ \t\n]+\([^\0]*\|$\)' % string.letters
|
||||
).match_group,
|
||||
olp=ts_regex.compile('[ \t]*([0-9]+)[ \t\n]+\([^\0]*\|$\)'
|
||||
).match_group,
|
||||
):
|
||||
r=''
|
||||
for s in structure:
|
||||
|
||||
ts_results = bullet(s[0], (1,))
|
||||
if ts_results:
|
||||
p = ts_results[1]
|
||||
if s[0][-2:]=='::' and s[1]: ps=self.pre(s[1])
|
||||
else: ps=self._str(s[1],level)
|
||||
r=self.ul(r,p,ps)
|
||||
continue
|
||||
ts_results = ol(s[0], (3,))
|
||||
if ts_results:
|
||||
p = ts_results[1]
|
||||
if s[0][-2:]=='::' and s[1]: ps=self.pre(s[1])
|
||||
else: ps=self._str(s[1],level)
|
||||
r=self.ol(r,p,ps)
|
||||
continue
|
||||
ts_results = olp(s[0], (1,))
|
||||
if ts_results:
|
||||
p = ts_results[1]
|
||||
if s[0][-2:]=='::' and s[1]: ps=self.pre(s[1])
|
||||
else: ps=self._str(s[1],level)
|
||||
r=self.ol(r,p,ps)
|
||||
continue
|
||||
ts_results = dl(s[0], (1,2))
|
||||
if ts_results:
|
||||
t,d = ts_results[1]
|
||||
r=self.dl(r,t,d,self._str(s[1],level))
|
||||
continue
|
||||
if example(s[0]) >= 0 and s[1]:
|
||||
# Introduce an example, using pre tags:
|
||||
r=self.normal(r,s[0],self.pre(s[1]))
|
||||
continue
|
||||
if s[0][-2:]=='::' and s[1]:
|
||||
# Introduce an example, using pre tags:
|
||||
r=self.normal(r,s[0][:-1],self.pre(s[1]))
|
||||
continue
|
||||
if table.create(s[0]):
|
||||
## table support.
|
||||
r=self.table(r,table.html(),self._str(s[1],level))
|
||||
continue
|
||||
else:
|
||||
|
||||
if nl(s[0]) < 0 and s[1] and s[0][-1:] != ':':
|
||||
# Treat as a heading
|
||||
t=s[0]
|
||||
r=self.head(r,t,level,
|
||||
self._str(s[1],level and level+1))
|
||||
else:
|
||||
r=self.normal(r,s[0],self._str(s[1],level))
|
||||
return r
|
||||
|
||||
|
||||
def html_quote(v,
|
||||
character_entities=(
|
||||
(re.compile('&'), '&'),
|
||||
(re.compile("<"), '<' ),
|
||||
(re.compile(">"), '>' ),
|
||||
(re.compile('"'), '"')
|
||||
)): #"
|
||||
text=str(v)
|
||||
for re,name in character_entities:
|
||||
text=re.sub(name,text)
|
||||
return text
|
||||
|
||||
def html_with_references(text, level=1):
|
||||
text = re.sub(
|
||||
r'[\0\n]\.\. \[([0-9_%s-]+)\]' % string.letters,
|
||||
r'\n <a name="\1">[\1]</a>',
|
||||
text)
|
||||
|
||||
text = re.sub(
|
||||
r'([\x00- ,])\[(?P<ref>[0-9_%s-]+)\]([\x00- ,.:])' % string.letters,
|
||||
r'\1<a href="#\2">[\2]</a>\3',
|
||||
text)
|
||||
|
||||
text = re.sub(
|
||||
r'([\0- ,])\[([^]]+)\.html\]([\0- ,.:])',
|
||||
r'\1<a href="\2.html">[\2]</a>\3',
|
||||
text)
|
||||
|
||||
return HTML(text,level=level)
|
||||
|
||||
|
||||
def main():
|
||||
import sys, getopt
|
||||
|
||||
opts,args=getopt.getopt(sys.argv[1:],'twl')
|
||||
|
||||
if args:
|
||||
[infile]=args
|
||||
s=open(infile,'r').read()
|
||||
else:
|
||||
s=sys.stdin.read()
|
||||
|
||||
if opts:
|
||||
|
||||
if filter(lambda o: o[0]=='-w', opts):
|
||||
print 'Content-Type: text/html\n'
|
||||
|
||||
if filter(lambda o: o[0]=='-l', opts):
|
||||
import locale
|
||||
locale.setlocale(locale.LC_ALL,"")
|
||||
|
||||
if s[:2]=='#!':
|
||||
s=re.sub('^#![^\n]+','',s)
|
||||
|
||||
mo = re.compile('([\0-\n]*\n)').match(s)
|
||||
if mo is not None:
|
||||
s = s[len(mo.group(0)) :]
|
||||
|
||||
s=str(html_with_references(s))
|
||||
if s[:4]=='<h1>':
|
||||
t=s[4:find(s,'</h1>')]
|
||||
s='''<html><head><title>%s</title>
|
||||
</head><body>
|
||||
%s
|
||||
</body></html>
|
||||
''' % (t,s)
|
||||
print s
|
||||
else:
|
||||
print html_with_references(s)
|
||||
|
||||
if __name__=="__main__": main()
|
@@ -1,332 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import string
|
||||
from string import join, split, find, lstrip
|
||||
|
||||
class DocBookClass:
|
||||
|
||||
element_types={
|
||||
'#text': '_text',
|
||||
'StructuredTextDocument': 'document',
|
||||
'StructuredTextParagraph': 'paragraph',
|
||||
'StructuredTextExample': 'example',
|
||||
'StructuredTextBullet': 'bullet',
|
||||
'StructuredTextNumbered': 'numbered',
|
||||
'StructuredTextDescription': 'description',
|
||||
'StructuredTextDescriptionTitle': 'descriptionTitle',
|
||||
'StructuredTextDescriptionBody': 'descriptionBody',
|
||||
'StructuredTextSection': 'section',
|
||||
'StructuredTextSectionTitle': 'sectionTitle',
|
||||
'StructuredTextLiteral': 'literal',
|
||||
'StructuredTextEmphasis': 'emphasis',
|
||||
'StructuredTextStrong': 'strong',
|
||||
'StructuredTextLink': 'link',
|
||||
'StructuredTextXref': 'xref',
|
||||
'StructuredTextSGML': 'sgml',
|
||||
}
|
||||
|
||||
def dispatch(self, doc, level, output):
|
||||
getattr(self, self.element_types[doc.getNodeName()])(doc, level, output)
|
||||
|
||||
def __call__(self, doc, level=1):
|
||||
r=[]
|
||||
self.dispatch(doc, level-1, r.append)
|
||||
return join(r,'')
|
||||
|
||||
def _text(self, doc, level, output):
|
||||
if doc.getNodeName() == 'StructuredTextLiteral':
|
||||
output(doc.getNodeValue())
|
||||
else:
|
||||
output(lstrip(doc.getNodeValue()))
|
||||
|
||||
def document(self, doc, level, output):
|
||||
output('<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">\n')
|
||||
output('<book>\n')
|
||||
children=doc.getChildNodes()
|
||||
if (children and
|
||||
children[0].getNodeName() == 'StructuredTextSection'):
|
||||
output('<title>%s</title>' % children[0].getChildNodes()[0].getNodeValue())
|
||||
for c in children:
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</book>\n')
|
||||
|
||||
def section(self, doc, level, output):
|
||||
output('\n<section>\n')
|
||||
children=doc.getChildNodes()
|
||||
for c in children:
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level+1, output)
|
||||
output('\n</section>\n')
|
||||
|
||||
def sectionTitle(self, doc, level, output):
|
||||
output('<title>')
|
||||
for c in doc.getChildNodes():
|
||||
try:
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
except:
|
||||
print "failed", c.getNodeName(), c
|
||||
output('</title>\n')
|
||||
|
||||
def description(self, doc, level, output):
|
||||
p=doc.getPreviousSibling()
|
||||
if p is None or p.getNodeName() is not doc.getNodeName():
|
||||
output('<variablelist>\n')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
n=doc.getNextSibling()
|
||||
if n is None or n.getNodeName() is not doc.getNodeName():
|
||||
output('</variablelist>\n')
|
||||
|
||||
def descriptionTitle(self, doc, level, output):
|
||||
output('<varlistentry><term>\n')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</term>\n')
|
||||
|
||||
def descriptionBody(self, doc, level, output):
|
||||
output('<listitem><para>\n')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</para></listitem>\n')
|
||||
output('</varlistentry>\n')
|
||||
|
||||
def bullet(self, doc, level, output):
|
||||
p=doc.getPreviousSibling()
|
||||
if p is None or p.getNodeName() is not doc.getNodeName():
|
||||
output('<itemizedlist>\n')
|
||||
output('<listitem><para>\n')
|
||||
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
n=doc.getNextSibling()
|
||||
output('</para></listitem>\n')
|
||||
if n is None or n.getNodeName() is not doc.getNodeName():
|
||||
output('</itemizedlist>\n')
|
||||
|
||||
def numbered(self, doc, level, output):
|
||||
p=doc.getPreviousSibling()
|
||||
if p is None or p.getNodeName() is not doc.getNodeName():
|
||||
output('<orderedlist>\n')
|
||||
output('<listitem><para>\n')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
n=doc.getNextSibling()
|
||||
output('</para></listitem>\n')
|
||||
if n is None or n.getNodeName() is not doc.getNodeName():
|
||||
output('</orderedlist>\n')
|
||||
|
||||
def example(self, doc, level, output):
|
||||
i=0
|
||||
for c in doc.getChildNodes():
|
||||
if i==0:
|
||||
output('<programlisting>\n<![CDATA[\n')
|
||||
##
|
||||
## eek. A ']]>' in your body will break this...
|
||||
##
|
||||
output(prestrip(c.getNodeValue()))
|
||||
output('\n]]></programlisting>\n')
|
||||
else:
|
||||
getattr(self, self.element_types[c.getNodeName()])(
|
||||
c, level, output)
|
||||
|
||||
def paragraph(self, doc, level, output):
|
||||
output('<para>\n\n')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(
|
||||
c, level, output)
|
||||
output('</para>\n\n')
|
||||
|
||||
def link(self, doc, level, output):
|
||||
output('<ulink url="%s">' % doc.href)
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</ulink>')
|
||||
|
||||
def emphasis(self, doc, level, output):
|
||||
output('<emphasis>')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</emphasis> ')
|
||||
|
||||
def literal(self, doc, level, output):
|
||||
output('<literal>')
|
||||
for c in doc.getChildNodes():
|
||||
output(c.getNodeValue())
|
||||
output('</literal>')
|
||||
|
||||
def strong(self, doc, level, output):
|
||||
output('<emphasis>')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</emphasis>')
|
||||
|
||||
def xref(self, doc, level, output):
|
||||
output('<xref linkend="%s"/>' % doc.getNodeValue())
|
||||
|
||||
def sgml(self, doc, level, output):
|
||||
output(doc.getNodeValue())
|
||||
|
||||
|
||||
def prestrip(v):
|
||||
v=string.replace(v, '\r\n', '\n')
|
||||
v=string.replace(v, '\r', '\n')
|
||||
v=string.replace(v, '\t', ' ')
|
||||
lines=string.split(v, '\n')
|
||||
indent=len(lines[0])
|
||||
for line in lines:
|
||||
if not len(line): continue
|
||||
i=len(line)-len(string.lstrip(line))
|
||||
if i < indent:
|
||||
indent=i
|
||||
nlines=[]
|
||||
for line in lines:
|
||||
nlines.append(line[indent:])
|
||||
return string.join(nlines, '\n')
|
||||
|
||||
|
||||
class DocBookChapter(DocBookClass):
|
||||
|
||||
def document(self, doc, level, output):
|
||||
output('<chapter>\n')
|
||||
children=doc.getChildNodes()
|
||||
if (children and
|
||||
children[0].getNodeName() == 'StructuredTextSection'):
|
||||
output('<title>%s</title>' % children[0].getChildNodes()[0].getNodeValue())
|
||||
for c in children[0].getChildNodes()[1:]:
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</chapter>\n')
|
||||
|
||||
ets = DocBookClass.element_types
|
||||
ets.update({'StructuredTextImage': 'image'})
|
||||
|
||||
class DocBookChapterWithFigures(DocBookChapter):
|
||||
|
||||
element_types = ets
|
||||
|
||||
def image(self, doc, level, output):
|
||||
if hasattr(doc, 'key'):
|
||||
output('<figure id="%s"><title>%s</title>\n' % (doc.key, doc.getNodeValue()) )
|
||||
else:
|
||||
output('<figure><title>%s</title>\n' % doc.getNodeValue())
|
||||
## for c in doc.getChildNodes():
|
||||
## getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('<graphic fileref="%s"></graphic>\n</figure>\n' % doc.href)
|
||||
|
||||
class DocBookArticle(DocBookClass):
|
||||
|
||||
def document(self, doc, level, output):
|
||||
output('<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN">\n')
|
||||
output('<article>\n')
|
||||
children=doc.getChildNodes()
|
||||
if (children and
|
||||
children[0].getNodeName() == 'StructuredTextSection'):
|
||||
output('<articleinfo>\n<title>%s</title>\n</articleinfo>\n' %
|
||||
children[0].getChildNodes()[0].getNodeValue())
|
||||
for c in children:
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</article>\n')
|
||||
|
||||
|
||||
class DocBookBook:
|
||||
|
||||
def __init__(self, title=''):
|
||||
self.title = title
|
||||
self.chapters = []
|
||||
|
||||
def addChapter(self, chapter):
|
||||
self.chapters.append(chapter)
|
||||
|
||||
def read(self):
|
||||
out = '<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">\n<book>\n'
|
||||
out = out + '<title>%s</title>\n' % self.title
|
||||
for chapter in self.chapters:
|
||||
out = out + chapter + '\n</book>\n'
|
||||
|
||||
return out
|
||||
|
||||
def __str__(self):
|
||||
return self.read()
|
||||
|
||||
|
@@ -1,998 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import re, ST, STDOM
|
||||
from string import split, join, replace, expandtabs, strip, find, rstrip
|
||||
from STletters import *
|
||||
|
||||
|
||||
StringType=type('')
|
||||
ListType=type([])
|
||||
|
||||
def flatten(obj, append):
|
||||
if obj.getNodeType()==STDOM.TEXT_NODE:
|
||||
append(obj.getNodeValue())
|
||||
else:
|
||||
for child in obj.getChildNodes():
|
||||
flatten(child, append)
|
||||
|
||||
|
||||
class StructuredTextExample(ST.StructuredTextParagraph):
|
||||
"""Represents a section of document with literal text, as for examples"""
|
||||
|
||||
def __init__(self, subs, **kw):
|
||||
t=[]
|
||||
a=t.append
|
||||
for s in subs:
|
||||
flatten(s, a)
|
||||
apply(ST.StructuredTextParagraph.__init__,
|
||||
(self, join(t,'\n\n'), ()),
|
||||
kw)
|
||||
|
||||
def getColorizableTexts(self): return ()
|
||||
def setColorizableTexts(self, src): pass # never color examples
|
||||
|
||||
class StructuredTextBullet(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextNumbered(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextDescriptionTitle(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextDescriptionBody(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextDescription(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
def __init__(self, title, src, subs, **kw):
|
||||
apply(ST.StructuredTextParagraph.__init__, (self, src, subs), kw)
|
||||
self._title=title
|
||||
|
||||
def getColorizableTexts(self): return self._title, self._src
|
||||
def setColorizableTexts(self, src): self._title, self._src = src
|
||||
|
||||
def getChildren(self):
|
||||
return (StructuredTextDescriptionTitle(self._title),
|
||||
StructuredTextDescriptionBody(self._src, self._subs))
|
||||
|
||||
class StructuredTextSectionTitle(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
|
||||
class StructuredTextSection(ST.StructuredTextParagraph):
|
||||
"""Represents a section of a document with a title and a body"""
|
||||
def __init__(self, src, subs=None, **kw):
|
||||
apply(ST.StructuredTextParagraph.__init__,
|
||||
(self, StructuredTextSectionTitle(src), subs),
|
||||
kw)
|
||||
|
||||
def getColorizableTexts(self):
|
||||
return self._src.getColorizableTexts()
|
||||
|
||||
def setColorizableTexts(self,src):
|
||||
self._src.setColorizableTexts(src)
|
||||
|
||||
# a StructuredTextTable holds StructuredTextRows
|
||||
class StructuredTextTable(ST.StructuredTextParagraph):
|
||||
"""
|
||||
rows is a list of lists containing tuples, which
|
||||
represent the columns/cells in each rows.
|
||||
EX
|
||||
rows = [[('row 1:column1',1)],[('row2:column1',1)]]
|
||||
"""
|
||||
|
||||
def __init__(self, rows, src, subs, **kw):
|
||||
apply(ST.StructuredTextParagraph.__init__,(self,subs),kw)
|
||||
self._rows = []
|
||||
for row in rows:
|
||||
if row:
|
||||
self._rows.append(StructuredTextRow(row,kw))
|
||||
|
||||
def getRows(self):
|
||||
return [self._rows]
|
||||
|
||||
def _getRows(self):
|
||||
return self.getRows()
|
||||
|
||||
def getColumns(self):
|
||||
result = []
|
||||
for row in self._rows:
|
||||
result.append(row.getColumns())
|
||||
return result
|
||||
|
||||
def _getColumns(self):
|
||||
return self.getColumns()
|
||||
|
||||
def setColumns(self,columns):
|
||||
for index in range(len(self._rows)):
|
||||
self._rows[index].setColumns(columns[index])
|
||||
|
||||
def _setColumns(self,columns):
|
||||
return self.setColumns(columns)
|
||||
|
||||
def getColorizableTexts(self):
|
||||
"""
|
||||
return a tuple where each item is a column/cell's
|
||||
contents. The tuple, result, will be of this format.
|
||||
("r1 col1", "r1=col2", "r2 col1", "r2 col2")
|
||||
"""
|
||||
|
||||
result = []
|
||||
for row in self._rows:
|
||||
for column in row.getColumns()[0]:
|
||||
result.append(column.getColorizableTexts()[0])
|
||||
return result
|
||||
|
||||
def setColorizableTexts(self,texts):
|
||||
"""
|
||||
texts is going to a tuple where each item is the
|
||||
result of being mapped to the colortext function.
|
||||
Need to insert the results appropriately into the
|
||||
individual columns/cells
|
||||
"""
|
||||
for row_index in range(len(self._rows)):
|
||||
for column_index in range(len(self._rows[row_index]._columns)):
|
||||
self._rows[row_index]._columns[column_index].setColorizableTexts((texts[0],))
|
||||
texts = texts[1:]
|
||||
|
||||
def _getColorizableTexts(self):
|
||||
return self.getColorizableTexts()
|
||||
|
||||
def _setColorizableTexts(self):
|
||||
return self.setColorizableTexts()
|
||||
|
||||
# StructuredTextRow holds StructuredTextColumns
|
||||
class StructuredTextRow(ST.StructuredTextParagraph):
|
||||
|
||||
def __init__(self,row,kw):
|
||||
"""
|
||||
row is a list of tuples, where each tuple is
|
||||
the raw text for a cell/column and the span
|
||||
of that cell/column.
|
||||
EX
|
||||
[('this is column one',1), ('this is column two',1)]
|
||||
"""
|
||||
|
||||
apply(ST.StructuredTextParagraph.__init__,(self,[]),kw)
|
||||
|
||||
self._columns = []
|
||||
for column in row:
|
||||
self._columns.append(StructuredTextColumn(column[0],
|
||||
column[1],
|
||||
column[2],
|
||||
column[3],
|
||||
column[4],
|
||||
kw))
|
||||
|
||||
def getColumns(self):
|
||||
return [self._columns]
|
||||
|
||||
def _getColumns(self):
|
||||
return [self._columns]
|
||||
|
||||
def setColumns(self,columns):
|
||||
self._columns = columns
|
||||
|
||||
def _setColumns(self,columns):
|
||||
return self.setColumns(columns)
|
||||
|
||||
# this holds the text of a table cell
|
||||
class StructuredTextColumn(ST.StructuredTextParagraph):
|
||||
"""
|
||||
StructuredTextColumn is a cell/column in a table.
|
||||
A cell can hold multiple paragraphs. The cell
|
||||
is either classified as a StructuredTextTableHeader
|
||||
or StructuredTextTableData.
|
||||
"""
|
||||
|
||||
def __init__(self,text,span,align,valign,typ,kw):
|
||||
apply(ST.StructuredTextParagraph.__init__,(self,text,[]),kw)
|
||||
self._span = span
|
||||
self._align = align
|
||||
self._valign = valign
|
||||
self._type = typ
|
||||
|
||||
def getSpan(self):
|
||||
return self._span
|
||||
|
||||
def _getSpan(self):
|
||||
return self._span
|
||||
|
||||
def getAlign(self):
|
||||
return self._align
|
||||
|
||||
def _getAlign(self):
|
||||
return self.getAlign()
|
||||
|
||||
def getValign(self):
|
||||
return self._valign
|
||||
|
||||
def _getValign(self):
|
||||
return self.getValign()
|
||||
|
||||
def getType(self):
|
||||
return self._type
|
||||
|
||||
def _getType(self):
|
||||
return self.getType()
|
||||
|
||||
class StructuredTextTableHeader(ST.StructuredTextParagraph): pass
|
||||
|
||||
class StructuredTextTableData(ST.StructuredTextParagraph): pass
|
||||
|
||||
class StructuredTextMarkup(STDOM.Element):
|
||||
|
||||
def __init__(self, v, **kw):
|
||||
self._value=v
|
||||
self._attributes=kw.keys()
|
||||
for k, v in kw.items(): setattr(self, k, v)
|
||||
|
||||
def getChildren(self, type=type, lt=type([])):
|
||||
v=self._value
|
||||
if type(v) is not lt: v=[v]
|
||||
return v
|
||||
|
||||
def getColorizableTexts(self): return self._value,
|
||||
def setColorizableTexts(self, v): self._value=v[0]
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (self.__class__.__name__, `self._value`)
|
||||
|
||||
class StructuredTextLiteral(StructuredTextMarkup):
|
||||
def getColorizableTexts(self): return ()
|
||||
def setColorizableTexts(self, v): pass
|
||||
|
||||
class StructuredTextEmphasis(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextStrong(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextInnerLink(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextNamedLink(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextUnderline(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextSGML(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextLink(StructuredTextMarkup): pass
|
||||
|
||||
class StructuredTextXref(StructuredTextMarkup): pass
|
||||
|
||||
class DocumentClass:
|
||||
"""
|
||||
Class instance calls [ex.=> x()] require a structured text
|
||||
structure. Doc will then parse each paragraph in the structure
|
||||
and will find the special structures within each paragraph.
|
||||
Each special structure will be stored as an instance. Special
|
||||
structures within another special structure are stored within
|
||||
the 'top' structure
|
||||
EX : '-underline this-' => would be turned into an underline
|
||||
instance. '-underline **this**' would be stored as an underline
|
||||
instance with a strong instance stored in its string
|
||||
"""
|
||||
|
||||
paragraph_types = [
|
||||
'doc_bullet',
|
||||
'doc_numbered',
|
||||
'doc_description',
|
||||
'doc_header',
|
||||
'doc_table',
|
||||
]
|
||||
|
||||
#'doc_inner_link',
|
||||
#'doc_named_link',
|
||||
#'doc_underline',
|
||||
text_types = [
|
||||
'doc_sgml',
|
||||
'doc_href',
|
||||
'doc_strong',
|
||||
'doc_emphasize',
|
||||
'doc_literal',
|
||||
'doc_sgml',
|
||||
'doc_xref',
|
||||
]
|
||||
|
||||
def __call__(self, doc):
|
||||
if type(doc) is type(''):
|
||||
doc=ST.StructuredText(doc)
|
||||
doc.setSubparagraphs(self.color_paragraphs(
|
||||
doc.getSubparagraphs()))
|
||||
else:
|
||||
doc=ST.StructuredTextDocument(self.color_paragraphs(
|
||||
doc.getSubparagraphs()))
|
||||
return doc
|
||||
|
||||
def parse(self, raw_string, text_type,
|
||||
type=type, st=type(''), lt=type([])):
|
||||
|
||||
"""
|
||||
Parse accepts a raw_string, an expr to test the raw_string,
|
||||
and the raw_string's subparagraphs.
|
||||
|
||||
Parse will continue to search through raw_string until
|
||||
all instances of expr in raw_string are found.
|
||||
|
||||
If no instances of expr are found, raw_string is returned.
|
||||
Otherwise a list of substrings and instances is returned
|
||||
"""
|
||||
|
||||
tmp = [] # the list to be returned if raw_string is split
|
||||
append=tmp.append
|
||||
|
||||
if type(text_type) is st: text_type=getattr(self, text_type)
|
||||
|
||||
while 1:
|
||||
t = text_type(raw_string)
|
||||
if not t: break
|
||||
#an instance of expr was found
|
||||
t, start, end = t
|
||||
|
||||
if start: append(raw_string[0:start])
|
||||
|
||||
tt=type(t)
|
||||
if tt is st:
|
||||
# if we get a string back, add it to text to be parsed
|
||||
raw_string = t+raw_string[end:len(raw_string)]
|
||||
else:
|
||||
if tt is lt:
|
||||
# is we get a list, append it's elements
|
||||
tmp[len(tmp):]=t
|
||||
else:
|
||||
# normal case, an object
|
||||
append(t)
|
||||
raw_string = raw_string[end:len(raw_string)]
|
||||
|
||||
if not tmp: return raw_string # nothing found
|
||||
|
||||
if raw_string: append(raw_string)
|
||||
elif len(tmp)==1: return tmp[0]
|
||||
|
||||
return tmp
|
||||
|
||||
|
||||
def color_text(self, str, types=None):
|
||||
"""Search the paragraph for each special structure
|
||||
"""
|
||||
if types is None: types=self.text_types
|
||||
|
||||
for text_type in types:
|
||||
|
||||
if type(str) is StringType:
|
||||
str = self.parse(str, text_type)
|
||||
elif type(str) is ListType:
|
||||
r=[]; a=r.append
|
||||
for s in str:
|
||||
if type(s) is StringType:
|
||||
s=self.parse(s, text_type)
|
||||
if type(s) is ListType: r[len(r):]=s
|
||||
else: a(s)
|
||||
else:
|
||||
s.setColorizableTexts(
|
||||
map(self.color_text,
|
||||
s.getColorizableTexts()
|
||||
))
|
||||
a(s)
|
||||
str=r
|
||||
else:
|
||||
r=[]; a=r.append; color=self.color_text
|
||||
for s in str.getColorizableTexts():
|
||||
color(s, (text_type,))
|
||||
a(s)
|
||||
|
||||
str.setColorizableTexts(r)
|
||||
|
||||
return str
|
||||
|
||||
def color_paragraphs(self, raw_paragraphs,
|
||||
type=type, sequence_types=(type([]), type(())),
|
||||
st=type('')):
|
||||
result=[]
|
||||
for paragraph in raw_paragraphs:
|
||||
if paragraph.getNodeName() != 'StructuredTextParagraph':
|
||||
result.append(paragraph)
|
||||
continue
|
||||
|
||||
for pt in self.paragraph_types:
|
||||
if type(pt) is st:
|
||||
# grab the corresponding function
|
||||
pt=getattr(self, pt)
|
||||
# evaluate the paragraph
|
||||
r=pt(paragraph)
|
||||
if r:
|
||||
if type(r) not in sequence_types:
|
||||
r=r,
|
||||
new_paragraphs=r
|
||||
for paragraph in new_paragraphs:
|
||||
paragraph.setSubparagraphs(self.color_paragraphs(paragraph.getSubparagraphs()))
|
||||
break
|
||||
else:
|
||||
new_paragraphs=ST.StructuredTextParagraph(paragraph.getColorizableTexts()[0],
|
||||
self.color_paragraphs(paragraph.getSubparagraphs()),
|
||||
indent=paragraph.indent),
|
||||
|
||||
# color the inline StructuredText types
|
||||
# for each StructuredTextParagraph
|
||||
for paragraph in new_paragraphs:
|
||||
|
||||
if paragraph.getNodeName() is "StructuredTextTable":
|
||||
cells = paragraph.getColumns()
|
||||
text = paragraph.getColorizableTexts()
|
||||
text = map(ST.StructuredText,text)
|
||||
text = map(self.__call__,text)
|
||||
for t in range(len(text)):
|
||||
text[t] = text[t].getSubparagraphs()
|
||||
paragraph.setColorizableTexts(text)
|
||||
|
||||
paragraph.setColorizableTexts(
|
||||
map(self.color_text,
|
||||
paragraph.getColorizableTexts()
|
||||
))
|
||||
result.append(paragraph)
|
||||
|
||||
return result
|
||||
|
||||
def doc_table(self, paragraph, expr = re.compile(r'\s*\|[-]+\|').match):
|
||||
text = paragraph.getColorizableTexts()[0]
|
||||
m = expr(text)
|
||||
|
||||
subs = paragraph.getSubparagraphs()
|
||||
|
||||
if not (m):
|
||||
return None
|
||||
rows = []
|
||||
|
||||
spans = []
|
||||
ROWS = []
|
||||
COLS = []
|
||||
indexes = []
|
||||
ignore = []
|
||||
|
||||
TDdivider = re.compile("[\-]+").match
|
||||
THdivider = re.compile("[\=]+").match
|
||||
col = re.compile('\|').search
|
||||
innertable = re.compile('\|([-]+|[=]+)\|').search
|
||||
|
||||
text = strip(text)
|
||||
rows = split(text,'\n')
|
||||
foo = ""
|
||||
|
||||
for row in range(len(rows)):
|
||||
rows[row] = strip(rows[row])
|
||||
|
||||
# have indexes store if a row is a divider
|
||||
# or a cell part
|
||||
for index in range(len(rows)):
|
||||
tmpstr = rows[index][1:len(rows[index])-1]
|
||||
if TDdivider(tmpstr):
|
||||
indexes.append("TDdivider")
|
||||
elif THdivider(tmpstr):
|
||||
indexes.append("THdivider")
|
||||
else:
|
||||
indexes.append("cell")
|
||||
|
||||
for index in range(len(indexes)):
|
||||
if indexes[index] is "TDdivider" or indexes[index] is THdivider:
|
||||
ignore = [] # reset ignore
|
||||
#continue # skip dividers
|
||||
|
||||
tmp = strip(rows[index]) # clean the row up
|
||||
tmp = tmp[1:len(tmp)-1] # remove leading + trailing |
|
||||
offset = 0
|
||||
|
||||
# find the start and end of inner
|
||||
# tables. ignore everything between
|
||||
if innertable(tmp):
|
||||
tmpstr = strip(tmp)
|
||||
while innertable(tmpstr):
|
||||
start,end = innertable(tmpstr).span()
|
||||
if not (start,end-1) in ignore:
|
||||
ignore.append(start,end-1)
|
||||
tmpstr = " " + tmpstr[end:]
|
||||
|
||||
# find the location of column dividers
|
||||
# NOTE: |'s in inner tables do not count
|
||||
# as column dividers
|
||||
if col(tmp):
|
||||
while col(tmp):
|
||||
bar = 1 # true if start is not in ignore
|
||||
start,end = col(tmp).span()
|
||||
|
||||
if not start+offset in spans:
|
||||
for s,e in ignore:
|
||||
if start+offset >= s or start+offset <= e:
|
||||
bar = None
|
||||
break
|
||||
if bar: # start is clean
|
||||
spans.append(start+offset)
|
||||
if not bar:
|
||||
foo = foo + tmp[:end]
|
||||
tmp = tmp[end:]
|
||||
offset = offset + end
|
||||
else:
|
||||
COLS.append((foo + tmp[0:start],start+offset))
|
||||
foo = ""
|
||||
tmp = " " + tmp[end:]
|
||||
offset = offset + start
|
||||
if not offset+len(tmp) in spans:
|
||||
spans.append(offset+len(tmp))
|
||||
COLS.append((foo + tmp,offset+len(tmp)))
|
||||
foo = ""
|
||||
ROWS.append(COLS)
|
||||
COLS = []
|
||||
|
||||
spans.sort()
|
||||
ROWS = ROWS[1:len(ROWS)]
|
||||
|
||||
# find each column span
|
||||
cols = []
|
||||
tmp = []
|
||||
|
||||
for row in ROWS:
|
||||
for c in row:
|
||||
tmp.append(c[1])
|
||||
cols.append(tmp)
|
||||
tmp = []
|
||||
|
||||
cur = 1
|
||||
tmp = []
|
||||
C = []
|
||||
for col in cols:
|
||||
for span in spans:
|
||||
if not span in col:
|
||||
cur = cur + 1
|
||||
else:
|
||||
tmp.append(cur)
|
||||
cur = 1
|
||||
C.append(tmp)
|
||||
tmp = []
|
||||
|
||||
for index in range(len(C)):
|
||||
for i in range(len(C[index])):
|
||||
ROWS[index][i] = (ROWS[index][i][0],C[index][i])
|
||||
rows = ROWS
|
||||
|
||||
# label things as either TableData or
|
||||
# Table header
|
||||
TD = []
|
||||
TH = []
|
||||
all = []
|
||||
for index in range(len(indexes)):
|
||||
if indexes[index] is "TDdivider":
|
||||
TD.append(index)
|
||||
all.append(index)
|
||||
if indexes[index] is "THdivider":
|
||||
TH.append(index)
|
||||
all.append(index)
|
||||
TD = TD[1:]
|
||||
dividers = all[1:]
|
||||
#print "TD => ", TD
|
||||
#print "TH => ", TH
|
||||
#print "all => ", all, "\n"
|
||||
|
||||
for div in dividers:
|
||||
if div in TD:
|
||||
index = all.index(div)
|
||||
for rowindex in range(all[index-1],all[index]):
|
||||
for i in range(len(rows[rowindex])):
|
||||
rows[rowindex][i] = (rows[rowindex][i][0],
|
||||
rows[rowindex][i][1],
|
||||
"td")
|
||||
else:
|
||||
index = all.index(div)
|
||||
for rowindex in range(all[index-1],all[index]):
|
||||
for i in range(len(rows[rowindex])):
|
||||
rows[rowindex][i] = (rows[rowindex][i][0],
|
||||
rows[rowindex][i][1],
|
||||
"th")
|
||||
|
||||
# now munge the multi-line cells together
|
||||
# as paragraphs
|
||||
ROWS = []
|
||||
COLS = []
|
||||
for row in rows:
|
||||
for index in range(len(row)):
|
||||
if not COLS:
|
||||
COLS = range(len(row))
|
||||
for i in range(len(COLS)):
|
||||
COLS[i] = ["",1,""]
|
||||
if TDdivider(row[index][0]) or THdivider(row[index][0]):
|
||||
ROWS.append(COLS)
|
||||
COLS = []
|
||||
else:
|
||||
COLS[index][0] = COLS[index][0] + (row[index][0]) + "\n"
|
||||
COLS[index][1] = row[index][1]
|
||||
COLS[index][2] = row[index][2]
|
||||
|
||||
# now that each cell has been munged together,
|
||||
# determine the cell's alignment.
|
||||
# Default is to center. Also determine the cell's
|
||||
# vertical alignment, top, middle, bottom. Default is
|
||||
# to middle
|
||||
rows = []
|
||||
cols = []
|
||||
for row in ROWS:
|
||||
for index in range(len(row)):
|
||||
topindent = 0
|
||||
bottomindent = 0
|
||||
leftindent = 0
|
||||
rightindent = 0
|
||||
left = []
|
||||
right = []
|
||||
text = row[index][0]
|
||||
text = split(text,'\n')
|
||||
text = text[:len(text)-1]
|
||||
align = ""
|
||||
valign = ""
|
||||
for t in text:
|
||||
t = strip(t)
|
||||
if not t:
|
||||
topindent = topindent + 1
|
||||
else:
|
||||
break
|
||||
text.reverse()
|
||||
for t in text:
|
||||
t = strip(t)
|
||||
if not t:
|
||||
bottomindent = bottomindent + 1
|
||||
else:
|
||||
break
|
||||
text.reverse()
|
||||
tmp = join(text[topindent:len(text)-bottomindent],"\n")
|
||||
pars = re.compile("\n\s*\n").split(tmp)
|
||||
for par in pars:
|
||||
if index > 0:
|
||||
par = par[1:]
|
||||
par = split(par, ' ')
|
||||
for p in par:
|
||||
if not p:
|
||||
leftindent = leftindent+1
|
||||
else:
|
||||
break
|
||||
left.append(leftindent)
|
||||
leftindent = 0
|
||||
par.reverse()
|
||||
for p in par:
|
||||
if not p:
|
||||
rightindent = rightindent + 1
|
||||
else:
|
||||
break
|
||||
right.append(rightindent)
|
||||
rightindent = 0
|
||||
left.sort()
|
||||
right.sort()
|
||||
|
||||
if topindent == bottomindent:
|
||||
valign="middle"
|
||||
elif topindent < 1:
|
||||
valign="top"
|
||||
elif bottomindent < 1:
|
||||
valign="bottom"
|
||||
else:
|
||||
valign="middle"
|
||||
|
||||
if left[0] < 1:
|
||||
align = "left"
|
||||
elif right[0] < 1:
|
||||
align = "right"
|
||||
elif left[0] > 1 and right[0] > 1:
|
||||
align="center"
|
||||
else:
|
||||
align="left"
|
||||
|
||||
cols.append(row[index][0],row[index][1],align,valign,row[index][2])
|
||||
rows.append(cols)
|
||||
cols = []
|
||||
return StructuredTextTable(rows,text,subs,indent=paragraph.indent)
|
||||
|
||||
def doc_bullet(self, paragraph, expr = re.compile(r'\s*[-*o]\s+').match):
|
||||
top=paragraph.getColorizableTexts()[0]
|
||||
m=expr(top)
|
||||
|
||||
if not m:
|
||||
return None
|
||||
|
||||
subs=paragraph.getSubparagraphs()
|
||||
if top[-2:]=='::':
|
||||
subs=[StructuredTextExample(subs)]
|
||||
top=top[:-1]
|
||||
return StructuredTextBullet(top[m.span()[1]:], subs,
|
||||
indent=paragraph.indent,
|
||||
bullet=top[:m.span()[1]]
|
||||
)
|
||||
|
||||
def doc_numbered(
|
||||
self, paragraph,
|
||||
expr = re.compile(r'(\s*[%s]+\.)|(\s*[0-9]+\.)|(\s*[0-9]+\s+)' % letters).match):
|
||||
|
||||
# This is the old expression. It had a nasty habit
|
||||
# of grabbing paragraphs that began with a single
|
||||
# letter word even if there was no following period.
|
||||
|
||||
#expr = re.compile('\s*'
|
||||
# '(([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.)*'
|
||||
# '([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.?'
|
||||
# '\s+').match):
|
||||
|
||||
top=paragraph.getColorizableTexts()[0]
|
||||
m=expr(top)
|
||||
if not m: return None
|
||||
subs=paragraph.getSubparagraphs()
|
||||
if top[-2:]=='::':
|
||||
subs=[StructuredTextExample(subs)]
|
||||
top=top[:-1]
|
||||
return StructuredTextNumbered(top[m.span()[1]:], subs,
|
||||
indent=paragraph.indent,
|
||||
number=top[:m.span()[1]])
|
||||
|
||||
def doc_description(
|
||||
self, paragraph,
|
||||
delim = re.compile(r'\s+--\s+').search,
|
||||
nb=re.compile(r'[^\000- ]').search,
|
||||
):
|
||||
|
||||
top=paragraph.getColorizableTexts()[0]
|
||||
d=delim(top)
|
||||
if not d: return None
|
||||
start, end = d.span()
|
||||
title=top[:start]
|
||||
if find(title, '\n') >= 0: return None
|
||||
if not nb(title): return None
|
||||
d=top[start:end]
|
||||
top=top[end:]
|
||||
|
||||
subs=paragraph.getSubparagraphs()
|
||||
if top[-2:]=='::':
|
||||
subs=[StructuredTextExample(subs)]
|
||||
top=top[:-1]
|
||||
|
||||
return StructuredTextDescription(
|
||||
title, top, subs,
|
||||
indent=paragraph.indent,
|
||||
delim=d)
|
||||
|
||||
def doc_header(self, paragraph,
|
||||
expr = re.compile(r'[ %s0-9.:/,-_*<>\?\'\"]+' % letters).match
|
||||
):
|
||||
subs=paragraph.getSubparagraphs()
|
||||
if not subs: return None
|
||||
top=paragraph.getColorizableTexts()[0]
|
||||
if not strip(top): return None
|
||||
if top[-2:]=='::':
|
||||
subs=StructuredTextExample(subs)
|
||||
if strip(top)=='::': return subs
|
||||
return ST.StructuredTextParagraph(
|
||||
top[:-1], [subs], indent=paragraph.indent)
|
||||
|
||||
if find(top,'\n') >= 0: return None
|
||||
return StructuredTextSection(top, subs, indent=paragraph.indent)
|
||||
|
||||
def doc_literal(
|
||||
self, s,
|
||||
expr=re.compile(
|
||||
r"(?:\s|^)'" # open
|
||||
r"([^ \t\n\r\f\v']|[^ \t\n\r\f\v'][^\n']*[^ \t\n\r\f\v'])" # contents
|
||||
r"'(?:\s|[,.;:!?]|$)" # close
|
||||
).search):
|
||||
|
||||
r=expr(s)
|
||||
if r:
|
||||
start, end = r.span(1)
|
||||
return (StructuredTextLiteral(s[start:end]), start-1, end+1)
|
||||
else:
|
||||
return None
|
||||
|
||||
def doc_emphasize(
|
||||
self, s,
|
||||
expr = re.compile(r'\s*\*([ \n%s0-9]+)\*(?!\*|-)' % lettpunc).search
|
||||
):
|
||||
|
||||
r=expr(s)
|
||||
if r:
|
||||
start, end = r.span(1)
|
||||
return (StructuredTextEmphasis(s[start:end]), start-1, end+1)
|
||||
else:
|
||||
return None
|
||||
|
||||
def doc_inner_link(self,
|
||||
s,
|
||||
expr1 = re.compile(r"\.\.\s*").search,
|
||||
expr2 = re.compile(r"\[[%s0-9]+\]" % letters ).search):
|
||||
|
||||
# make sure we dont grab a named link
|
||||
if expr2(s) and expr1(s):
|
||||
start1,end1 = expr1(s).span()
|
||||
start2,end2 = expr2(s).span()
|
||||
if end1 == start2:
|
||||
# uh-oh, looks like a named link
|
||||
return None
|
||||
else:
|
||||
# the .. is somewhere else, ignore it
|
||||
return (StructuredTextInnerLink(s[start2+1,end2-1],start2,end2))
|
||||
return None
|
||||
elif expr2(s) and not expr1(s):
|
||||
start,end = expr2(s).span()
|
||||
return (StructuredTextInnerLink(s[start+1:end-1]),start,end)
|
||||
return None
|
||||
|
||||
def doc_named_link(self,
|
||||
s,
|
||||
expr=re.compile(r"(\.\.\s)(\[[%s0-9]+\])" % letters).search):
|
||||
|
||||
result = expr(s)
|
||||
if result:
|
||||
start,end = result.span(2)
|
||||
a,b = result.span(1)
|
||||
str = strip(s[a:b]) + s[start:end]
|
||||
st,en = result.span()
|
||||
return (StructuredTextNamedLink(str),st,en)
|
||||
#return (StructuredTextNamedLink(s[st:en]),st,en)
|
||||
return None
|
||||
|
||||
def doc_underline(self,
|
||||
s,
|
||||
expr=re.compile(r"\s+\_([%s0-9\s]+)\_" % lettpunc).search):
|
||||
|
||||
result = expr(s)
|
||||
if result:
|
||||
start,end = result.span(1)
|
||||
st,e = result.span()
|
||||
return (StructuredTextUnderline(s[start:end]),st,e)
|
||||
else:
|
||||
return None
|
||||
|
||||
def doc_strong(self,
|
||||
s,
|
||||
expr = re.compile(r'\s*\*\*([ \n%s0-9]+)\*\*' % lettpunc).search
|
||||
):
|
||||
|
||||
r=expr(s)
|
||||
if r:
|
||||
start, end = r.span(1)
|
||||
return (StructuredTextStrong(s[start:end]), start-2, end+2)
|
||||
else:
|
||||
return None
|
||||
|
||||
## Some constants to make the doc_href() regex easier to read.
|
||||
_DQUOTEDTEXT = r'("[%s0-9\n\-\.\,\;\(\)\/\:\/\*\']+")' % letters ## double quoted text
|
||||
_URL_AND_PUNC = r'([%s0-9\@\.\,\?\!\/\:\;\-\#\~]+)' % letters
|
||||
_SPACES = r'(\s*)'
|
||||
|
||||
def doc_href(self, s,
|
||||
expr1 = re.compile(_DQUOTEDTEXT + "(:)" + _URL_AND_PUNC + _SPACES).search,
|
||||
expr2 = re.compile(_DQUOTEDTEXT + r'(\,\s+)' + _URL_AND_PUNC + _SPACES).search):
|
||||
|
||||
punctuation = re.compile(r"[\,\.\?\!\;]+").match
|
||||
r=expr1(s) or expr2(s)
|
||||
|
||||
if r:
|
||||
# need to grab the href part and the
|
||||
# beginning part
|
||||
|
||||
start,e = r.span(1)
|
||||
name = s[start:e]
|
||||
name = replace(name,'"','',2)
|
||||
#start = start + 1
|
||||
st,end = r.span(3)
|
||||
if punctuation(s[end-1:end]):
|
||||
end = end -1
|
||||
link = s[st:end]
|
||||
#end = end - 1
|
||||
|
||||
# name is the href title, link is the target
|
||||
# of the href
|
||||
return (StructuredTextLink(name, href=link),
|
||||
start, end)
|
||||
|
||||
#return (StructuredTextLink(s[start:end], href=s[start:end]),
|
||||
# start, end)
|
||||
else:
|
||||
return None
|
||||
|
||||
def doc_sgml(self,s,expr=re.compile(r"\<[%s0-9\.\=\'\"\:\/\-\#\+\s\*]+\>" % letters).search):
|
||||
"""
|
||||
SGML text is ignored and outputed as-is
|
||||
"""
|
||||
r = expr(s)
|
||||
if r:
|
||||
start,end = r.span()
|
||||
text = s[start:end]
|
||||
return (StructuredTextSGML(text),start,end)
|
||||
|
||||
|
||||
def doc_xref(self, s,
|
||||
expr = re.compile('\[([%s0-9\-.:/;,\n\~]+)\]' % letters).search
|
||||
):
|
||||
r = expr(s)
|
||||
if r:
|
||||
start, end = r.span(1)
|
||||
return (StructuredTextXref(s[start:end]), start-1, end+1)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
|
||||
|
@@ -1,134 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import re, ST, STDOM
|
||||
from string import split, join, replace, expandtabs, strip, find
|
||||
|
||||
from DocumentClass import *
|
||||
|
||||
class StructuredTextImage(StructuredTextMarkup):
|
||||
"A simple embedded image"
|
||||
|
||||
class DocumentWithImages(DocumentClass):
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
|
||||
text_types = [
|
||||
'doc_img',
|
||||
] + DocumentClass.text_types
|
||||
|
||||
|
||||
def doc_img(
|
||||
self, s,
|
||||
expr1=re.compile('\"([ _a-zA-Z0-9*.:/;,\-\n\~]+)\":img:([a-zA-Z0-9\-.:/;,\n\~]+)').search,
|
||||
expr2=re.compile('\"([ _a-zA-Z0-9*.:/;,\-\n\~]+)\":img:([a-zA-Z0-9\-.:/;,\n\~]+):([a-zA-Z0-9\-.:/;,\n\~]+)').search
|
||||
):
|
||||
|
||||
|
||||
r = expr2(s)
|
||||
if r:
|
||||
startt, endt = r.span(1)
|
||||
startk, endk = r.span(2)
|
||||
starth, endh = r.span(3)
|
||||
start, end = r.span()
|
||||
return (StructuredTextImage(s[startt:endt], href=s[starth:endh], key=s[startk:endk]),
|
||||
start, end)
|
||||
|
||||
|
||||
else:
|
||||
|
||||
r=expr1(s)
|
||||
|
||||
if r:
|
||||
startt, endt = r.span(1)
|
||||
starth, endh = r.span(2)
|
||||
start, end = r.span()
|
||||
return (StructuredTextImage(s[startt:endt], href=s[starth:endh]),
|
||||
start, end)
|
||||
|
||||
return None
|
||||
|
@@ -1,307 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from string import join, split, find
|
||||
from cgi import escape
|
||||
import re, sys, ST
|
||||
|
||||
class HTMLClass:
|
||||
|
||||
element_types={
|
||||
'#text': '_text',
|
||||
'StructuredTextDocument': 'document',
|
||||
'StructuredTextParagraph': 'paragraph',
|
||||
'StructuredTextExample': 'example',
|
||||
'StructuredTextBullet': 'bullet',
|
||||
'StructuredTextNumbered': 'numbered',
|
||||
'StructuredTextDescription': 'description',
|
||||
'StructuredTextDescriptionTitle': 'descriptionTitle',
|
||||
'StructuredTextDescriptionBody': 'descriptionBody',
|
||||
'StructuredTextSection': 'section',
|
||||
'StructuredTextSectionTitle': 'sectionTitle',
|
||||
'StructuredTextLiteral': 'literal',
|
||||
'StructuredTextEmphasis': 'emphasis',
|
||||
'StructuredTextStrong': 'strong',
|
||||
'StructuredTextLink': 'link',
|
||||
'StructuredTextXref': 'xref',
|
||||
'StructuredTextInnerLink':'innerLink',
|
||||
'StructuredTextNamedLink':'namedLink',
|
||||
'StructuredTextUnderline':'underline',
|
||||
'StructuredTextTable':'table',
|
||||
'StructuredTextSGML':'sgml',
|
||||
}
|
||||
|
||||
def dispatch(self, doc, level, output):
|
||||
getattr(self, self.element_types[doc.getNodeName()])(doc, level, output)
|
||||
|
||||
def __call__(self, doc, level=1):
|
||||
r=[]
|
||||
self.dispatch(doc, level-1, r.append)
|
||||
return join(r,'')
|
||||
|
||||
def _text(self, doc, level, output):
|
||||
output(doc.getNodeValue())
|
||||
|
||||
def document(self, doc, level, output):
|
||||
output('<html>\n')
|
||||
children=doc.getChildNodes()
|
||||
if (children and
|
||||
children[0].getNodeName() == 'StructuredTextSection'):
|
||||
output('<head>\n<title>%s</title>\n</head>\n' %
|
||||
children[0].getChildNodes()[0].getNodeValue())
|
||||
output('<body>\n')
|
||||
for c in children:
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</body>\n')
|
||||
output('</html>\n')
|
||||
|
||||
def section(self, doc, level, output):
|
||||
children=doc.getChildNodes()
|
||||
for c in children:
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level+1, output)
|
||||
|
||||
def sectionTitle(self, doc, level, output):
|
||||
output('<h%d>' % (level))
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</h%d>\n' % (level))
|
||||
|
||||
def description(self, doc, level, output):
|
||||
p=doc.getPreviousSibling()
|
||||
if p is None or p.getNodeName() is not doc.getNodeName():
|
||||
output('<dl>\n')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
n=doc.getNextSibling()
|
||||
if n is None or n.getNodeName() is not doc.getNodeName():
|
||||
output('</dl>\n')
|
||||
|
||||
def descriptionTitle(self, doc, level, output):
|
||||
output('<dt>')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</dt>\n')
|
||||
|
||||
def descriptionBody(self, doc, level, output):
|
||||
output('<dd>')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</dd>\n')
|
||||
|
||||
def bullet(self, doc, level, output):
|
||||
p=doc.getPreviousSibling()
|
||||
if p is None or p.getNodeName() is not doc.getNodeName():
|
||||
output('\n<ul>\n')
|
||||
output('<li>')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
n=doc.getNextSibling()
|
||||
output('</li>\n')
|
||||
if n is None or n.getNodeName() is not doc.getNodeName():
|
||||
output('\n</ul>\n')
|
||||
|
||||
def numbered(self, doc, level, output):
|
||||
p=doc.getPreviousSibling()
|
||||
if p is None or p.getNodeName() is not doc.getNodeName():
|
||||
output('\n<ol>\n')
|
||||
output('<li>')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
n=doc.getNextSibling()
|
||||
output('</li>\n')
|
||||
if n is None or n.getNodeName() is not doc.getNodeName():
|
||||
output('\n</ol>\n')
|
||||
|
||||
def example(self, doc, level, output):
|
||||
i=0
|
||||
for c in doc.getChildNodes():
|
||||
if i==0:
|
||||
output('\n<pre>\n')
|
||||
output(escape(c.getNodeValue()))
|
||||
output('\n</pre>\n')
|
||||
else:
|
||||
getattr(self, self.element_types[c.getNodeName()])(
|
||||
c, level, output)
|
||||
|
||||
def paragraph(self, doc, level, output):
|
||||
i=0
|
||||
output('<p>')
|
||||
for c in doc.getChildNodes():
|
||||
if c.getNodeName() in ['StructuredTextParagraph']:
|
||||
getattr(self, self.element_types[c.getNodeName()])(
|
||||
c, level, output)
|
||||
else:
|
||||
getattr(self, self.element_types[c.getNodeName()])(
|
||||
c, level, output)
|
||||
output('</p>\n')
|
||||
|
||||
def link(self, doc, level, output):
|
||||
output('<a href="%s">' % doc.href)
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</a>')
|
||||
|
||||
def emphasis(self, doc, level, output):
|
||||
output('<em>')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</em>')
|
||||
|
||||
def literal(self, doc, level, output):
|
||||
output('<code>')
|
||||
for c in doc.getChildNodes():
|
||||
output(escape(c.getNodeValue()))
|
||||
output('</code>')
|
||||
|
||||
def strong(self, doc, level, output):
|
||||
output('<strong>')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</strong>')
|
||||
|
||||
def underline(self, doc, level, output):
|
||||
output("<u>")
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output("</u>")
|
||||
|
||||
def innerLink(self, doc, level, output):
|
||||
output('<a href="#');
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('">[')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output(']</a>')
|
||||
|
||||
def namedLink(self, doc, level, output):
|
||||
output('<a name="')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('">[')
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output(']</a>')
|
||||
|
||||
def sgml(self,doc,level,output):
|
||||
for c in doc.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
|
||||
def xref(self, doc, level, output):
|
||||
val = doc.getNodeValue()
|
||||
output('<a href="#%s">[%s]</a>' % (val, val) )
|
||||
|
||||
def table(self,doc,level,output):
|
||||
"""
|
||||
A StructuredTextTable holds StructuredTextRow(s) which
|
||||
holds StructuredTextColumn(s). A StructuredTextColumn
|
||||
is a type of StructuredTextParagraph and thus holds
|
||||
the actual data.
|
||||
"""
|
||||
output("<table border=1 cellpadding=2>\n")
|
||||
for row in doc.getRows()[0]:
|
||||
output("<tr>\n")
|
||||
for column in row.getColumns()[0]:
|
||||
if hasattr(column,"getAlign"):
|
||||
str = "<%s colspan=%s align=%s valign=%s>" % (column.getType(),
|
||||
column.getSpan(),
|
||||
column.getAlign(),
|
||||
column.getValign())
|
||||
else:
|
||||
str = "<td colspan=%s>" % column.getSpan()
|
||||
output(str)
|
||||
for c in column.getChildNodes():
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
if hasattr(column,"getType"):
|
||||
output("</"+column.getType()+">\n")
|
||||
else:
|
||||
output("</td>\n")
|
||||
output("</tr>\n")
|
||||
output("</table>\n")
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,128 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from string import join, split, find
|
||||
import re, sys, ST
|
||||
import time
|
||||
|
||||
from HTMLClass import HTMLClass
|
||||
|
||||
ets = HTMLClass.element_types
|
||||
ets.update({'StructuredTextImage': 'image'})
|
||||
|
||||
class HTMLWithImages(HTMLClass):
|
||||
|
||||
element_types = ets
|
||||
|
||||
def document(self, doc, level, output):
|
||||
output('<html>\n')
|
||||
children=doc.getChildNodes()
|
||||
if (children and
|
||||
children[0].getNodeName() == 'StructuredTextSection'):
|
||||
output('<head>\n<title>%s</title>\n</head>\n' %
|
||||
children[0].getChildNodes()[0].getNodeValue())
|
||||
output('<body bgcolor="#FFFFFF">\n')
|
||||
for c in children:
|
||||
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
|
||||
output('</body>\n')
|
||||
output('</html>\n')
|
||||
|
||||
def image(self, doc, level, output):
|
||||
if hasattr(doc, 'key'):
|
||||
output('<a name="%s"></a>\n' % doc.key)
|
||||
output('<img src="%s" alt="%s">\n' % (doc.href, doc.getNodeValue()))
|
||||
if doc.getNodeValue() and hasattr(doc, 'key'):
|
||||
output('<p><b>Figure %s</b> %s</p>\n' % (doc.key, doc.getNodeValue()))
|
||||
|
||||
def xref(self, doc, level, output):
|
||||
val = doc.getNodeValue()
|
||||
output('<a href="#%s">Figure %s</a>' % (val, val) )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,283 +0,0 @@
|
||||
import re, STDOM
|
||||
from string import split, join, replace, expandtabs, strip, find
|
||||
|
||||
#####################################################################
|
||||
# Updated functions #
|
||||
#####################################################################
|
||||
|
||||
def indention(str,front = re.compile("^\s+").match):
|
||||
"""
|
||||
Convert all tabs to the appropriate number of spaces.
|
||||
Find the number of leading spaces. If none, return 0
|
||||
"""
|
||||
|
||||
if front(str):
|
||||
start,end = front(str).span()
|
||||
return end-start-1
|
||||
else:
|
||||
return 0 # no leading spaces
|
||||
|
||||
def insert(struct, top, level):
|
||||
"""
|
||||
find what will be the parant paragraph of
|
||||
a sentence and return that paragraph's
|
||||
sub-paragraphs. The new paragraph will be
|
||||
appended to those sub-paragraphs
|
||||
"""
|
||||
#print "struct", struct, top-1
|
||||
if not top-1 in range(len(struct)):
|
||||
if struct:
|
||||
return struct[len(struct)-1].getSubparagraphs()
|
||||
return struct
|
||||
run = struct[top-1]
|
||||
i = 0
|
||||
while i+1 < level:
|
||||
run = run.getSubparagraphs()[len(run.getSubparagraphs())-1]
|
||||
i = i + 1
|
||||
#print "parent for level ", level, " was => ", run.getColorizableTexts()
|
||||
return run.getSubparagraphs()
|
||||
|
||||
def display(struct):
|
||||
"""
|
||||
runs through the structure and prints out
|
||||
the paragraphs. If the insertion works
|
||||
correctly, display's results should mimic
|
||||
the orignal paragraphs.
|
||||
"""
|
||||
|
||||
if struct.getColorizableTexts():
|
||||
print join(struct.getColorizableTexts()),"\n"
|
||||
if struct.getSubparagraphs():
|
||||
for x in struct.getSubparagraphs():
|
||||
display(x)
|
||||
|
||||
def display2(struct):
|
||||
"""
|
||||
runs through the structure and prints out
|
||||
the paragraphs. If the insertion works
|
||||
correctly, display's results should mimic
|
||||
the orignal paragraphs.
|
||||
"""
|
||||
|
||||
if struct.getNodeValue():
|
||||
print struct.getNodeValue(),"\n"
|
||||
if struct.getSubparagraphs():
|
||||
for x in struct.getSubparagraphs():
|
||||
display(x)
|
||||
|
||||
def findlevel(levels,indent):
|
||||
"""
|
||||
remove all level information of levels
|
||||
with a greater level of indentation.
|
||||
Then return which level should insert this
|
||||
paragraph
|
||||
"""
|
||||
|
||||
keys = levels.keys()
|
||||
for key in keys:
|
||||
if levels[key] > indent:
|
||||
del(levels[key])
|
||||
keys = levels.keys()
|
||||
if not(keys):
|
||||
return 0
|
||||
else:
|
||||
for key in keys:
|
||||
if levels[key] == indent:
|
||||
return key
|
||||
highest = 0
|
||||
for key in keys:
|
||||
if key > highest:
|
||||
highest = key
|
||||
return highest-1
|
||||
|
||||
#####################################################################
|
||||
|
||||
# Golly, the capitalization of this function always makes me think it's a class
|
||||
def StructuredText(paragraphs, paragraph_delimiter=re.compile('\n\s*\n')):
|
||||
"""
|
||||
StructuredText accepts paragraphs, which is a list of
|
||||
lines to be parsed. StructuredText creates a structure
|
||||
which mimics the structure of the paragraphs.
|
||||
Structure => [paragraph,[sub-paragraphs]]
|
||||
"""
|
||||
|
||||
currentlevel = 0
|
||||
currentindent = 0
|
||||
levels = {0:0}
|
||||
level = 0 # which header are we under
|
||||
struct = [] # the structure to be returned
|
||||
run = struct
|
||||
|
||||
paragraphs = filter(
|
||||
strip,
|
||||
paragraph_delimiter.split(expandtabs('\n\n'+paragraphs+'\n\n'))
|
||||
)
|
||||
|
||||
if not paragraphs: return []
|
||||
|
||||
ind = [] # structure based on indention levels
|
||||
for paragraph in paragraphs:
|
||||
ind.append([indention(paragraph), paragraph])
|
||||
|
||||
currentindent = indention(paragraphs[0])
|
||||
levels[0] = currentindent
|
||||
|
||||
#############################################################
|
||||
# updated #
|
||||
#############################################################
|
||||
|
||||
for indent,paragraph in ind :
|
||||
if indent == 0:
|
||||
level = level + 1
|
||||
currentlevel = 0
|
||||
currentindent = 0
|
||||
levels = {0:0}
|
||||
struct.append(StructuredTextParagraph(paragraph, indent=indent, level=currentlevel))
|
||||
elif indent > currentindent:
|
||||
currentlevel = currentlevel + 1
|
||||
currentindent = indent
|
||||
levels[currentlevel] = indent
|
||||
run = insert(struct,level,currentlevel)
|
||||
run.append(StructuredTextParagraph(paragraph, indent=indent, level=currentlevel))
|
||||
elif indent < currentindent:
|
||||
result = findlevel(levels,indent)
|
||||
if result > 0:
|
||||
currentlevel = result
|
||||
currentindent = indent
|
||||
if not level:
|
||||
struct.append(StructuredTextParagraph(paragraph, indent=indent, level=currentlevel))
|
||||
else:
|
||||
run = insert(struct,level,currentlevel)
|
||||
run.append(StructuredTextParagraph(paragraph, indent=indent, level=currentlevel))
|
||||
else:
|
||||
if insert(struct,level,currentlevel):
|
||||
run = insert(struct,level,currentlevel)
|
||||
else:
|
||||
run = struct
|
||||
currentindet = indent
|
||||
run.append(StructuredTextParagraph(paragraph, indent=indent, level=currentlevel))
|
||||
|
||||
return StructuredTextDocument(struct)
|
||||
|
||||
Basic = StructuredText
|
||||
|
||||
class StructuredTextParagraph(STDOM.Element):
|
||||
|
||||
indent=0
|
||||
|
||||
def __init__(self, src, subs=None, **kw):
|
||||
if subs is None: subs=[]
|
||||
self._src=src
|
||||
self._subs=list(subs)
|
||||
|
||||
self._attributes=kw.keys()
|
||||
for k, v in kw.items(): setattr(self, k, v)
|
||||
|
||||
def getChildren(self, type=type, lt=type([])):
|
||||
src=self._src
|
||||
if type(src) is not lt: src=[src]
|
||||
return src+self._subs
|
||||
|
||||
def getAttribute(self, name):
|
||||
return getattr(self, name, None)
|
||||
|
||||
def getAttributeNode(self, name):
|
||||
if hasattr(self, name):
|
||||
return STDOM.Attr(name, getattr(self, name))
|
||||
|
||||
def getAttributes(self):
|
||||
d={}
|
||||
for a in self._attributes:
|
||||
d[a]=getattr(self, a, '')
|
||||
return STDOM.NamedNodeMap(d)
|
||||
|
||||
def getSubparagraphs(self):
|
||||
return self._subs
|
||||
|
||||
def setSubparagraphs(self, subs):
|
||||
self._subs=subs
|
||||
|
||||
def getColorizableTexts(self):
|
||||
return (self._src,)
|
||||
|
||||
def setColorizableTexts(self, src):
|
||||
self._src=src[0]
|
||||
|
||||
def __repr__(self):
|
||||
r=[]; a=r.append
|
||||
a((' '*(self.indent or 0))+
|
||||
('%s(' % self.__class__.__name__)
|
||||
+str(self._src)+', ['
|
||||
)
|
||||
for p in self._subs: a(`p`)
|
||||
a((' '*(self.indent or 0))+'])')
|
||||
return join(r,'\n')
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
|
||||
def _get_Children(self, type=type, lt=type([])):
|
||||
return self.getChildren(type,lt)
|
||||
|
||||
def _get_Attribute(self, name):
|
||||
return self.getAttribute(name)
|
||||
|
||||
def _get_AttributeNode(self, name):
|
||||
return self.getAttributeNode(name)
|
||||
|
||||
def _get_Attributes(self):
|
||||
return self.getAttributes()
|
||||
|
||||
def _get_Subparagraphs(self):
|
||||
return self.getSubparagraphs()
|
||||
|
||||
def _set_Subparagraphs(self, subs):
|
||||
return self.setSubparagraphs(subs)
|
||||
|
||||
def _get_ColorizableTexts(self):
|
||||
return self.getColorizableTexts()
|
||||
|
||||
def _set_ColorizableTexts(self, src):
|
||||
return self.setColorizableTexts(src)
|
||||
|
||||
class StructuredTextDocument(StructuredTextParagraph):
|
||||
"""
|
||||
A StructuredTextDocument holds StructuredTextParagraphs
|
||||
as its subparagraphs.
|
||||
"""
|
||||
_attributes=()
|
||||
|
||||
def __init__(self, subs=None, **kw):
|
||||
apply(StructuredTextParagraph.__init__,
|
||||
(self, '', subs),
|
||||
kw)
|
||||
|
||||
def getChildren(self):
|
||||
return self._subs
|
||||
|
||||
def getColorizableTexts(self):
|
||||
return ()
|
||||
|
||||
def setColorizableTexts(self, src):
|
||||
pass
|
||||
|
||||
def __repr__(self):
|
||||
r=[]; a=r.append
|
||||
a('%s([' % self.__class__.__name__)
|
||||
for p in self._subs: a(`p`+',')
|
||||
a('])')
|
||||
return join(r,'\n')
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
|
||||
def _get_Children(self):
|
||||
return self.getChildren()
|
||||
|
||||
def _get_ColorizableTexts(self):
|
||||
return self.getColorizableTexts()
|
||||
|
||||
def _set_ColorizableTexts(self, src):
|
||||
return self.setColorizableTexts(src)
|
@@ -1,736 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
"""
|
||||
DOM implementation in StructuredText : Read-Only methods
|
||||
|
||||
All standard Zope objects support DOM to a limited extent.
|
||||
"""
|
||||
import string
|
||||
|
||||
|
||||
# Node type codes
|
||||
# ---------------
|
||||
|
||||
ELEMENT_NODE = 1
|
||||
ATTRIBUTE_NODE = 2
|
||||
TEXT_NODE = 3
|
||||
CDATA_SECTION_NODE = 4
|
||||
ENTITY_REFERENCE_NODE = 5
|
||||
ENTITY_NODE = 6
|
||||
PROCESSING_INSTRUCTION_NODE = 7
|
||||
COMMENT_NODE = 8
|
||||
DOCUMENT_NODE = 9
|
||||
DOCUMENT_TYPE_NODE = 10
|
||||
DOCUMENT_FRAGMENT_NODE = 11
|
||||
NOTATION_NODE = 12
|
||||
|
||||
# Exception codes
|
||||
# ---------------
|
||||
|
||||
INDEX_SIZE_ERR = 1
|
||||
DOMSTRING_SIZE_ERR = 2
|
||||
HIERARCHY_REQUEST_ERR = 3
|
||||
WRONG_DOCUMENT_ERR = 4
|
||||
INVALID_CHARACTER_ERR = 5
|
||||
NO_DATA_ALLOWED_ERR = 6
|
||||
NO_MODIFICATION_ALLOWED_ERR = 7
|
||||
NOT_FOUND_ERR = 8
|
||||
NOT_SUPPORTED_ERR = 9
|
||||
INUSE_ATTRIBUTE_ERR = 10
|
||||
|
||||
# Exceptions
|
||||
# ----------
|
||||
|
||||
class DOMException(Exception):
|
||||
pass
|
||||
class IndexSizeException(DOMException):
|
||||
code = INDEX_SIZE_ERR
|
||||
class DOMStringSizeException(DOMException):
|
||||
code = DOMSTRING_SIZE_ERR
|
||||
class HierarchyRequestException(DOMException):
|
||||
code = HIERARCHY_REQUEST_ERR
|
||||
class WrongDocumentException(DOMException):
|
||||
code = WRONG_DOCUMENT_ERR
|
||||
class InvalidCharacterException(DOMException):
|
||||
code = INVALID_CHARACTER_ERR
|
||||
class NoDataAllowedException(DOMException):
|
||||
code = NO_DATA_ALLOWED_ERR
|
||||
class NoModificationAllowedException(DOMException):
|
||||
code = NO_MODIFICATION_ALLOWED_ERR
|
||||
class NotFoundException(DOMException):
|
||||
code = NOT_FOUND_ERR
|
||||
class NotSupportedException(DOMException):
|
||||
code = NOT_SUPPORTED_ERR
|
||||
class InUseAttributeException(DOMException):
|
||||
code = INUSE_ATTRIBUTE_ERR
|
||||
|
||||
# Node classes
|
||||
# ------------
|
||||
|
||||
class ParentNode:
|
||||
"""
|
||||
A node that can have children, or, more precisely, that implements
|
||||
the child access methods of the DOM.
|
||||
"""
|
||||
|
||||
def getChildNodes(self, type=type, st=type('')):
|
||||
"""
|
||||
Returns a NodeList that contains all children of this node.
|
||||
If there are no children, this is a empty NodeList
|
||||
"""
|
||||
|
||||
r=[]
|
||||
for n in self.getChildren():
|
||||
if type(n) is st: n=TextNode(n)
|
||||
r.append(n.__of__(self))
|
||||
|
||||
return NodeList(r)
|
||||
|
||||
def getFirstChild(self, type=type, st=type('')):
|
||||
"""
|
||||
The first child of this node. If there is no such node
|
||||
this returns None
|
||||
"""
|
||||
children = self.getChildren()
|
||||
|
||||
if not children:
|
||||
return None
|
||||
|
||||
n=children[0]
|
||||
|
||||
if type(n) is st:
|
||||
n=TextNode(n)
|
||||
|
||||
return n.__of__(self)
|
||||
|
||||
def getLastChild(self, type=type, st=type('')):
|
||||
"""
|
||||
The last child of this node. If there is no such node
|
||||
this returns None.
|
||||
"""
|
||||
children = self.getChildren()
|
||||
if not children: return None
|
||||
n=chidren[-1]
|
||||
if type(n) is st: n=TextNode(n)
|
||||
return n.__of__(self)
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
|
||||
def _get_ChildNodes(self, type=type, st=type('')):
|
||||
return self.getChildNodes(type,st)
|
||||
|
||||
def _get_FirstChild(self, type=type, st=type('')):
|
||||
return self.getFirstChild(type,st)
|
||||
|
||||
def _get_LastChild(self, type=type, st=type('')):
|
||||
return self.getLastChild(type,st)
|
||||
|
||||
class NodeWrapper(ParentNode):
|
||||
"""
|
||||
This is an acquisition-like wrapper that provides parent access for
|
||||
DOM sans circular references!
|
||||
"""
|
||||
|
||||
def __init__(self, aq_self, aq_parent):
|
||||
self.aq_self=aq_self
|
||||
self.aq_parent=aq_parent
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.aq_self, name)
|
||||
|
||||
def getParentNode(self):
|
||||
"""
|
||||
The parent of this node. All nodes except Document
|
||||
DocumentFragment and Attr may have a parent
|
||||
"""
|
||||
return self.aq_parent
|
||||
|
||||
def _getDOMIndex(self, children, getattr=getattr):
|
||||
i=0
|
||||
self=self.aq_self
|
||||
for child in children:
|
||||
if getattr(child, 'aq_self', child) is self:
|
||||
self._DOMIndex=i
|
||||
return i
|
||||
i=i+1
|
||||
return None
|
||||
|
||||
def getPreviousSibling(self,
|
||||
type=type,
|
||||
st=type(''),
|
||||
getattr=getattr,
|
||||
None=None):
|
||||
|
||||
"""
|
||||
The node immediately preceding this node. If
|
||||
there is no such node, this returns None.
|
||||
"""
|
||||
|
||||
children = self.aq_parent.getChildren()
|
||||
if not children:
|
||||
return None
|
||||
|
||||
index=getattr(self, '_DOMIndex', None)
|
||||
if index is None:
|
||||
index=self._getDOMIndex(children)
|
||||
if index is None: return None
|
||||
|
||||
index=index-1
|
||||
if index < 0: return None
|
||||
try: n=children[index]
|
||||
except IndexError: return None
|
||||
else:
|
||||
if type(n) is st:
|
||||
n=TextNode(n)
|
||||
n._DOMIndex=index
|
||||
return n.__of__(self)
|
||||
|
||||
|
||||
def getNextSibling(self, type=type, st=type('')):
|
||||
"""
|
||||
The node immediately preceding this node. If
|
||||
there is no such node, this returns None.
|
||||
"""
|
||||
children = self.aq_parent.getChildren()
|
||||
if not children:
|
||||
return None
|
||||
|
||||
index=getattr(self, '_DOMIndex', None)
|
||||
if index is None:
|
||||
index=self._getDOMIndex(children)
|
||||
if index is None:
|
||||
return None
|
||||
|
||||
index=index+1
|
||||
try: n=children[index]
|
||||
except IndexError:
|
||||
return None
|
||||
else:
|
||||
if type(n) is st:
|
||||
n=TextNode(n)
|
||||
n._DOMIndex=index
|
||||
return n.__of__(self)
|
||||
|
||||
def getOwnerDocument(self):
|
||||
"""
|
||||
The Document object associated with this node, if any.
|
||||
"""
|
||||
return self.aq_parent.getOwnerDocument()
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
|
||||
def _get_ParentNode(self):
|
||||
return self.getParentNode()
|
||||
|
||||
def _get_DOMIndex(self, children, getattr=getattr):
|
||||
return self._getDOMIndex(children,getattr)
|
||||
|
||||
def _get_PreviousSibling(self,
|
||||
type=type,
|
||||
st=type(''),
|
||||
getattr=getattr,
|
||||
None=None):
|
||||
|
||||
return self.getPreviousSibling(type,st,getattr,None)
|
||||
|
||||
def _get_NextSibling(self, type=type, st=type('')):
|
||||
return self.getNextSibling(type,st)
|
||||
|
||||
def _get_OwnerDocument(self):
|
||||
return self.getOwnerDocument()
|
||||
|
||||
class Node(ParentNode):
|
||||
"""
|
||||
Node Interface
|
||||
"""
|
||||
|
||||
# Get a DOM wrapper with a parent link
|
||||
def __of__(self, parent):
|
||||
return NodeWrapper(self, parent)
|
||||
|
||||
# DOM attributes
|
||||
# --------------
|
||||
|
||||
def getNodeName(self):
|
||||
"""
|
||||
The name of this node, depending on its type
|
||||
"""
|
||||
|
||||
def getNodeValue(self):
|
||||
"""
|
||||
The value of this node, depending on its type
|
||||
"""
|
||||
return None
|
||||
|
||||
def getParentNode(self):
|
||||
"""
|
||||
The parent of this node. All nodes except Document
|
||||
DocumentFragment and Attr may have a parent
|
||||
"""
|
||||
|
||||
def getChildren(self):
|
||||
"""
|
||||
Get a Python sequence of children
|
||||
"""
|
||||
return ()
|
||||
|
||||
def getPreviousSibling(self,
|
||||
type=type,
|
||||
st=type(''),
|
||||
getattr=getattr,
|
||||
None=None):
|
||||
"""
|
||||
The node immediately preceding this node. If
|
||||
there is no such node, this returns None.
|
||||
"""
|
||||
|
||||
def getNextSibling(self, type=type, st=type('')):
|
||||
"""
|
||||
The node immediately preceding this node. If
|
||||
there is no such node, this returns None.
|
||||
"""
|
||||
|
||||
def getAttributes(self):
|
||||
"""
|
||||
Returns a NamedNodeMap containing the attributes
|
||||
of this node (if it is an element) or None otherwise.
|
||||
"""
|
||||
return None
|
||||
|
||||
def getOwnerDocument(self):
|
||||
"""
|
||||
The Document object associated with this node, if any.
|
||||
"""
|
||||
|
||||
# DOM Methods
|
||||
# -----------
|
||||
|
||||
def hasChildNodes(self):
|
||||
"""
|
||||
Returns true if the node has any children, false
|
||||
if it doesn't.
|
||||
"""
|
||||
return len(self.getChildren())
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
|
||||
def _get_NodeName(self):
|
||||
return self.getNodeName()
|
||||
|
||||
def _get_NodeValue(self):
|
||||
return self.getNodeValue()
|
||||
|
||||
def _get_ParentNode(self):
|
||||
return self.getParentNode()
|
||||
|
||||
def _get_Children(self):
|
||||
return self.getChildren()
|
||||
|
||||
def _get_PreviousSibling(self,
|
||||
type=type,
|
||||
st=type(''),
|
||||
getattr=getattr,
|
||||
None=None):
|
||||
|
||||
return self.getPreviousSibling(type,st,getattr,None)
|
||||
|
||||
def _get_NextSibling(self, type=type, st=type('')):
|
||||
return self.getNextSibling()
|
||||
|
||||
def _get_Attributes(self):
|
||||
return self.getAttributes()
|
||||
|
||||
def _get_OwnerDocument(self):
|
||||
return self.getOwnerDocument()
|
||||
|
||||
def _has_ChildNodes(self):
|
||||
return self.hasChildNodes()
|
||||
|
||||
|
||||
class TextNode(Node):
|
||||
|
||||
def __init__(self, str): self._value=str
|
||||
|
||||
def getNodeType(self):
|
||||
return TEXT_NODE
|
||||
|
||||
def getNodeName(self):
|
||||
return '#text'
|
||||
|
||||
def getNodeValue(self):
|
||||
return self._value
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
|
||||
def _get_NodeType(self):
|
||||
return self.getNodeType()
|
||||
|
||||
def _get_NodeName(self):
|
||||
return self.getNodeName()
|
||||
|
||||
def _get_NodeValue(self):
|
||||
return self.getNodeValue()
|
||||
|
||||
class Element(Node):
|
||||
"""
|
||||
Element interface
|
||||
"""
|
||||
|
||||
# Element Attributes
|
||||
# ------------------
|
||||
|
||||
def getTagName(self):
|
||||
"""The name of the element"""
|
||||
return self.__class__.__name__
|
||||
|
||||
def getNodeName(self):
|
||||
"""The name of this node, depending on its type"""
|
||||
return self.__class__.__name__
|
||||
|
||||
def getNodeType(self):
|
||||
"""A code representing the type of the node."""
|
||||
return ELEMENT_NODE
|
||||
|
||||
def getNodeValue(self, type=type, st=type('')):
|
||||
r=[]
|
||||
for c in self.getChildren():
|
||||
if type(c) is not st:
|
||||
c=c.getNodeValue()
|
||||
r.append(c)
|
||||
return string.join(r,'')
|
||||
|
||||
def getParentNode(self):
|
||||
"""
|
||||
The parent of this node. All nodes except Document
|
||||
DocumentFragment and Attr may have a parent
|
||||
"""
|
||||
|
||||
# Element Methods
|
||||
# ---------------
|
||||
|
||||
_attributes=()
|
||||
|
||||
def getAttribute(self, name): return getattr(self, name, None)
|
||||
def getAttributeNode(self, name):
|
||||
if hasattr(self, name):
|
||||
return Attr(name, getattr(self, name))
|
||||
|
||||
def getAttributes(self):
|
||||
d={}
|
||||
for a in self._attributes:
|
||||
d[a]=getattr(self, a, '')
|
||||
return NamedNodeMap(d)
|
||||
|
||||
def getAttribute(self, name):
|
||||
"""Retrieves an attribute value by name."""
|
||||
return None
|
||||
|
||||
def getAttributeNode(self, name):
|
||||
""" Retrieves an Attr node by name or None if
|
||||
there is no such attribute. """
|
||||
return None
|
||||
|
||||
def getElementsByTagName(self, tagname):
|
||||
"""
|
||||
Returns a NodeList of all the Elements with a given tag
|
||||
name in the order in which they would be encountered in a
|
||||
preorder traversal of the Document tree. Parameter: tagname
|
||||
The name of the tag to match (* = all tags). Return Value: A new
|
||||
NodeList object containing all the matched Elements.
|
||||
"""
|
||||
nodeList = []
|
||||
for child in self.getChildren():
|
||||
if (child.getNodeType()==ELEMENT_NODE and \
|
||||
child.getTagName()==tagname or tagname== '*'):
|
||||
|
||||
nodeList.append(child)
|
||||
|
||||
if hasattr(child, 'getElementsByTagName'):
|
||||
n1 = child.getElementsByTagName(tagname)
|
||||
nodeList = nodeList + n1._data
|
||||
return NodeList(nodeList)
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
|
||||
def _get_TagName(self):
|
||||
return self.getTagName()
|
||||
|
||||
def _get_NodeName(self):
|
||||
return self.getNodeName()
|
||||
|
||||
def _get_NodeType(self):
|
||||
return self.getNodeType()
|
||||
|
||||
def _get_NodeValue(self, type=type, st=type('')):
|
||||
return self.getNodeValue(type,st)
|
||||
|
||||
def _get_ParentNode(self):
|
||||
return self.getParentNode()
|
||||
|
||||
def _get_Attribute(self, name):
|
||||
return self.getAttribute(name)
|
||||
|
||||
def _get_AttributeNode(self, name):
|
||||
return self.getAttributeNode(name)
|
||||
|
||||
def _get_Attributes(self):
|
||||
return self.getAttributes()
|
||||
|
||||
def _get_Attribute(self, name):
|
||||
return self.getAttribute(name)
|
||||
|
||||
def _get_AttributeNode(self, name):
|
||||
return self.getAttributeNode(name)
|
||||
|
||||
def _get_ElementsByTagName(self, tagname):
|
||||
return self.getElementsByTagName(tagname)
|
||||
|
||||
|
||||
class NodeList:
|
||||
"""
|
||||
NodeList interface - Provides the abstraction of an ordered
|
||||
collection of nodes.
|
||||
|
||||
Python extensions: can use sequence-style 'len', 'getitem', and
|
||||
'for..in' constructs.
|
||||
"""
|
||||
|
||||
def __init__(self,list=None):
|
||||
self._data = list or []
|
||||
|
||||
def __getitem__(self, index, type=type, st=type('')):
|
||||
return self._data[index]
|
||||
|
||||
def __getslice__(self, i, j):
|
||||
return self._data[i:j]
|
||||
|
||||
def item(self, index):
|
||||
"""
|
||||
Returns the index-th item in the collection
|
||||
"""
|
||||
try: return self._data[index]
|
||||
except IndexError: return None
|
||||
|
||||
def getLength(self):
|
||||
"""
|
||||
The length of the NodeList
|
||||
"""
|
||||
return len(self._data)
|
||||
|
||||
__len__=getLength
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
|
||||
def _get_Length(self):
|
||||
return self.getLength()
|
||||
|
||||
class NamedNodeMap:
|
||||
"""
|
||||
NamedNodeMap interface - Is used to represent collections
|
||||
of nodes that can be accessed by name. NamedNodeMaps are not
|
||||
maintained in any particular order.
|
||||
|
||||
Python extensions: can use sequence-style 'len', 'getitem', and
|
||||
'for..in' constructs, and mapping-style 'getitem'.
|
||||
"""
|
||||
|
||||
def __init__(self, data=None):
|
||||
if data is None:
|
||||
data = {}
|
||||
self._data = data
|
||||
|
||||
def item(self, index):
|
||||
"""
|
||||
Returns the index-th item in the map
|
||||
"""
|
||||
try: return self._data.values()[index]
|
||||
except IndexError: return None
|
||||
|
||||
def __getitem__(self, key):
|
||||
if type(key)==type(1):
|
||||
return self._data.values()[key]
|
||||
else:
|
||||
return self._data[key]
|
||||
|
||||
def getLength(self):
|
||||
"""
|
||||
The length of the NodeList
|
||||
"""
|
||||
return len(self._data)
|
||||
|
||||
__len__ = getLength
|
||||
|
||||
def getNamedItem(self, name):
|
||||
"""
|
||||
Retrieves a node specified by name. Parameters:
|
||||
name Name of a node to retrieve. Return Value A Node (of any
|
||||
type) with the specified name, or None if the specified name
|
||||
did not identify any node in the map.
|
||||
"""
|
||||
if self._data.has_key(name):
|
||||
return self._data[name]
|
||||
return None
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
def _get_Length(self):
|
||||
return self.getLength()
|
||||
|
||||
def _get_NamedItem(self, name):
|
||||
return self.getNamedItem(name)
|
||||
|
||||
class Attr(Node):
|
||||
"""
|
||||
Attr interface - The Attr interface represents an attriubte in an
|
||||
Element object. Attr objects inherit the Node Interface
|
||||
"""
|
||||
|
||||
def __init__(self, name, value, specified=1):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.specified = specified
|
||||
|
||||
def getNodeName(self):
|
||||
"""
|
||||
The name of this node, depending on its type
|
||||
"""
|
||||
return self.name
|
||||
|
||||
def getName(self):
|
||||
"""
|
||||
Returns the name of this attribute.
|
||||
"""
|
||||
return self.name
|
||||
|
||||
def getNodeValue(self):
|
||||
"""
|
||||
The value of this node, depending on its type
|
||||
"""
|
||||
return self.value
|
||||
|
||||
def getNodeType(self):
|
||||
"""
|
||||
A code representing the type of the node.
|
||||
"""
|
||||
return ATTRIBUTE_NODE
|
||||
|
||||
def getSpecified(self):
|
||||
"""
|
||||
If this attribute was explicitly given a value in the
|
||||
original document, this is true; otherwise, it is false.
|
||||
"""
|
||||
return self.specified
|
||||
|
||||
"""
|
||||
create aliases for all above functions in the pythony way.
|
||||
"""
|
||||
|
||||
def _get_NodeName(self):
|
||||
return self.getNodeName()
|
||||
|
||||
def _get_Name(self):
|
||||
return self.getName()
|
||||
|
||||
def _get_NodeValue(self):
|
||||
return self.getNodeValue()
|
||||
|
||||
def _get_NodeType(self):
|
||||
return self.getNodeType()
|
||||
|
||||
def _get_Specified(self):
|
||||
return self.getSpecified()
|
@@ -1,116 +0,0 @@
|
||||
Using Structured Text
|
||||
|
||||
The goal of StructuredText is to make it possible to express
|
||||
structured text using a relatively simple plain text format. Simple
|
||||
structures, like bullets or headings are indicated through
|
||||
conventions that are natural, for some definition of
|
||||
"natural". Hierarchical structures are indicated through
|
||||
indentation. The use of indentation to express hierarchical
|
||||
structure is inspired by the Python programming language.
|
||||
|
||||
Use of StructuredText consists of one to three logical steps. In the
|
||||
first step, a text string is converted to a network of objects using
|
||||
the 'StructuredText.Basic' facility, as in the following
|
||||
example::
|
||||
|
||||
raw=open("mydocument.txt").read()
|
||||
import StructuredText
|
||||
st=StructuredText.Basic(raw)
|
||||
|
||||
The output of 'StructuredText.Basic' is simply a
|
||||
StructuredTextDocument object containing StructuredTextParagraph
|
||||
objects arranged in a hierarchy. Paragraphs are delimited by strings
|
||||
of two or more whitespace characters beginning and ending with
|
||||
newline characters. Hierarchy is indicated by indentation. The
|
||||
indentation of a paragraph is the minimum number of leading spaces
|
||||
in a line containing non-white-space characters after converting tab
|
||||
characters to spaces (assuming a tab stop every eight characters).
|
||||
|
||||
StructuredTextNode objects support the read-only subset of the
|
||||
Document Object Model (DOM) API. It should be possible to process
|
||||
'StructuredTextNode' hierarchies using XML tools such as XSLT.
|
||||
|
||||
The second step in using StructuredText is to apply additional
|
||||
structuring rules based on text content. A variety of differentText
|
||||
rules can be used. Typically, these are used to implement a
|
||||
structured text language for producing documents, but any sort of
|
||||
structured text language could be implemented in the second
|
||||
step. For example, it is possible to use StructuredText to implement
|
||||
structured text formats for representing structured data. The second
|
||||
step, which could consist of multiple processing steps, is
|
||||
performed by processing, or "coloring", the hierarchy of generic
|
||||
StructuredTextParagraph objects into a network of more specialized
|
||||
objects. Typically, the objects produced should also implement the DOM
|
||||
API to allow processing with XML tools.
|
||||
|
||||
A document processor is provided to convert a StructuredTextDocument
|
||||
object containing only StructuredStructuredTextParagraph objects
|
||||
into a StructuredTextDocument object containing a richer collection
|
||||
of objects such as bullets, headings, emphasis, and so on using
|
||||
hints in the text. Hints are selected based on conventions of the
|
||||
sort typically seen in electronic mail or news-group postings. It
|
||||
should be noted, however, that these conventions are somewhat
|
||||
culturally dependent, fortunately, the document processor is easily
|
||||
customized to implement alternative rules. Here's an example of
|
||||
using the DOC processor to convert the output of the previous example::
|
||||
|
||||
doc=StructuredText.Document(st)
|
||||
|
||||
The final step is to process the colored networks produced from the
|
||||
second step to produce additional outputs. The final step could be
|
||||
performed by Python programs, or by XML tools. A Python outputter is
|
||||
provided for the document processor output that produces Hypertext Markup
|
||||
Language (HTML) text::
|
||||
|
||||
html=StructuredText.HTML(doc)
|
||||
|
||||
Customizing the document processor
|
||||
|
||||
The document processor is driven by two tables. The first table,
|
||||
named 'paragraph_types', is a sequence of callable objects or method
|
||||
names for coloring paragraphs. If a table entry is a string, then it
|
||||
is the name of a method of the document processor to be used. For
|
||||
each input paragraph, the objects in the table are called until one
|
||||
returns a value (not 'None'). The value returned replaces the
|
||||
original input paragraph in the output. If none of the objects in
|
||||
the paragraph types table return a value, then a copy of the
|
||||
original paragraph is used. The new object returned by calling a
|
||||
paragraph type should implement the ReadOnlyDOM,
|
||||
StructuredTextColorizable, and StructuredTextSubparagraphContainer
|
||||
interfaces. See the 'Document.py' source file for examples.
|
||||
|
||||
A paragraph type may return a list or tuple of replacement
|
||||
paragraphs, this allowing a paragraph to be split into multiple
|
||||
paragraphs.
|
||||
|
||||
The second table, 'text_types', is a sequence of callable objects or
|
||||
method names for coloring text. The callable objects in this table
|
||||
are used in sequence to transform the input text into new text or
|
||||
objects. The callable objects are passed a string and return
|
||||
nothing ('None') or a three-element tuple consisting of:
|
||||
|
||||
- a replacement object,
|
||||
|
||||
- a starting position, and
|
||||
|
||||
- an ending position
|
||||
|
||||
The text from the starting position is (logically) replaced with the
|
||||
replacement object. The replacement object is typically an object
|
||||
that implements that implements the ReadOnlyDOM, and
|
||||
StructuredTextColorizable interfaces. The replacement object can
|
||||
also be a string or a list of strings or objects. Replacement is
|
||||
done from beginning to end and text after the replacement ending
|
||||
position will be passed to the character type objects for processing.
|
||||
|
||||
Example: adding wiki links
|
||||
|
||||
We want to add support for Wiki links. A Wiki link is a string of
|
||||
text containing mixed-case letters, such that at least two of the
|
||||
letters are upper case and such that the first letter is upper case.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,15 +0,0 @@
|
||||
import string
|
||||
|
||||
try:
|
||||
del string
|
||||
import locale
|
||||
locale.setlocale(locale.LC_ALL,"")
|
||||
except:
|
||||
pass
|
||||
|
||||
import string
|
||||
|
||||
letters = string.letters
|
||||
punctuations = string.punctuation
|
||||
|
||||
lettpunc = letters + punctuations
|
@@ -1,148 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
""" Alias module for StructuredTextClassic compatibility which makes
|
||||
use of StructuredTextNG """
|
||||
|
||||
|
||||
import HTMLClass, DocumentClass, ClassicDocumentClass
|
||||
from ST import Basic
|
||||
|
||||
import re, string,sys
|
||||
from STletters import letters
|
||||
|
||||
Document = ClassicDocumentClass.DocumentClass()
|
||||
HTMLNG = HTMLClass.HTMLClass()
|
||||
|
||||
def HTML(aStructuredString, level=0):
|
||||
st = Basic(aStructuredString)
|
||||
doc = Document(st)
|
||||
return HTMLNG(doc)
|
||||
|
||||
def StructuredText(aStructuredString, level=0):
|
||||
return HTML(aStructuredString,level)
|
||||
|
||||
def html_with_references(text, level=1):
|
||||
text = re.sub(
|
||||
r'[\000\n]\.\. \[([0-9_%s-]+)\]' % letters,
|
||||
r'\n <a name="\1">[\1]</a>',
|
||||
text)
|
||||
|
||||
text = re.sub(
|
||||
r'([\000- ,])\[(?P<ref>[0-9_%s-]+)\]([\000- ,.:])' % letters,
|
||||
r'\1<a href="#\2">[\2]</a>\3',
|
||||
text)
|
||||
|
||||
text = re.sub(
|
||||
r'([\000- ,])\[([^]]+)\.html\]([\000- ,.:])',
|
||||
r'\1<a href="\2.html">[\2]</a>\3',
|
||||
text)
|
||||
|
||||
return HTML(text,level=level)
|
||||
|
||||
def html_quote(v,
|
||||
character_entities=(
|
||||
(re.compile('&'), '&'),
|
||||
(re.compile("<"), '<' ),
|
||||
(re.compile(">"), '>' ),
|
||||
(re.compile('"'), '"')
|
||||
)): #"
|
||||
text=str(v)
|
||||
for re,name in character_entities:
|
||||
text=re.sub(name,text)
|
||||
return text
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
import getopt
|
||||
|
||||
opts,args = getopt.getopt(sys.argv[1:],'',[])
|
||||
|
||||
for k,v in opts:
|
||||
pass
|
||||
|
||||
|
||||
for f in args:
|
||||
print HTML(open(f).read())
|
@@ -1,158 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from Html import HTML
|
||||
from string import split
|
||||
from ST import DOC
|
||||
import re
|
||||
|
||||
"""
|
||||
This is the new structured text type.
|
||||
"""
|
||||
|
||||
class Zwiki_Title:
|
||||
def __init__(self,str=''):
|
||||
self.expr1 = re.compile('([A-Z]+[A-Z]+[a-zA-Z]*)').search
|
||||
self.expr2 = re.compile('([A-Z]+[a-z]+[A-Z]+[a-zA-Z]*)').search
|
||||
self.str = [str]
|
||||
self.typ = "Zwiki_Title"
|
||||
|
||||
def type(self):
|
||||
return '%s' % self.typ
|
||||
|
||||
def string(self):
|
||||
return self.str
|
||||
|
||||
def __getitem__(self,index):
|
||||
return self.str[index]
|
||||
|
||||
def __call__(self,raw_string,subs):
|
||||
|
||||
"""
|
||||
The raw_string is checked to see if it matches the rules
|
||||
for this structured text expression. If the raw_string does,
|
||||
it is parsed for the sub-string which matches and a doc_inner_link
|
||||
instance is returned whose string is the matching substring.
|
||||
If raw_string does not match, nothing is returned.
|
||||
"""
|
||||
|
||||
if self.expr1(raw_string):
|
||||
start,end = self.expr1(raw_string).span()
|
||||
result = Zwiki_Title(raw_string[start:end])
|
||||
result.start,result.end = self.expr1(raw_string).span()
|
||||
return result
|
||||
elif self.expr2(raw_string):
|
||||
start,end = self.expr2(raw_string).span()
|
||||
result = Zwiki_Title(raw_string[start:end])
|
||||
result.start,result.end = self.expr2(raw_string).span()
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
|
||||
def span(self):
|
||||
return self.start,self.end
|
||||
|
||||
class Zwiki_doc(DOC):
|
||||
|
||||
def __init__(self):
|
||||
DOC.__init__(self)
|
||||
"""
|
||||
Add the new type to self.types
|
||||
"""
|
||||
self.types.append(Zwiki_Title())
|
||||
|
||||
class Zwiki_parser(HTML):
|
||||
def __init__(self):
|
||||
HTML.__init__(self)
|
||||
self.types["Zwiki_Title"] = self.zwiki_title
|
||||
|
||||
def zwiki_title(self,object):
|
||||
result = ""
|
||||
for x in object.string():
|
||||
result = result + x
|
||||
result = "<a href=%s>%s</a>" % (result,result)
|
||||
#result = "<dtml-wikiname %s>" % result
|
||||
self.string = self.string + result
|
@@ -1,112 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions in source code must retain the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions, and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Digital Creations requests that attribution be given to Zope
|
||||
# in any manner possible. Zope includes a "Powered by Zope"
|
||||
# button that is installed by default. While it is not a license
|
||||
# violation to remove this button, it is requested that the
|
||||
# attribution remain. A significant investment has been put
|
||||
# into Zope, and this effort will continue if the Zope community
|
||||
# continues to grow. This is one way to assure that growth.
|
||||
#
|
||||
# 4. All advertising materials and documentation mentioning
|
||||
# features derived from or use of this software must display
|
||||
# the following acknowledgement:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# In the event that the product being advertised includes an
|
||||
# intact Zope distribution (with copyright and license included)
|
||||
# then this clause is waived.
|
||||
#
|
||||
# 5. Names associated with Zope or Digital Creations must not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# prior written permission from Digital Creations.
|
||||
#
|
||||
# 6. Modified redistributions of any form whatsoever must retain
|
||||
# the following acknowledgment:
|
||||
#
|
||||
# "This product includes software developed by Digital Creations
|
||||
# for use in the Z Object Publishing Environment
|
||||
# (http://www.zope.org/)."
|
||||
#
|
||||
# Intact (re-)distributions of any official Zope release do not
|
||||
# require an external acknowledgement.
|
||||
#
|
||||
# 7. Modifications are encouraged but must be packaged separately as
|
||||
# patches to official Zope releases. Distributions that do not
|
||||
# clearly separate the patches from the original work must be clearly
|
||||
# labeled as unofficial distributions. Modifications which do not
|
||||
# carry the name Zope may be packaged in any form, as long as they
|
||||
# conform to all of the clauses above.
|
||||
#
|
||||
#
|
||||
# Disclaimer
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
|
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# This software consists of contributions made by Digital Creations and
|
||||
# many individuals on behalf of Digital Creations. Specific
|
||||
# attributions are listed in the accompanying credits file.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import HTMLClass, DocumentClass
|
||||
import ClassicDocumentClass
|
||||
from StructuredText import html_with_references, HTML
|
||||
from ST import Basic
|
||||
import DocBookClass
|
||||
import HTMLWithImages
|
||||
import DocumentWithImages
|
||||
|
||||
ClassicHTML=HTML
|
||||
HTMLNG=HTMLClass.HTMLClass()
|
||||
|
||||
def HTML(src, level=0, type=type, StringType=type('')):
|
||||
if type(src) is StringType:
|
||||
return ClassicHTML(src, level)
|
||||
return HTMLNG(src, level)
|
||||
|
||||
Classic=ClassicDocumentClass.DocumentClass()
|
||||
Document=DocumentClass.DocumentClass()
|
||||
DocumentWithImages=DocumentWithImages.DocumentWithImages()
|
||||
HTMLWithImages=HTMLWithImages.HTMLWithImages()
|
||||
|
||||
DocBookBook=DocBookClass.DocBookBook()
|
||||
DocBookChapter=DocBookClass.DocBookChapter()
|
||||
DocBookChapterWithFigures=DocBookClass.DocBookChapterWithFigures()
|
||||
DocBookArticle=DocBookClass.DocBookArticle()
|
||||
|
||||
|
@@ -1,201 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import sys, os
|
||||
import StructuredText
|
||||
from wxPython.wx import *
|
||||
|
||||
|
||||
USE_WXHTML = 1
|
||||
|
||||
|
||||
if not USE_WXHTML:
|
||||
try: # try to load the IE ActiveX control
|
||||
from wxPython.lib.activexwrapper import MakeActiveXClass
|
||||
import win32com.client.gencache
|
||||
browserModule = win32com.client.gencache.EnsureModule(
|
||||
"{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1)
|
||||
except:
|
||||
USE_WXHTML = 1
|
||||
|
||||
if not USE_WXHTML:
|
||||
BrowserClass = MakeActiveXClass(browserModule.WebBrowser)
|
||||
|
||||
class MyHtmlWindow(BrowserClass):
|
||||
def SetPage(self, html):
|
||||
import tempfile
|
||||
filename = tempfile.mktemp('.html')
|
||||
f = open(filename, 'w')
|
||||
f.write(html)
|
||||
f.close()
|
||||
self.Navigate(os.path.abspath(filename))
|
||||
self.filename = filename
|
||||
|
||||
def OnDocumentComplete(self, pDisp=None, URL=None):
|
||||
os.unlink(self.filename)
|
||||
|
||||
else:
|
||||
from wxPython.html import *
|
||||
MyHtmlWindow = wxHtmlWindow
|
||||
|
||||
|
||||
|
||||
class StxFrame(wxFrame):
|
||||
title = "StxViewer"
|
||||
def __init__(self, stxFile):
|
||||
wxFrame.__init__(self, None, -1, self.title, size=(650, 700),
|
||||
style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
|
||||
|
||||
##self.CreateStatusBar()
|
||||
|
||||
menu = wxMenu()
|
||||
menu.Append(10, "&Open\tCtrl-O", "Open a Structured Text file")
|
||||
EVT_MENU(self, 10, self.OnOpen)
|
||||
menu.Append(20, "&Close", "Close the current file")
|
||||
EVT_MENU(self, 20, self.OnClose)
|
||||
menu.Append(30, "&Save\tCtrl-S", "Save the current file")
|
||||
EVT_MENU(self, 30, self.OnSave)
|
||||
menu.Append(40, "Save &as", "Save the current file to a new name")
|
||||
EVT_MENU(self, 40, self.OnSaveAs)
|
||||
menu.Append(45, "Save as &html", "Save the current file as HTML")
|
||||
EVT_MENU(self, 45, self.OnSaveAsHTML)
|
||||
menu.AppendSeparator()
|
||||
menu.Append(50, "&Refresh\tCtrl-R", "Reload the file from disk")
|
||||
EVT_MENU(self, 50, self.OnRefresh)
|
||||
menu.AppendSeparator()
|
||||
menu.Append(60, "E&xit\tCtrl-X", "Close the application")
|
||||
EVT_MENU(self, 60, self.OnExit)
|
||||
|
||||
|
||||
menuBar = wxMenuBar()
|
||||
menuBar.Append(menu, "&File")
|
||||
self.SetMenuBar(menuBar)
|
||||
|
||||
|
||||
nb = wxNotebook(self, -1)
|
||||
EVT_NOTEBOOK_PAGE_CHANGED(self, -1, self.OnPageChanged)
|
||||
|
||||
self.htmlWin = MyHtmlWindow(nb, -1)
|
||||
nb.AddPage(self.htmlWin, "View")
|
||||
|
||||
self.editWin = wxTextCtrl(nb, -1, "", style=wxTE_MULTILINE)
|
||||
self.editWin.SetFont(wxFont(10, wxTELETYPE, wxNORMAL, wxNORMAL))
|
||||
nb.AddPage(self.editWin, "Edit")
|
||||
|
||||
self.viewHtml = wxTextCtrl(nb, -1, "", style=wxTE_MULTILINE|wxTE_READONLY)
|
||||
self.viewHtml.SetFont(wxFont(10, wxTELETYPE, wxNORMAL, wxNORMAL))
|
||||
nb.AddPage(self.viewHtml, "HTML")
|
||||
|
||||
self.LoadStxFile(stxFile)
|
||||
|
||||
|
||||
def LoadStxFile(self, stxFile):
|
||||
self.file = stxFile
|
||||
if stxFile is not None:
|
||||
text = open(stxFile).read()
|
||||
self.SetTitle(self.title + ': ' + stxFile)
|
||||
else:
|
||||
text = ""
|
||||
self.SetTitle(self.title)
|
||||
self.LoadStxText(text)
|
||||
|
||||
|
||||
def LoadStxText(self, text):
|
||||
# Old ST
|
||||
html = str(StructuredText.html_with_references(text))
|
||||
|
||||
# NG Version
|
||||
#st = StructuredText.Basic(text)
|
||||
#doc = StructuredText.Document(st)
|
||||
#html = StructuredText.HTMLNG(doc)
|
||||
|
||||
self.htmlWin.SetPage(html)
|
||||
self.editWin.SetValue(text)
|
||||
self.viewHtml.SetValue(html)
|
||||
self.html = html
|
||||
|
||||
|
||||
def OnPageChanged(self, evt):
|
||||
if evt.GetOldSelection() == 1: # if it was on the edit page
|
||||
text = self.editWin.GetValue()
|
||||
self.LoadStxText(text)
|
||||
|
||||
|
||||
def OnOpen(self, evt):
|
||||
dlg = wxFileDialog(self, defaultDir=os.getcwd(),
|
||||
wildcard = "STX files (*.stx)|*.stx|"
|
||||
"Text files (*.txt)|*.txt|"
|
||||
"All files (*.*)|*.*",
|
||||
style=wxOPEN)
|
||||
if dlg.ShowModal() == wxID_OK:
|
||||
self.LoadStxFile(dlg.GetPath())
|
||||
dlg.Destroy()
|
||||
|
||||
|
||||
|
||||
def OnClose(self, evt):
|
||||
self.LoadStxFile(None)
|
||||
|
||||
|
||||
def OnSave(self, evt):
|
||||
if not self.file:
|
||||
self.OnSaveAs(evt)
|
||||
else:
|
||||
text = self.editWin.GetValue()
|
||||
open(self.file, 'w').write(text)
|
||||
self.LoadStxFile(self.file)
|
||||
|
||||
|
||||
def OnSaveAs(self, evt):
|
||||
dlg = wxFileDialog(self, "Save as...", defaultDir=os.getcwd(),
|
||||
wildcard = "STX files (*.stx)|*.stx|"
|
||||
"Text files (*.txt)|*.txt|"
|
||||
"All files (*.*)|*.*",
|
||||
style=wxSAVE)
|
||||
if dlg.ShowModal() == wxID_OK:
|
||||
file = dlg.GetPath()
|
||||
text = self.editWin.GetValue()
|
||||
open(file, 'w').write(text)
|
||||
self.LoadStxFile(file)
|
||||
dlg.Destroy()
|
||||
|
||||
|
||||
def OnSaveAsHTML(self, evt):
|
||||
dlg = wxFileDialog(self, "Save as...", defaultDir=os.getcwd(),
|
||||
wildcard = "HTML files (*.html)|*.html|"
|
||||
"All files (*.*)|*.*",
|
||||
style=wxSAVE)
|
||||
if dlg.ShowModal() == wxID_OK:
|
||||
file = dlg.GetPath()
|
||||
text = self.editWin.GetValue()
|
||||
self.LoadStxText(text)
|
||||
open(file, 'w').write(self.html)
|
||||
dlg.Destroy()
|
||||
|
||||
|
||||
|
||||
def OnRefresh(self, evt):
|
||||
self.LoadStxFile(self.file)
|
||||
|
||||
|
||||
def OnExit(self, evt):
|
||||
self.Close(true)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
app = wxPySimpleApp()
|
||||
wxInitAllImageHandlers()
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
filename = sys.argv[1]
|
||||
else:
|
||||
filename = None
|
||||
|
||||
frame = StxFrame(filename)
|
||||
frame.Show(true)
|
||||
app.MainLoop()
|
||||
|
||||
|
||||
|
@@ -1,127 +0,0 @@
|
||||
Structured Text Manipulation
|
||||
|
||||
Parse a structured text string into a form that can be used with
|
||||
structured formats, like html.
|
||||
|
||||
Structured text is text that uses indentation and simple
|
||||
symbology to indicate the structure of a document.
|
||||
|
||||
A structured string consists of a sequence of paragraphs separated by
|
||||
one or more blank lines. Each paragraph has a level which is defined
|
||||
as the minimum indentation of the paragraph. A paragraph is a
|
||||
sub-paragraph of another paragraph if the other paragraph is the last
|
||||
preceding paragraph that has a lower level.
|
||||
|
||||
Special symbology is used to indicate special constructs:
|
||||
|
||||
- A single-line paragraph whose immediately succeeding paragraphs are lower
|
||||
level is treated as a header.
|
||||
|
||||
- A paragraph that begins with a '-', '*', or 'o' is treated as an
|
||||
unordered list (bullet) element.
|
||||
|
||||
- A paragraph that begins with a sequence of digits followed by a
|
||||
white-space character is treated as an ordered list element.
|
||||
|
||||
- A paragraph that begins with a sequence of sequences, where each
|
||||
sequence is a sequence of digits or a sequence of letters followed
|
||||
by a period, is treated as an ordered list element. If the sequence is
|
||||
made up of lower-case i's and v's, a lower-case roman-numeral list is
|
||||
generated. If the sequence is made up of upper-case I's and V's, an
|
||||
upper-case roman-numeral list is generated. If the sequence is made
|
||||
up of other lower case letters (typically a,b,c) a lowercase alphabetic
|
||||
list is generated. If the sequence is made of of other upper case
|
||||
letters (typically, A,B,C) an uppercase alphabetic list is generated.
|
||||
If the sequence is something else (typically, 1,2,3), a arabic-numeral
|
||||
list is generated.
|
||||
|
||||
- A paragraph with a first line that contains some text, followed by
|
||||
some white-space and '--' is treated as a descriptive list element.
|
||||
The leading text is treated as the element title.
|
||||
|
||||
- Sub-paragraphs of a paragraph that ends in the word 'example' or the
|
||||
word 'examples', or '::' is treated as example code and is output as is.
|
||||
|
||||
- Text enclosed single quotes (with white-space to the left of the
|
||||
first quote and whitespace or puctuation to the right of the second quote)
|
||||
is treated as example code.
|
||||
|
||||
- Text surrounded by '*' characters (with white-space to the left of the
|
||||
first '*' and whitespace or puctuation to the right of the second '*')
|
||||
is *emphasized*.
|
||||
|
||||
- Text surrounded by '**' characters (with white-space to the left of the
|
||||
first '**' and whitespace or puctuation to the right of the second '**')
|
||||
is made **strong**.
|
||||
|
||||
- Text surrounded by '_' underscore characters (with whitespace to the left
|
||||
and whitespace or punctuation to the right) is made _underlined_.
|
||||
|
||||
- Text encloded by double quotes followed by a colon, a URL, and concluded
|
||||
by punctuation plus white space, *or* just white space, is treated as a
|
||||
hyper link. For example:
|
||||
|
||||
'"Zope":http://www.zope.org/ is ...'
|
||||
|
||||
Is interpreted as '<a href="http://www.zope.org/">Zope</a> is ...'
|
||||
Note: This works for relative as well as absolute URLs.
|
||||
|
||||
- Text enclosed by double quotes followed by a comma, one or more spaces,
|
||||
an absolute URL and concluded by punctuation plus white space, or just
|
||||
white space, is treated as a hyper link. For example:
|
||||
|
||||
"mail me", mailto:amos@digicool.com.
|
||||
|
||||
Is interpreted as '<a href="mailto:amos@digicool.com">mail me</a>.'
|
||||
|
||||
- Text enclosed in brackets which consists only of letters, digits,
|
||||
underscores and dashes is treated as hyper links within the document.
|
||||
For example:
|
||||
|
||||
As demonstrated by Smith [12] this technique is quite effective.
|
||||
|
||||
Is interpreted as '... by Smith <a href="#12">[12]</a> this ...'. Together
|
||||
with the next rule this allows easy coding of references or end notes.
|
||||
|
||||
- Text enclosed in brackets which is preceded by the start of a line, two
|
||||
periods and a space is treated as a named link. For example:
|
||||
|
||||
.. [12] "Effective Techniques" Smith, Joe ...
|
||||
|
||||
Is interpreted as '<a name="12">[12]</a> "Effective Techniques" ...'.
|
||||
Together with the previous rule this allows easy coding of references or
|
||||
end notes.
|
||||
|
||||
|
||||
- A paragraph that has blocks of text enclosed in '||' is treated as a
|
||||
table. The text blocks correspond to table cells and table rows are
|
||||
denoted by newlines. By default the cells are center aligned. A cell
|
||||
can span more than one column by preceding a block of text with an
|
||||
equivalent number of cell separators '||'. Newlines and '|' cannot
|
||||
be a part of the cell text. For example:
|
||||
|
||||
|||| **Ingredients** ||
|
||||
|| *Name* || *Amount* ||
|
||||
||Spam||10||
|
||||
||Eggs||3||
|
||||
|
||||
is interpreted as::
|
||||
|
||||
<TABLE BORDER=1 CELLPADDING=2>
|
||||
<TR>
|
||||
<TD ALIGN=CENTER COLSPAN=2> <strong>Ingredients</strong> </TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN=CENTER COLSPAN=1> <em>Name</em> </TD>
|
||||
<TD ALIGN=CENTER COLSPAN=1> <em>Amount</em> </TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN=CENTER COLSPAN=1>Spam</TD>
|
||||
<TD ALIGN=CENTER COLSPAN=1>10</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN=CENTER COLSPAN=1>Eggs</TD>
|
||||
<TD ALIGN=CENTER COLSPAN=1>3</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
@@ -89,12 +89,12 @@ class main_window(wxFrame):
|
||||
# Install the tree and the editor.
|
||||
# ------------------------------------------------------------------------------------
|
||||
splitter.SplitVertically (self.tree, self.editor)
|
||||
splitter.SetSashPosition (180, true)
|
||||
splitter.SetSashPosition (180, True)
|
||||
|
||||
self.Show(true)
|
||||
self.Show(True)
|
||||
|
||||
# Some global state variables.
|
||||
self.projectdirty = false
|
||||
self.projectdirty = False
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
# Some nice little handlers.
|
||||
@@ -118,9 +118,9 @@ class main_window(wxFrame):
|
||||
self.tree.Expand (self.root)
|
||||
|
||||
self.editor.Clear()
|
||||
self.editor.Enable (false)
|
||||
self.editor.Enable (False)
|
||||
|
||||
self.projectdirty = false
|
||||
self.projectdirty = False
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
@@ -139,7 +139,7 @@ class main_window(wxFrame):
|
||||
(child,iter) = self.tree.GetNextChild(self.root,iter)
|
||||
output.write (self.tree.GetItemText(child) + "\n")
|
||||
output.close()
|
||||
self.projectdirty = false
|
||||
self.projectdirty = False
|
||||
except IOError:
|
||||
dlg_m = wxMessageDialog (self, 'There was an error saving the project file.',
|
||||
'Error!', wxOK)
|
||||
@@ -151,7 +151,7 @@ class main_window(wxFrame):
|
||||
# ----------------------------------------------------------------------------------------
|
||||
|
||||
def OnProjectOpen(self, event):
|
||||
open_it = true
|
||||
open_it = True
|
||||
if self.projectdirty:
|
||||
dlg=wxMessageDialog(self, 'The project has been changed. Save?', 'wxProject',
|
||||
wxYES_NO | wxCANCEL)
|
||||
@@ -159,7 +159,7 @@ class main_window(wxFrame):
|
||||
if result == wxID_YES:
|
||||
self.project_save()
|
||||
if result == wxID_CANCEL:
|
||||
open_it = false
|
||||
open_it = False
|
||||
dlg.Destroy()
|
||||
if open_it:
|
||||
dlg = wxFileDialog(self, "Choose a project to open", ".", "", "*.wxp", wxOPEN)
|
||||
@@ -168,7 +168,7 @@ class main_window(wxFrame):
|
||||
dlg.Destroy()
|
||||
|
||||
def OnProjectNew(self, event):
|
||||
open_it = true
|
||||
open_it = True
|
||||
if self.projectdirty:
|
||||
dlg=wxMessageDialog(self, 'The project has been changed. Save?', 'wxProject',
|
||||
wxYES_NO | wxCANCEL)
|
||||
@@ -176,7 +176,7 @@ class main_window(wxFrame):
|
||||
if result == wxID_YES:
|
||||
self.project_save()
|
||||
if result == wxID_CANCEL:
|
||||
open_it = false
|
||||
open_it = False
|
||||
dlg.Destroy()
|
||||
|
||||
if open_it:
|
||||
@@ -202,7 +202,7 @@ class main_window(wxFrame):
|
||||
dlg.Destroy()
|
||||
|
||||
def OnProjectExit(self, event):
|
||||
close = true
|
||||
close = True
|
||||
if self.projectdirty:
|
||||
dlg=wxMessageDialog(self, 'The project has been changed. Save?', 'wxProject',
|
||||
wxYES_NO | wxCANCEL)
|
||||
@@ -210,7 +210,7 @@ class main_window(wxFrame):
|
||||
if result == wxID_YES:
|
||||
self.project_save()
|
||||
if result == wxID_CANCEL:
|
||||
close = false
|
||||
close = False
|
||||
dlg.Destroy()
|
||||
if close:
|
||||
self.Close()
|
||||
@@ -243,10 +243,10 @@ class main_window(wxFrame):
|
||||
event.Veto()
|
||||
|
||||
def OnTreeLabelEditEnd(self, event):
|
||||
self.projectdirty = true
|
||||
self.projectdirty = True
|
||||
|
||||
def OnTreeItemActivated(self, event):
|
||||
go_ahead = true
|
||||
go_ahead = True
|
||||
if self.activeitem != self.root:
|
||||
if self.editor.IsModified():
|
||||
dlg=wxMessageDialog(self, 'The edited file has changed. Save it?',
|
||||
@@ -255,7 +255,7 @@ class main_window(wxFrame):
|
||||
if result == wxID_YES:
|
||||
self.editor.SaveFile (self.tree.GetItemText (self.activeitem))
|
||||
if result == wxID_CANCEL:
|
||||
go_ahead = false
|
||||
go_ahead = False
|
||||
dlg.Destroy()
|
||||
if go_ahead:
|
||||
self.tree.SetItemBold (self.activeitem, 0)
|
||||
@@ -279,7 +279,7 @@ class App(wxApp):
|
||||
self.SetTopWindow(frame)
|
||||
if (projfile != 'Unnamed'):
|
||||
frame.project_open (projfile)
|
||||
return true
|
||||
return True
|
||||
|
||||
app = App(0)
|
||||
app.MainLoop()
|
||||
|
1
wxPython/samples/wx_examples/basic/__init__.py
Normal file
1
wxPython/samples/wx_examples/basic/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Python package.
|
27
wxPython/samples/wx_examples/basic/app.py
Executable file
27
wxPython/samples/wx_examples/basic/app.py
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Basic application class."""
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
import wx
|
||||
|
||||
from frame import Frame
|
||||
|
||||
class App(wx.App):
|
||||
"""Application class."""
|
||||
|
||||
def OnInit(self):
|
||||
self.frame = Frame()
|
||||
self.frame.Show()
|
||||
self.SetTopWindow(self.frame)
|
||||
return True
|
||||
|
||||
def main():
|
||||
app = App()
|
||||
app.MainLoop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
33
wxPython/samples/wx_examples/basic/frame.py
Executable file
33
wxPython/samples/wx_examples/basic/frame.py
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Basic frame class, with App for testing."""
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
import wx
|
||||
|
||||
class Frame(wx.Frame):
|
||||
"""Frame class."""
|
||||
|
||||
def __init__(self, parent=None, id=-1, title='Title',
|
||||
pos=wx.DefaultPosition, size=(400, 200)):
|
||||
"""Create a Frame instance."""
|
||||
wx.Frame.__init__(self, parent, id, title, pos, size)
|
||||
|
||||
class App(wx.App):
|
||||
"""Application class."""
|
||||
|
||||
def OnInit(self):
|
||||
self.frame = Frame()
|
||||
self.frame.Show()
|
||||
self.SetTopWindow(self.frame)
|
||||
return True
|
||||
|
||||
def main():
|
||||
app = App()
|
||||
app.MainLoop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
1
wxPython/samples/wx_examples/hello/__init__.py
Normal file
1
wxPython/samples/wx_examples/hello/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Python package.
|
38
wxPython/samples/wx_examples/hello/hello.py
Executable file
38
wxPython/samples/wx_examples/hello/hello.py
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Hello, wxPython! program."""
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
import wx
|
||||
|
||||
class Frame(wx.Frame):
|
||||
"""Frame class that displays an image."""
|
||||
|
||||
def __init__(self, image, parent=None, id=-1,
|
||||
pos=wx.DefaultPosition, title='Hello, wxPython!'):
|
||||
"""Create a Frame instance and display image."""
|
||||
temp = image.ConvertToBitmap()
|
||||
size = temp.GetWidth(), temp.GetHeight()
|
||||
wx.Frame.__init__(self, parent, id, title, pos, size)
|
||||
self.bmp = wx.StaticBitmap(parent=self, id=-1, bitmap=temp)
|
||||
|
||||
class App(wx.App):
|
||||
"""Application class."""
|
||||
|
||||
def OnInit(self):
|
||||
wx.InitAllImageHandlers()
|
||||
image = wx.Image('wxPython.jpg', wx.BITMAP_TYPE_JPEG)
|
||||
self.frame = Frame(image)
|
||||
self.frame.Show()
|
||||
self.SetTopWindow(self.frame)
|
||||
return True
|
||||
|
||||
def main():
|
||||
app = App()
|
||||
app.MainLoop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
BIN
wxPython/samples/wx_examples/hello/wxPython.jpg
Normal file
BIN
wxPython/samples/wx_examples/hello/wxPython.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
Reference in New Issue
Block a user