AW: AW: AW: [Idle-dev] Extends an events
Matthias Barmeier
barmeier@BARMEIER.COM
Mon, 20 Mar 2000 09:03:02 +0100
This is a multi-part message in MIME format.
------=_NextPart_000_0000_01BF924B.18F7D1C0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
Hi,
its me again. Of course it takes more than one or two hours but I think it
functional
enough to present an intermediate state.
I have marked the codes I have chenged with ### M.Barmeier.
Copy the attached files to your idel-develeopment directory and start idle.
Everything should work like before. If you open a file you see a message in
your console window
where the opened filename is displayed. This message is printed from the
extension RecentList.py.
This is for discussion only!!! Dont use it in any productive environment !!!
So what do you think ??
/*
Dipl.-Inform. Matthias Barmeier Tel: +49 (0)30 79 70 72 87
Büro für Softwareentwicklung Fax +49 (0)30 79 70 72 88
Grunewaldstr. 18 Email: barmeier@barmeier.com
12165 Berlin WWW: <http://www.barmeier.com>
*/
> -----Ursprüngliche Nachricht-----
> Von: guido@CNRI.Reston.VA.US [mailto:guido@CNRI.Reston.VA.US]Im Auftrag
> von Guido van Rossum
> Gesendet: Sonntag, 5. März 2000 13:28
> An: Matthias Barmeier
> Cc: idle-dev@python.org
> Betreff: Re: AW: AW: [Idle-dev] Extends an events
>
>
> > I have checked the Tcl/Tk bind and bindings. But as I can see
> > parameter passing is impossible when using this approach.
>
> In the rare cases where you need to pass parameters around, you can
> place them on the EditorWindow (or whatever) instance. This can
> simply be part of the specs of a particular binding (e.g. open).
>
> > When I find an hour or two in the next week I will try to make a
> > suggestion in form of a modified EditorWindow.py.
>
> Great!
>
> --Guido van Rossum (home page: http://www.python.org/~guido/)
------=_NextPart_000_0000_01BF924B.18F7D1C0
Content-Type: text/plain;
name="IOBinding.py"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="IOBinding.py"
import os
import tkFileDialog
import tkMessageBox
#$ event <<open-window-from-file>>
#$ win <Control-o>
#$ unix <Control-x><Control-f>
#$ event <<save-window>>
#$ win <Control-s>
#$ unix <Control-x><Control-s>
#$ event <<save-window-as-file>>
#$ win <Alt-s>
#$ unix <Control-x><Control-w>
#$ event <<save-copy-of-window-as-file>>
#$ win <Alt-Shift-s>
#$ unix <Control-x><w>
class IOBinding:
def __init__(self, editwin):
self.editwin =3D editwin
self.text =3D editwin.text
### M.BArmeier =20
self.editwin.eventmanager.registerDefaultCallback (self.text, =
"<<open-window-from-file>>", self.open)
self.editwin.eventmanager.registerDefaultCallback (self.text, =
"<<save-window>>", self.save)
self.editwin.eventmanager.registerDefaultCallback (self.text, =
"<<save-window-as-file>>", self.save_as)
self.editwin.eventmanager.registerDefaultCallback (self.text, =
"<<save-copy-of-window-as-file>>", self.save_a_copy)
### --
def close(self):
### M.BArmeier =20
=
self.editwin.eventmanager.unregisterDefaultCallback("<<open-window-from-f=
ile>>")
=
self.editwin.eventmanager.unregisterDefaultCallback("<<save-window>>")
=
self.editwin.eventmanager.unregisterDefaultCallback("<<save-window-as-fil=
e>>")
=
self.editwin.eventmanager.unregisterDefaultCallback("<<save-copy-of-windo=
w-as-file>>")
### --
# Break cycles
self.editwin =3D None
self.text =3D None
self.filename_change_hook =3D None
def get_saved(self):
return self.editwin.get_saved()
def set_saved(self, flag):
self.editwin.set_saved(flag)
def reset_undo(self):
self.editwin.reset_undo()
filename_change_hook =3D None
def set_filename_change_hook(self, hook):
self.filename_change_hook =3D hook
filename =3D None
def set_filename(self, filename):
self.filename =3D filename
self.set_saved(1)
if self.filename_change_hook:
self.filename_change_hook()
def open(self, event):
if self.editwin.flist:
filename =3D self.askopenfile()
if filename:
self.editwin.flist.open(filename)
### M.Barmeier
event["FileName"]=3Dfilename
### --
else:
self.text.focus_set()
### M.Barmeier
return event
### --
# Code for use outside IDLE:
if self.get_saved():
reply =3D self.maybesave()
if reply =3D=3D "cancel":
self.text.focus_set()
return "break"
filename =3D self.askopenfile()
if filename:
self.loadfile(filename)
else:
self.text.focus_set()
return "break"
def loadfile(self, filename):
try:
f =3D open(filename)
chars =3D f.read()
f.close()
except IOError, msg:
tkMessageBox.showerror("I/O Error", str(msg), =
master=3Dself.text)
return 0
self.text.delete("1.0", "end")
self.set_filename(None)
self.text.insert("1.0", chars)
self.reset_undo()
self.set_filename(filename)
self.text.mark_set("insert", "1.0")
self.text.see("insert")
return 1
def maybesave(self):
if self.get_saved():
return "yes"
message =3D "Do you want to save %s before closing?" % (
self.filename or "this untitled document")
m =3D tkMessageBox.Message(
title=3D"Save On Close",
message=3Dmessage,
icon=3DtkMessageBox.QUESTION,
type=3DtkMessageBox.YESNOCANCEL,
master=3Dself.text)
reply =3D m.show()
if reply =3D=3D "yes":
self.save(None)
if not self.get_saved():
reply =3D "cancel"
self.text.focus_set()
return reply
def save(self, event):
if not self.filename:
self.save_as(event)
else:
if self.writefile(self.filename):
self.set_saved(1)
self.text.focus_set()
return "break"
def save_as(self, event):
filename =3D self.asksavefile()
if filename:
if self.writefile(filename):
self.set_filename(filename)
self.set_saved(1)
self.text.focus_set()
return "break"
def save_a_copy(self, event):
filename =3D self.asksavefile()
if filename:
self.writefile(filename)
self.text.focus_set()
return "break"
def writefile(self, filename):
self.fixlastline()
try:
f =3D open(filename, "w")
chars =3D self.text.get("1.0", "end-1c")
f.write(chars)
f.close()
## print "saved to", `filename`
return 1
except IOError, msg:
tkMessageBox.showerror("I/O Error", str(msg),
master=3Dself.text)
return 0
def fixlastline(self):
c =3D self.text.get("end-2c")
if c !=3D '\n':
self.text.insert("end-1c", "\n")
opendialog =3D None
savedialog =3D None
filetypes =3D [
("Python and text files", "*.py *.pyw *.txt", "TEXT"),
("All text files", "*", "TEXT"),
("All files", "*"),
]
def askopenfile(self):
dir, base =3D self.defaultfilename("open")
if not self.opendialog:
self.opendialog =3D tkFileDialog.Open(master=3Dself.text,
=
filetypes=3Dself.filetypes)
return self.opendialog.show(initialdir=3Ddir, =
initialfile=3Dbase)
def defaultfilename(self, mode=3D"open"):
if self.filename:
return os.path.split(self.filename)
else:
try:
pwd =3D os.getcwd()
except os.error:
pwd =3D ""
return pwd, ""
def asksavefile(self):
dir, base =3D self.defaultfilename("save")
if not self.savedialog:
self.savedialog =3D tkFileDialog.SaveAs(master=3Dself.text,
=
filetypes=3Dself.filetypes)
return self.savedialog.show(initialdir=3Ddir, =
initialfile=3Dbase)
def test():
from Tkinter import *
root =3D Tk()
class MyEditWin:
def __init__(self, text):
self.text =3D text
self.flist =3D None
self.text.bind("<Control-o>", self.open)
self.text.bind("<Control-s>", self.save)
self.text.bind("<Alt-s>", self.save_as)
self.text.bind("<Alt-z>", self.save_a_copy)
def get_saved(self): return 0
def set_saved(self, flag): pass
def reset_undo(self): pass
def open(self, event):
self.text.event_generate("<<open-window-from-file>>")
def save(self, event):
self.text.event_generate("<<save-window>>")
def save_as(self, event):
self.text.event_generate("<<save-window-as-file>>")
def save_a_copy(self, event):
self.text.event_generate("<<save-copy-of-window-as-file>>")
text =3D Text(root)
text.pack()
text.focus_set()
editwin =3D MyEditWin(text)
io =3D IOBinding(editwin)
root.mainloop()
if __name__ =3D=3D "__main__":
test()
------=_NextPart_000_0000_01BF924B.18F7D1C0
Content-Type: text/plain;
name="RecentList.py"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="RecentList.py"
# Sample extension: zoom a window to maximum height
import re
import sys
class RecentList:
def __init__(self, editwin):
self.editwin =3D editwin
self.editwin.eventmanager.registerAfterCallback =
("<<open-window-from-file>>", self.recentlist)
def recentlist (self, event):
print "open Completed for file ["+event["FileName"]+"]"
------=_NextPart_000_0000_01BF924B.18F7D1C0
Content-Type: text/plain;
name="EditorWindow.py"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="EditorWindow.py"
import sys
import os
import string
import re
import imp
from Tkinter import *
import tkSimpleDialog
import tkMessageBox
import idlever
import WindowList
### M.Barmeier
from EventManager import *
### --
# The default tab setting for a Text widget, in average-width =
characters.
TK_TABWIDTH_DEFAULT =3D 8
# File menu
#$ event <<open-module>>
#$ win <Alt-m>
#$ unix <Control-x><Control-m>
#$ event <<open-class-browser>>
#$ win <Alt-c>
#$ unix <Control-x><Control-b>
#$ event <<open-path-browser>>
#$ event <<close-window>>
#$ unix <Control-x><Control-0>
#$ unix <Control-x><Key-0>
#$ win <Alt-F4>
# Edit menu
#$ event <<Copy>>
#$ win <Control-c>
#$ unix <Alt-w>
#$ event <<Cut>>
#$ win <Control-x>
#$ unix <Control-w>
#$ event <<Paste>>
#$ win <Control-v>
#$ unix <Control-y>
#$ event <<select-all>>
#$ win <Alt-a>
#$ unix <Alt-a>
# Help menu
#$ event <<help>>
#$ win <F1>
#$ unix <F1>
#$ event <<about-idle>>
# Events without menu entries
#$ event <<remove-selection>>
#$ win <Escape>
#$ event <<center-insert>>
#$ win <Control-l>
#$ unix <Control-l>
#$ event <<do-nothing>>
#$ unix <Control-x>
about_title =3D "About IDLE"
about_text =3D """\
IDLE %s
An Integrated DeveLopment Environment for Python
by Guido van Rossum
""" % idlever.IDLE_VERSION
class EditorWindow:
from Percolator import Percolator
from ColorDelegator import ColorDelegator
from UndoDelegator import UndoDelegator
from IOBinding import IOBinding
import Bindings
from Tkinter import Toplevel
from MultiStatusBar import MultiStatusBar
about_title =3D about_title
about_text =3D about_text
vars =3D {}
def __init__(self, flist=3DNone, filename=3DNone, key=3DNone, =
root=3DNone):
### M.Barmeier
self.eventmanager =3D EventManager()
### --
cprefs =3D self.ColorDelegator.cprefs
self.flist =3D flist
root =3D root or flist.root
self.root =3D root
if flist:
self.vars =3D flist.vars
self.menubar =3D Menu(root)
self.top =3D top =3D self.Toplevel(root, menu=3Dself.menubar)
self.vbar =3D vbar =3D Scrollbar(top, name=3D'vbar')
self.text_frame =3D text_frame =3D Frame(top)
self.text =3D text =3D Text(text_frame, name=3D'text', padx=3D5,
foreground=3Dcprefs.CNormal[0],
background=3Dcprefs.CNormal[1],
highlightcolor=3Dcprefs.CHilite[0],
highlightbackground=3Dcprefs.CHilite[1],
insertbackground=3Dcprefs.CCursor[1],
wrap=3D"none")
self.createmenubar()
self.apply_bindings()
self.top.protocol("WM_DELETE_WINDOW", self.close)
self.top.bind("<<close-window>>", self.close_event)
### M.Barmeier
self.eventmanager.registerDefaultCallback (self.text, =
"<<center-insert>>", self.center_insert_event)
self.eventmanager.registerDefaultCallback (self.text, =
"<<help>>", self.help_dialog)
self.eventmanager.registerDefaultCallback (self.text, =
"<<python-docs>>", self.python_docs)
self.eventmanager.registerDefaultCallback (self.text, =
"<<about-idle>>", self.about_dialog)
self.eventmanager.registerDefaultCallback (self.text, =
"<<open-module>>", self.open_module)
self.eventmanager.registerDefaultCallback (self.text, =
"<<do-nothing>>", lambda event: "break")
self.eventmanager.registerDefaultCallback (self.text, =
"<<select-all>>", self.select_all)
self.eventmanager.registerDefaultCallback (self.text, =
"<<remove-selection>>", self.remove_selection)
self.eventmanager.registerDefaultCallback (self.text, "<3>", =
self.right_menu_event)
if flist:
flist.inversedict[self] =3D key
if key:
flist.dict[key] =3D self
self.eventmanager.registerDefaultCallback (self.text, =
"<<open-new-window>>", self.flist.new_callback)
self.eventmanager.registerDefaultCallback (self.text, =
"<<close-all-windows>>", self.flist.close_all_callback)
self.eventmanager.registerDefaultCallback (self.text, =
"<<open-class-browser>>", self.open_class_browser)
self.eventmanager.registerDefaultCallback (self.text, =
"<<open-path-browser>>", self.open_path_browser)
### --
vbar['command'] =3D text.yview
vbar.pack(side=3DRIGHT, fill=3DY)
text['yscrollcommand'] =3D vbar.set
if sys.platform[:3] =3D=3D 'win':
text['font'] =3D ("lucida console", 8)
# text['font'] =3D ("courier new", 10)
text_frame.pack(side=3DLEFT, fill=3DBOTH, expand=3D1)
text.pack(side=3DTOP, fill=3DBOTH, expand=3D1)
text.focus_set()
self.per =3D per =3D self.Percolator(text)
if self.ispythonsource(filename):
self.color =3D color =3D self.ColorDelegator(); =
per.insertfilter(color)
##print "Initial colorizer"
else:
##print "No initial colorizer"
self.color =3D None
self.undo =3D undo =3D self.UndoDelegator(); =
per.insertfilter(undo)
self.io =3D io =3D self.IOBinding(self)
text.undo_block_start =3D undo.undo_block_start
text.undo_block_stop =3D undo.undo_block_stop
undo.set_saved_change_hook(self.saved_change_hook)
io.set_filename_change_hook(self.filename_change_hook)
if filename:
if os.path.exists(filename):
io.loadfile(filename)
else:
io.set_filename(filename)
self.saved_change_hook()
self.load_extensions()
menu =3D self.menudict.get('windows')
if menu:
end =3D menu.index("end")
if end is None:
end =3D -1
if end >=3D 0:
menu.add_separator()
end =3D end + 1
self.wmenu_end =3D end
WindowList.register_callback(self.postwindowsmenu)
# Some abstractions so IDLE extensions are cross-IDE
self.askyesno =3D tkMessageBox.askyesno
self.askinteger =3D tkSimpleDialog.askinteger
self.showerror =3D tkMessageBox.showerror
if self.extensions.has_key('AutoIndent'):
self.extensions['AutoIndent'].set_indentation_params(
self.ispythonsource(filename))
self.set_status_bar()
def set_status_bar(self):
self.status_bar =3D self.MultiStatusBar(self.text_frame)
self.status_bar.set_label('column', 'Col: ?', side=3DRIGHT)
self.status_bar.set_label('line', 'Ln: ?', side=3DRIGHT)
self.status_bar.pack(side=3DBOTTOM, fill=3DX)
self.text.bind('<KeyRelease>', self.set_line_and_column)
self.text.bind('<ButtonRelease>', self.set_line_and_column)
self.text.after_idle(self.set_line_and_column)
def set_line_and_column(self, event=3DNone):
line, column =3D string.split(self.text.index(INSERT), '.')
self.status_bar.set_label('column', 'Col: %s' % column)
self.status_bar.set_label('line', 'Ln: %s' % line)
def wakeup(self):
if self.top.wm_state() =3D=3D "iconic":
self.top.wm_deiconify()
else:
self.top.tkraise()
self.text.focus_set()
menu_specs =3D [
("file", "_File"),
("edit", "_Edit"),
("windows", "_Windows"),
("help", "_Help"),
]
def createmenubar(self):
mbar =3D self.menubar
self.menudict =3D menudict =3D {}
for name, label in self.menu_specs:
underline, label =3D prepstr(label)
menudict[name] =3D menu =3D Menu(mbar, name=3Dname)
mbar.add_cascade(label=3Dlabel, menu=3Dmenu, =
underline=3Dunderline)
self.fill_menus()
def postwindowsmenu(self):
# Only called when Windows menu exists
# XXX Actually, this Just-In-Time updating interferes badly
# XXX with the tear-off feature. It would be better to update
# XXX all Windows menus whenever the list of windows changes.
menu =3D self.menudict['windows']
end =3D menu.index("end")
if end is None:
end =3D -1
if end > self.wmenu_end:
menu.delete(self.wmenu_end+1, end)
WindowList.add_windows_to_menu(menu)
rmenu =3D None
def right_menu_event(self, event):
self.text.tag_remove("sel", "1.0", "end")
self.text.mark_set("insert", "@%d,%d" % (event.x, event.y))
if not self.rmenu:
self.make_rmenu()
rmenu =3D self.rmenu
self.event =3D event
iswin =3D sys.platform[:3] =3D=3D 'win'
if iswin:
self.text.config(cursor=3D"arrow")
rmenu.tk_popup(event.x_root, event.y_root)
if iswin:
self.text.config(cursor=3D"ibeam")
rmenu_specs =3D [
# ("Label", "<<virtual-event>>"), ...
("Close", "<<close-window>>"), # Example
]
def make_rmenu(self):
rmenu =3D Menu(self.text, tearoff=3D0)
for label, eventname in self.rmenu_specs:
def command(text=3Dself.text, eventname=3Deventname):
text.event_generate(eventname)
rmenu.add_command(label=3Dlabel, command=3Dcommand)
self.rmenu =3D rmenu
def about_dialog(self, event=3DNone):
tkMessageBox.showinfo(self.about_title, self.about_text,
master=3Dself.text)
helpfile =3D "help.txt"
def help_dialog(self, event=3DNone):
try:
helpfile =3D os.path.join(os.path.dirname(__file__), =
self.helpfile)
except NameError:
helpfile =3D self.helpfile
if self.flist:
self.flist.open(helpfile)
else:
self.io.loadfile(helpfile)
# XXX Fix these for Windows
help_viewer =3D "netscape -remote 'openurl(%(url)s)' 2>/dev/null || =
" \
"netscape %(url)s &"
help_url =3D "http://www.python.org/doc/current/"
def python_docs(self, event=3DNone):
cmd =3D self.help_viewer % {"url": self.help_url}
os.system(cmd)
def select_all(self, event=3DNone):
self.text.tag_add("sel", "1.0", "end-1c")
self.text.mark_set("insert", "1.0")
self.text.see("insert")
return "break"
def remove_selection(self, event=3DNone):
self.text.tag_remove("sel", "1.0", "end")
self.text.see("insert")
def open_module(self, event=3DNone):
# XXX Shouldn't this be in IOBinding or in FileList?
try:
name =3D self.text.get("sel.first", "sel.last")
except TclError:
name =3D ""
else:
name =3D string.strip(name)
if not name:
name =3D tkSimpleDialog.askstring("Module",
"Enter the name of a Python module\n"
"to search on sys.path and open:",
parent=3Dself.text)
if name:
name =3D string.strip(name)
if not name:
return
# XXX Ought to support package syntax
# XXX Ought to insert current file's directory in front of path
try:
(f, file, (suffix, mode, type)) =3D imp.find_module(name)
except (NameError, ImportError), msg:
tkMessageBox.showerror("Import error", str(msg), =
parent=3Dself.text)
return
if type !=3D imp.PY_SOURCE:
tkMessageBox.showerror("Unsupported type",
"%s is not a source module" % name, parent=3Dself.text)
return
if f:
f.close()
if self.flist:
self.flist.open(file)
else:
self.io.loadfile(file)
def open_class_browser(self, event=3DNone):
filename =3D self.io.filename
if not filename:
tkMessageBox.showerror(
"No filename",
"This buffer has no associated filename",
master=3Dself.text)
self.text.focus_set()
return None
head, tail =3D os.path.split(filename)
base, ext =3D os.path.splitext(tail)
import ClassBrowser
ClassBrowser.ClassBrowser(self.flist, base, [head])
def open_path_browser(self, event=3DNone):
import PathBrowser
PathBrowser.PathBrowser(self.flist)
def gotoline(self, lineno):
if lineno is not None and lineno > 0:
self.text.mark_set("insert", "%d.0" % lineno)
self.text.tag_remove("sel", "1.0", "end")
self.text.tag_add("sel", "insert", "insert +1l")
self.center()
def ispythonsource(self, filename):
if not filename:
return 1
base, ext =3D os.path.splitext(os.path.basename(filename))
if os.path.normcase(ext) in (".py", ".pyw"):
return 1
try:
f =3D open(filename)
line =3D f.readline()
f.close()
except IOError:
return 0
return line[:2] =3D=3D '#!' and string.find(line, 'python') >=3D =
0
def close_hook(self):
if self.flist:
self.flist.close_edit(self)
def set_close_hook(self, close_hook):
self.close_hook =3D close_hook
def filename_change_hook(self):
if self.flist:
self.flist.filename_changed_edit(self)
self.saved_change_hook()
if self.ispythonsource(self.io.filename):
self.addcolorizer()
else:
self.rmcolorizer()
def addcolorizer(self):
if self.color:
return
##print "Add colorizer"
self.per.removefilter(self.undo)
self.color =3D self.ColorDelegator()
self.per.insertfilter(self.color)
self.per.insertfilter(self.undo)
def rmcolorizer(self):
if not self.color:
return
##print "Remove colorizer"
self.per.removefilter(self.undo)
self.per.removefilter(self.color)
self.color =3D None
self.per.insertfilter(self.undo)
def saved_change_hook(self):
short =3D self.short_title()
long =3D self.long_title()
if short and long:
title =3D short + " - " + long
elif short:
title =3D short
elif long:
title =3D long
else:
title =3D "Untitled"
icon =3D short or long or title
if not self.get_saved():
title =3D "*%s*" % title
icon =3D "*%s" % icon
self.top.wm_title(title)
self.top.wm_iconname(icon)
def get_saved(self):
return self.undo.get_saved()
def set_saved(self, flag):
self.undo.set_saved(flag)
def reset_undo(self):
self.undo.reset_undo()
def short_title(self):
filename =3D self.io.filename
if filename:
filename =3D os.path.basename(filename)
return filename
def long_title(self):
return self.io.filename or ""
def center_insert_event(self, event):
self.center()
def center(self, mark=3D"insert"):
text =3D self.text
top, bot =3D self.getwindowlines()
lineno =3D self.getlineno(mark)
height =3D bot - top
newtop =3D max(1, lineno - height/2)
text.yview(float(newtop))
def getwindowlines(self):
text =3D self.text
top =3D self.getlineno("@0,0")
bot =3D self.getlineno("@0,65535")
if top =3D=3D bot and text.winfo_height() =3D=3D 1:
# Geometry manager hasn't run yet
height =3D int(text['height'])
bot =3D top + height - 1
return top, bot
def getlineno(self, mark=3D"insert"):
text =3D self.text
return int(float(text.index(mark)))
def close_event(self, event):
self.close()
def maybesave(self):
if self.io:
return self.io.maybesave()
def close(self):
self.top.wm_deiconify()
self.top.tkraise()
reply =3D self.maybesave()
if reply !=3D "cancel":
self._close()
return reply
def _close(self):
WindowList.unregister_callback(self.postwindowsmenu)
if self.close_hook:
self.close_hook()
self.flist =3D None
colorizing =3D 0
self.unload_extensions()
self.io.close(); self.io =3D None
self.undo =3D None # XXX
if self.color:
colorizing =3D self.color.colorizing
doh =3D colorizing and self.top
self.color.close(doh) # Cancel colorization
self.text =3D None
self.vars =3D None
self.per.close(); self.per =3D None
if not colorizing:
self.top.destroy()
def load_extensions(self):
self.extensions =3D {}
self.load_standard_extensions()
def unload_extensions(self):
for ins in self.extensions.values():
if hasattr(ins, "close"):
ins.close()
self.extensions =3D {}
def load_standard_extensions(self):
for name in self.get_standard_extension_names():
try:
self.load_extension(name)
except:
print "Failed to load extension", `name`
import traceback
traceback.print_exc()
def get_standard_extension_names(self):
import extend
return extend.standard
def load_extension(self, name):
mod =3D __import__(name, globals(), locals(), [])
cls =3D getattr(mod, name)
ins =3D cls(self)
self.extensions[name] =3D ins
kdnames =3D ["keydefs"]
if sys.platform =3D=3D 'win32':
kdnames.append("windows_keydefs")
elif sys.platform =3D=3D 'mac':
kdnames.append("mac_keydefs")
else:
kdnames.append("unix_keydefs")
keydefs =3D {}
for kdname in kdnames:
if hasattr(ins, kdname):
keydefs.update(getattr(ins, kdname))
if keydefs:
self.apply_bindings(keydefs)
for vevent in keydefs.keys():
methodname =3D string.replace(vevent, "-", "_")
while methodname[:1] =3D=3D '<':
methodname =3D methodname[1:]
while methodname[-1:] =3D=3D '>':
methodname =3D methodname[:-1]
methodname =3D methodname + "_event"
if hasattr(ins, methodname):
self.text.bind(vevent, getattr(ins, methodname))
if hasattr(ins, "menudefs"):
self.fill_menus(ins.menudefs, keydefs)
return ins
def apply_bindings(self, keydefs=3DNone):
if keydefs is None:
keydefs =3D self.Bindings.default_keydefs
text =3D self.text
text.keydefs =3D keydefs
for event, keylist in keydefs.items():
if keylist:
apply(text.event_add, (event,) + tuple(keylist))
def fill_menus(self, defs=3DNone, keydefs=3DNone):
# Fill the menus. Menus that are absent or None in
# self.menudict are ignored.
if defs is None:
defs =3D self.Bindings.menudefs
if keydefs is None:
keydefs =3D self.Bindings.default_keydefs
menudict =3D self.menudict
text =3D self.text
for mname, itemlist in defs:
menu =3D menudict.get(mname)
if not menu:
continue
for item in itemlist:
if not item:
menu.add_separator()
else:
label, event =3D item
checkbutton =3D (label[:1] =3D=3D '!')
if checkbutton:
label =3D label[1:]
underline, label =3D prepstr(label)
accelerator =3D get_accelerator(keydefs, event)
## strange function !
def command(text=3Dtext, event=3Devent):
text.event_generate(event)
if checkbutton:
var =3D self.getrawvar(event, BooleanVar)
menu.add_checkbutton(label=3Dlabel, =
underline=3Dunderline,
command=3Dcommand, =
accelerator=3Daccelerator,
variable=3Dvar)
else:
menu.add_command(label=3Dlabel, =
underline=3Dunderline,
command=3Dcommand, =
accelerator=3Daccelerator)
def getvar(self, name):
var =3D self.getrawvar(name)
if var:
return var.get()
def setvar(self, name, value, vartype=3DNone):
var =3D self.getrawvar(name, vartype)
if var:
var.set(value)
def getrawvar(self, name, vartype=3DNone):
var =3D self.vars.get(name)
if not var and vartype:
self.vars[name] =3D var =3D vartype(self.text)
return var
# Tk implementations of "virtual text methods" -- each platform
# reusing IDLE's support code needs to define these for its GUI's
# flavor of widget.
# Is character at text_index in a Python string? Return 0 for
# "guaranteed no", true for anything else. This info is expensive
# to compute ab initio, but is probably already known by the
# platform's colorizer.
def is_char_in_string(self, text_index):
if self.color:
# Return true iff colorizer hasn't (re)gotten this far
# yet, or the character is tagged as being in a string
return self.text.tag_prevrange("TODO", text_index) or \
"STRING" in self.text.tag_names(text_index)
else:
# The colorizer is missing: assume the worst
return 1
# If a selection is defined in the text widget, return (start,
# end) as Tkinter text indices, otherwise return (None, None)
def get_selection_indices(self):
try:
first =3D self.text.index("sel.first")
last =3D self.text.index("sel.last")
return first, last
except TclError:
return None, None
# Return the text widget's current view of what a tab stop means
# (equivalent width in spaces).
def get_tabwidth(self):
current =3D self.text['tabs'] or TK_TABWIDTH_DEFAULT
return int(current)
# Set the text widget's current view of what a tab stop means.
def set_tabwidth(self, newtabwidth):
text =3D self.text
if self.get_tabwidth() !=3D newtabwidth:
pixels =3D text.tk.call("font", "measure", text["font"],
"-displayof", text.master,
"n" * newtabwith)
text.configure(tabs=3Dpixels)
def prepstr(s):
# Helper to extract the underscore from a string, e.g.
# prepstr("Co_py") returns (2, "Copy").
i =3D string.find(s, '_')
if i >=3D 0:
s =3D s[:i] + s[i+1:]
return i, s
keynames =3D {
'bracketleft': '[',
'bracketright': ']',
'slash': '/',
}
def get_accelerator(keydefs, event):
keylist =3D keydefs.get(event)
if not keylist:
return ""
s =3D keylist[0]
s =3D re.sub(r"-[a-z]\b", lambda m: string.upper(m.group()), s)
s =3D re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), =
m.group()), s)
s =3D re.sub("Key-", "", s)
s =3D re.sub("Control-", "Ctrl-", s)
s =3D re.sub("-", "+", s)
s =3D re.sub("><", " ", s)
s =3D re.sub("<", "", s)
s =3D re.sub(">", "", s)
return s
def fixwordbreaks(root):
# Make sure that Tk's double-click and next/previous word
# operations use our definition of a word (i.e. an identifier)
tk =3D root.tk
tk.call('tcl_wordBreakAfter', 'a b', 0) # make sure word.tcl is =
loaded
tk.call('set', 'tcl_wordchars', '[a-zA-Z0-9_]')
tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]')
def test():
root =3D Tk()
fixwordbreaks(root)
root.withdraw()
if sys.argv[1:]:
filename =3D sys.argv[1]
else:
filename =3D None
edit =3D EditorWindow(root=3Droot, filename=3Dfilename)
edit.set_close_hook(root.quit)
root.mainloop()
root.destroy()
if __name__ =3D=3D '__main__':
test()
------=_NextPart_000_0000_01BF924B.18F7D1C0
Content-Type: text/plain;
name="EventManager.py"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="EventManager.py"
class EventManager:
def __init__ (self):
print "initialized"
self.evtmgr=3D{}
def typeSort (self, one, two):
return cmp(one[1], two[1])
##
## This functions registers all callbacks that have to be called =
before the default callback
## is initiated
##
def registerAfterCallback (self, itemName, defaultCallback, =
type=3D3):
if not self.evtmgr.has_key(itemName):
raise "No DefaultCallback found for "+itemName
self.evtmgr[itemName].append((defaultCallback,type,None,None))
self.evtmgr[itemName].sort(self.typeSort) =09
##
## This functions registers all callbacks that have to be called =
after the default callback
## is initiated
##
def registerBeforeCallback (self, itemName, defaultCallback, =
type=3D1):
if not self.evtmgr.has_key(itemName):
raise "No DefaultCallback found for "+itemName
self.evtmgr[itemName].append((defaultCallback,type,None,None))
self.evtmgr[itemName].sort(self.typeSort) =09
##
## This functions registers the default callback. This function =
replaces the xxx.bind calls
## for all interceptable events.
##
def registerDefaultCallback (self, widget, itemName, =
defaultCallback, type=3D2):
##
## If the Event is registered the first time a real Tcl/Tk =
callback must be added
## this callback points to the driveEvent Function where the =
registered Callback will
## be initiated if the event is triggered ?!
##
if not self.evtmgr.has_key(itemName):
evtbind=3Dwidget.bind(itemName, lambda e, =
cb=3Dself.driveEvent, itemName=3DitemName: cb(e, itemName))
self.evtmgr[itemName]=3D[]
else:
raise "DefaultCallback already registered for "+itemName
=
self.evtmgr[itemName].append((defaultCallback,type,widget,evtbind))
self.evtmgr[itemName].sort(self.typeSort) =09
##
## This functions removes the defautl callbacks and all attached =
callbacks.
##
def unregisterDefaultCallback (self, itemName):
self.evtmgr[itemName][0][2].unbind (itemName, =
self.evtmgr[itemName][0][3])
self.evtmgr[itemName]=3DNone
##
## Process an event by calling all callbakcs registered
##
def driveEvent (self, event, name):
results=3D{}
print len(self.evtmgr[name])
for calls,type,widget,evtbind in self.evtmgr[name]:
print "####"
results=3Dcalls (results)
##To add the standard functionality :
##
## def openfile (itemName, params):
## if !params.has_key("defaultdir"):
## ... use standard directory to open file dialog ...
## else:
## ... use params["defaultdir"] ...
##
## ... after selectting a file ...
## params["filename"]=3Dthe_filename
## return (params)
##
## menuRegisterCallback ("File/Open...", openfile, 2)
##
##To intercept:
##
## def maintainRecentlist (itemName, params):
## addFileToRecentList (itemName)
## return (params) ## do nothing with the params
##
## menuRegisterCallback ("File/Open...", maintainRecentList, 3)
------=_NextPart_000_0000_01BF924B.18F7D1C0
Content-Type: text/plain;
name="extend.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="extend.py"
# IDLE extensions to be loaded by default (see extend.txt).
# Edit this file to configure your set of IDLE extensions.
standard = [
"SearchBinding",
"AutoIndent",
"AutoExpand",
"FormatParagraph",
"ZoomHeight",
"ScriptBinding",
"CallTips",
"RecentList",
]
------=_NextPart_000_0000_01BF924B.18F7D1C0--