xxx would be nice to inherit from delegator could go away if inheriting from delegator could go away if inheriting from delegator perhaps rename to pushfilter xxx perhaps should only support popfilter xxx would be nice to inherit from delegator could go away if inheriting from delegator could go away if inheriting from delegator perhaps rename to pushfilter xxx perhaps should only support popfilter htest
from idlelib.delegator import Delegator
from idlelib.redirector import WidgetRedirector


class Percolator:

    def __init__(self, text):
        
        self.text = text
        self.redir = WidgetRedirector(text)
        self.top = self.bottom = Delegator(text)
        self.bottom.insert = self.redir.register("insert", self.insert)
        self.bottom.delete = self.redir.register("delete", self.delete)
        self.filters = []

    def close(self):
        while self.top is not self.bottom:
            self.removefilter(self.top)
        self.top = None
        self.bottom.setdelegate(None)
        self.bottom = None
        self.redir.close()
        self.redir = None
        self.text = None

    def insert(self, index, chars, tags=None):
        
        self.top.insert(index, chars, tags)

    def delete(self, index1, index2=None):
        
        self.top.delete(index1, index2)

    def insertfilter(self, filter):
        
        assert isinstance(filter, Delegator)
        assert filter.delegate is None
        filter.setdelegate(self.top)
        self.top = filter

    def insertfilterafter(self, filter, after):
        assert isinstance(filter, Delegator)
        assert isinstance(after, Delegator)
        assert filter.delegate is None

        f = self.top
        f.resetcache()
        while f is not after:
            assert f is not self.bottom
            f = f.delegate
            f.resetcache()

        filter.setdelegate(f.delegate)
        f.setdelegate(filter)

    def removefilter(self, filter):
        
        assert isinstance(filter, Delegator)
        assert filter.delegate is not None
        f = self.top
        if f is filter:
            self.top = filter.delegate
            filter.setdelegate(None)
        else:
            while f.delegate is not filter:
                assert f is not self.bottom
                f.resetcache()
                f = f.delegate
            f.setdelegate(filter.delegate)
            filter.setdelegate(None)


def _percolator(parent):  
    import tkinter as tk

    class Tracer(Delegator):
        def __init__(self, name):
            self.name = name
            Delegator.__init__(self, None)

        def insert(self, *args):
            print(self.name, ": insert", args)
            self.delegate.insert(*args)

        def delete(self, *args):
            print(self.name, ": delete", args)
            self.delegate.delete(*args)

    box = tk.Toplevel(parent)
    box.title("Test Percolator")
    x, y = map(int, parent.geometry().split('+')[1:])
    box.geometry("+%d+%d" % (x, y + 175))
    text = tk.Text(box)
    p = Percolator(text)
    pin = p.insertfilter
    pout = p.removefilter
    t1 = Tracer("t1")
    t2 = Tracer("t2")

    def toggle1():
        (pin if var1.get() else pout)(t1)
    def toggle2():
        (pin if var2.get() else pout)(t2)

    text.pack()
    var1 = tk.IntVar(parent)
    cb1 = tk.Checkbutton(box, text="Tracer1", command=toggle1, variable=var1)
    cb1.pack()
    var2 = tk.IntVar(parent)
    cb2 = tk.Checkbutton(box, text="Tracer2", command=toggle2, variable=var2)
    cb2.pack()

if __name__ == "__main__":
    from unittest import main
    main('idlelib.idle_test.test_percolator', verbosity=2, exit=False)

    from idlelib.idle_test.htest import run
    run(_percolator)