Attachment "hook.txt" to
ticket [3167244fff]
added by
egavilan
2011-01-29 01:58:21.
hook(n) Hooks hook(n)
______________________________________________________________________________
NNAAMMEE
hook - Hooks
SSYYNNOOPPSSIISS
package require TTccll 88..55
package require hhooookk ??00..11??
hhooookk bbiinndd ?_s_u_b_j_e_c_t? ?_h_o_o_k? ?_o_b_s_e_r_v_e_r? ?_c_m_d_P_r_e_f_i_x?
hhooookk ccaallll _s_u_b_j_e_c_t _h_o_o_k ?_a_r_g_s...?
hhooookk ffoorrggeett _o_b_j_e_c_t
hhooookk ccggeett _o_p_t_i_o_n
hhooookk ccoonnffiigguurree ooppttiioonn _v_a_l_u_e ...
_________________________________________________________________
DDEESSCCRRIIPPTTIIOONN
This package provides the hhooookk ensemble command, which implements the
Subject/Observer pattern. It allows _s_u_b_j_e_c_t_s, which may be _m_o_d_u_l_e_s,
_o_b_j_e_c_t_s, _w_i_d_g_e_t_s, and so forth, to synchronously call _h_o_o_k_s which may
be bound to an arbitrary number of subscribers, called _o_b_s_e_r_v_e_r_s. A
subject may call any number of distinct hooks, and any number of
observers can bind callbacks to a particular hook called by a particu-
lar subject. Hook bindings can be queried and deleted.
This man page is intended to be a reference only.
CCOONNCCEEPPTTSS
IINNTTRROODDUUCCTTIIOONN
Tcl modules usually send notifications to other modules in two ways:
via Tk events, and via callback options like the text widget's
--yyssccrroollllccoommmmaanndd option. Tk events are available only in Tk, and call-
back options require tight coupling between the modules sending and
receiving the notification.
Loose coupling between sender and receiver is often desirable, however.
In Model/View/Controller terms, a View can send a command (stemming
from user input) to the Controller, which updates the Model. The Model
can then call a hook _t_o _w_h_i_c_h _a_l_l _r_e_l_e_v_a_n_t _V_i_e_w_s _s_u_b_s_c_r_i_b_e_. The Model
is decoupled from the Views, and indeed need not know whether any Views
actually exist. At present, Tcl/Tk has no standard mechanism for
implementing loose coupling of this kind. This package defines a new
command, hhooookk, which implements just such a mechanism.
BBIINNDDIINNGGSS
The hhooookk command manages a collection of hook bindings. A hook binding
has four elements:
[1] A _s_u_b_j_e_c_t: the name of the entity that will be calling the hook.
[2] The _h_o_o_k itself. A hook usually reflects some occurrence in the
life of the _s_u_b_j_e_c_t that other entities might care to know
about. A _h_o_o_k has a name, and may also have arguments. Hook
names are arbitrary strings. Each _s_u_b_j_e_c_t must document the
names and arguments of the hooks it can call.
[3] The name of the _o_b_s_e_r_v_e_r that wishes to receive the _h_o_o_k from
the _s_u_b_j_e_c_t.
[4] A command prefix to which the _h_o_o_k arguments will be appended
when the binding is executed.
SSUUBBJJEECCTTSS AANNDD OOBBSSEERRVVEERRSS
For convenience, this document collectively refers to subjects and
observers as _o_b_j_e_c_t_s, while placing no requirements on how these
_o_b_j_e_c_t_s are actually implemented. An object can be a TTccllOOOO or SSnniitt or
XXOOTTccll object, a Tcl command, a namespace, a module, a pseudo-object
managed by some other object (as tags are managed by the Tk text wid-
get) or simply a well-known name.
Subject and observer names are arbitrary strings; however, as hhooookk
might be used at the package level, it's necessary to have conventions
that avoid name collisions between packages written by different peo-
ple.
Therefore, any subject or observer name used in core or package level
code should look like a Tcl command name, and should be defined in a
namespace owned by the package. Consider, for example, an ensemble com-
mand ::::ffoooo that creates a set of pseudo-objects and uses hhooookk to send
notifications. The pseudo-objects have names that are not commands and
exist in their own namespace, rather like file handles do. To avoid
name collisions with subjects defined by other packages, users of hhooookk,
these ::::ffoooo handles should have names like ::::ffoooo::::11, ::::ffoooo::::22, and so
on.
Because object names are arbitrary strings, application code can use
whatever additional conventions are dictated by the needs of the appli-
cation.
RREEFFEERREENNCCEE
Hook provides the following commands:
hhooookk bbiinndd ?_s_u_b_j_e_c_t? ?_h_o_o_k? ?_o_b_s_e_r_v_e_r? ?_c_m_d_P_r_e_f_i_x?
This subcommand is used to create, update, delete, and query
hook bindings.
Called with no arguments it returns a list of the subjects with
hooks to which observers are currently bound.
Called with one argument, a _s_u_b_j_e_c_t, it returns a list of the
subject's hooks to which observers are currently bound.
Called with two arguments, a _s_u_b_j_e_c_t and a _h_o_o_k, it returns a
list of the observers which are currently bound to this _s_u_b_j_e_c_t
and _h_o_o_k.
Called with three arguments, a _s_u_b_j_e_c_t, a _h_o_o_k, and an _o_b_s_e_r_v_e_r,
it returns the binding proper, the command prefix to be called
when the hook is called, or the empty string if there is no such
binding.
Called with four arguments, it creates, updates, or deletes a
binding. If _c_m_d_P_r_e_f_i_x is the empty string, it deletes any exist-
ing binding for the _s_u_b_j_e_c_t, _h_o_o_k, and _o_b_s_e_r_v_e_r; nothing is
returned. Otherwise, _c_m_d_P_r_e_f_i_x must be a command prefix taking
as many additional arguments as are documented for the _s_u_b_j_e_c_t
and _h_o_o_k. The binding is added or updated, and the observer is
returned.
If the _o_b_s_e_r_v_e_r is the empty string, "", it will create a new
binding using an automatically generated observer name of the
form ::::hhooookk::::oobb<nnuummbbeerr>. The automatically generated name will
be returned, and can be used to query, update, and delete the
binding as usual. If automated observer names are always used,
the observer name effectively becomes a unique binding ID.
It is possible to call hhooookk bbiinndd to create or delete a binding
to a _s_u_b_j_e_c_t and _h_o_o_k while in an observer binding for that same
_s_u_b_j_e_c_t and _h_o_o_k. The following rules determine what happens
when
hook bind $s $h $o $binding
called during the execution of
hook call $s $h
[1]
No binding is ever called after it is deleted.
[2]
When a binding is called, the most recently given command prefix is
always used.
[3]
The set of observers whose bindings are to be called is determined
when this method begins to execute, and does not change thereafter,
except that deleted bindings are not called.
In particular:
[1]
If $$oo's binding to $$ss and $$hh is deleted, and
$$oo's binding has not yet been called during this execution of
hook call $s $h
might already have been called; and in all likelihood, it is probably
deleting itself.)
[2]
If $$oo changes the command prefix that's bound to $$ss and
$$hh, and if $$oo's binding has not yet been called during
this execution of
hook call $s $h
be called when the time comes. (But again, it is probably $$oo's
binding that is is making the change.)
[3]
If a new observer is bound to $$ss and $$hh, its binding will
not be called until the next invocation of
hook call $s $h
hhooookk ccaallll _s_u_b_j_e_c_t _h_o_o_k ?_a_r_g_s...?
This command is called when the named _s_u_b_j_e_c_t wishes to call the
named _h_o_o_k. All relevant bindings are called with the specified
arguments in the global namespace. Note that the bindings are called
synchronously, before the command returns; this allows the _a_r_g_s
to include references to entities that will be cleaned up as soon as
the hook has been called.
The order in which the bindings are called is not guaranteed. If
sequence among observers must be preserved, define one observer and
have its bindings call the other callbacks directly in the proper
sequence.
Because the hhooookk mechanism is intended to support loose
coupling, it is presumed that the _s_u_b_j_e_c_t has no knowledge of
the observers, nor any expectation regarding return values. This has a
number of implications:
[1]
hhooookk ccaallll returns the empty string.
[2]
Normal return values from observer bindings are ignored.
[3]
Errors and other exceptional returns propagate normally by
default. This will rarely be what is wanted, because the subjects
usually have no knowledge of the observers and will therefore have no
particular competence at handling their errors. That makes it an
application issue, and so applications will usually want to define an
--eerrrroorrccoommmmaanndd.
If the --eerrrroorrccoommmmaanndd configuration option has a non-empty
value, its value will be invoked for all errors and other exceptional
returns in observer bindings. See hhooookk ccoonnffiigguurree, below, for
more information on configuration options.
hhooookk ffoorrggeett _o_b_j_e_c_t
This command deletes any existing bindings in which the named
_o_b_j_e_c_t appears as either the _s_u_b_j_e_c_t or the
_o_b_s_e_r_v_e_r.
Bindings deleted by this method will never be called again. In
particular,
[1]
If an observer is forgotten during a call to hhooookk ccaallll, any
uncalled binding it might have had to the relevant subject and hook
will _n_o_t be called subsequently.
[2]
If a subject $$ss is forgotten during a call to
hook call $s $h
soon as the current binding returns. No further bindings will be
called.
hhooookk ccggeett _o_p_t_i_o_n
This command returns the value of one of the hhooookk command's
configuration options.
hhooookk ccoonnffiigguurree ooppttiioonn _v_a_l_u_e ...
This command sets the value of one or more of the hhooookk command's
configuration options:
--eerrrroorrccoommmmaanndd _c_m_d_P_r_e_f_i_x
If the value of this option is the empty string, "", then errors
and other exception returns in binding scripts are propagated
normally. Otherwise, it must be a command prefix taking three
additional arguments:
[1] a 4-element list {subject hook arglist observer},
[2] the result string, and
[3] the return options dictionary.
Given this information, the --eerrrroorrccoommmmaanndd can choose to log
the error, call iinntteerrpp bbggeerrrroorr, delete the errant binding
(thus preventing the error from arising a second time) and so forth.
--ttrraacceeccoommmmaanndd _c_m_d_P_r_e_f_i_x
The option's value should be a command prefix taking four
arguments:
[1] a _s_u_b_j_e_c_t,
[2] a _h_o_o_k,
[3] a list of the hook's argument values, and
[4] a list of _o_b_j_e_c_t_s the hook was called for.
The command will be called for each hook that is called. This allows
the application to trace hook execution for debugging purposes.
EEXXAAMMPPLLEE
The ::::mmooddeell module calls the <Update> hook in response to commands that
change the model's data:
hook call ::model <Update>
The ..vviieeww megawidget displays the model state, and needs to know about
model updates. Consequently, it subscribes to the ::model's <Update>
hook.
hook bind ::model <Update> .view [list .view ModelUpdate]
When the ::::mmooddeell calls the hook, the ..vviieeww's ModelUpdate subcommand
will be called.
Later the ..vviieeww megawidget is destroyed. In its destructor, it tells
the _h_o_o_k that it no longer exists:
hook forget .view
All bindings involving ..vviieeww are deleted.
CCRREEDDIITTSS
Hook has been designed and implemented by William H. Duquette.
BBUUGGSS,, IIDDEEAASS,, FFEEEEDDBBAACCKK
This document, and the package it describes, will undoubtedly contain
bugs and other problems. Please report such in the category _h_o_o_k of
the _T_c_l_l_i_b _S_F _T_r_a_c_k_e_r_s [http://source-
forge.net/tracker/?group_id=12883]. Please also report any ideas for
enhancements you may have for either package and/or documentation.
SSEEEE AALLSSOO
uevent(n)
KKEEYYWWOORRDDSS
callback, event, hook, observer, producer, publisher, subject, sub-
scriber, uevent
CCAATTEEGGOORRYY
Programming tools
CCOOPPYYRRIIGGHHTT
Copyright (c) 2010, by William H. Duquette
hook 0.1 hook(n)