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--