George Peter Staplin Jan 10, 2006 - A filter in this case is a plugin procedure that users write to alter the behavior of a program or receive notification of some code path being reached. They may also be used in cases other than plugins, such as a code path that requires several procedures to process an event and/or modify the actual event data with upvar.
The code that follows is an abstract way of invoking filters, adding filters for events, and removing filters. It ends with a simple demonstration.
# By George Peter Staplin # # This code implements a general filter mechanism. # # args is the data for the callback. # proc filter {name args} { global filters if {![info exists filters($name)]} { # # There are no filters for $name. # return } foreach script $filters($name) { if {[catch {uplevel 1 [concat $script $args]} err]} { puts stderr "filter error: $err" } } } # # args is the callback. # proc remove.filter {name args} { global filters set i [lsearch -exact $filters($name) $args] set filters($name) [lreplace $filters(name) $i $i] } # # args is the callback # proc add.filter {name args} { global filters lappend filters($name) $args }
# # This is some example test code that uses filters. # proc message.filter msg_var { upvar $msg_var msg set msg hello } proc person.filter person_var { upvar $person_var person # # This is a more sophisticated filter that sets a random name. # set map [list george joe bob] set person [lindex $map [expr {int(rand() * [llength $map])}]] } add.filter MESSAGE message.filter add.filter PERSON person.filter proc main {} { # # These are the defaults that a plugin may override. # set msg greetings set person earthling # # This passes the msg string to every filter in the filter list. # Therefore each filter may modify the msg via upvar. # Depending on your usage you may want to throw an error in add.filter # if an existing filter exists. I however plan to use the filter # mechanism for read-only tasks that pass multiple variables to upvar to # read the state of those variables, in addition to the write filters. # filter MESSAGE msg filter PERSON person puts "$msg $person" } main