MJ - With the use of namespace ensembles to create newer Tcl core commands (e.g. chan) it's very straightforward to extend core commands with your own functionallity. One way is to change the Tcl core as described in chan mode.
A better way that allows to achieve this is to write an extension adding the functionallity. For instance we can extend the Tcl chan command to have a new subcommand chan mode that returns a list of the mode of a file handle (r for readable, w for writeable) with the small extension below.
To register the new subcommand in the namespace ensemble the ensemble map needs to be updated (as described by NEM at the chan mode page)
examples
% package require chanmode 0.1 % chan mode stderr w % chan mode stdin r % set f [open c:/temp.txt w+] filee1f908 % chan mode $f r w
pkgIndex.tcl
package ifneeded chanmode 0.1 \ [list source [file dirname [info script]]/chanmode.tcl]
chanmode.tcl
load [file dirname [info script]]/chanmode0.1[info sharedlibextension] set map [namespace ensemble configure ::chan -map] dict set map mode ::chanmode::mode namespace ensemble configure ::chan -map $map
chanmode.c
#include <tcl.h> #include <stdio.h> int Chanmode_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; } int DLLEXPORT Chanmode_Init(Tcl_Interp *interp) { if (Tcl_InitStubs(interp, "8.5", 0) == 0L) { return TCL_ERROR; } Tcl_CreateObjCommand(interp, "chanmode::mode", Chanmode_ModeObjCmd, NULL, NULL); Tcl_PkgProvide(interp, "chanmode", "0.1"); return TCL_OK; }