[Richard Suchenwirth] 2007-05-04 - [MJ] contributed this nice example of how to extend Tcl with a new subcommand to the [chan] ensemble (new from 8.5). First, write a self-contained function that implements what you want - in this case, return a list indicating whether the given channel is readable (r) and/or writable (w): /* *---------------------------------------------------------------------- * * Tcl_ModeObjCmd -- * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ModeObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to puts on. */ const char *channelId; /* Name of channel for puts. */ int mode; /* Mode in which channel is opened. */ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } channelId = Tcl_GetString(objv[1]); chan = Tcl_GetChannel(interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } if ((mode & TCL_READABLE) != 0) { Tcl_AppendElement(interp, "r"); } if ((mode & TCL_WRITABLE) != 0) { Tcl_AppendElement(interp, "w"); } return TCL_OK; } Then, make it available as a command to Tcl: Tcl_CreateObjCommand(interp, "::tcl::chan::mode", Tcl_ModeObjCmd, NULL, NULL); Finally, in [init.tcl], register that new command as ensemble member of [chan]: # Set up the 'chan' ensemble (TIP #208). namespace eval chan { # TIP #219. Added methods: create, postevent. # TIP 287. Added method: pending. namespace ensemble create -command ::chan -map { blocked ::tcl::chan::blocked close ::tcl::chan::close configure ::tcl::chan::configure copy ::tcl::chan::copy create ::tcl::chan::rCreate eof ::tcl::chan::eof event ::tcl::chan::event flush ::tcl::chan::flush gets ::tcl::chan::gets mode {::tcl::chan::mode ;############### here} names {::file channels} pending ::tcl::chan::Pending postevent ::tcl::chan::rPostevent puts ::tcl::chan::puts read ::tcl::chan::read seek ::tcl::chan::seek tell ::tcl::chan::tell truncate ::tcl::chan::Truncate } } ---- [NEM] You shouldn't have to put the command in the tcl namespace or mess with init.tcl. The [namespace ensemble] mechanism is flexible enough to be extended from elsewhere. In this case, you could do: Tcl_CreateObjCommand(interp, "::mychan::mode", Tcl_ModeObjCmd, NULL, NULL); and then in some script do: set map [namespace ensemble configure ::chan -map] dict set map mode ::mychan::mode namespace ensemble configure ::chan -map $map [DKF]: I'd go further and say that what [NEM] suggests is the ''correct'' way to do it, since it does not rely on the current configuration of how [chan] has its internal subcommands. It also allows people to have other extension subcommands. [MJ]: I agree that in the case of extending chan with new subcommands this is the way to go, there is nothing in this piece of code that will prevent the [[chan mode]] command to be loaded in an extension (this extensibility is one of the advantages of ensembles). However, I wanted to add a command in the core itself and was delighted by how easy this was. See [Extending chan] for the right way to do it. ---- [[[Category Example]|[Category Channel]]]