Interactive features in Tcl9 discussion

Discussion of wish #87 from Tcl 9.0 WishList follows.

87 Provide better interactive support with consistent error reporting + a few more built-ins like parray + console on unix

ET: When I try to show off tcl and tk, I often use the console window (on ms windows esp.) and I like to show how one can write code interactively without needing a manual. Most commands will provide one with a usage help as an error, like this:

 % button 
 wrong # args: should be "button pathName ?options?"

Or even better,

 %info
 wrong # args: should be "info option ?arg arg ...?"

and then to see the options:

 % info xxx
 bad option "xxx": must be args, body, cmdcount, commands, complete, default, exists, functions, globals, hostname, level, library, loaded, 
 locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars

But there are some commands which don't provide this help beyond telling you what's wrong.

 array
 wrong # args: should be "array option arrayName ?arg ...?"
 % array xxx
 wrong # args: should be "array option arrayName ?arg ...?"

Now, array should know what options are permitted here, and it would be nice if it told you like it did with info. - RS: In fact, array knows, and tells, once it's called with the required minimum number of arguments:

 % array xxx yyy
 bad option "xxx": must be anymore, donesearch, exists, get, names, nextelement, set, size, startsearch, statistics, or unset

Seems to me that the console show command could be implemented easily on unix, and if not, well, maybe it could run tkcon.


And for interactive use, how about something akin to parray, for displaying in an easy to read format items you get from doing a configure on a widget with no args:

 %button .b
 .b
 % .b configure
 {-activebackground activeBackground Foreground SystemButtonFace SystemButtonFace} {-activeforeground activeForeground Background SystemButtonText
 SystemButtonText} {-anchor anchor Anchor center center} {-background background Background SystemButtonFace SystemButtonFace} {-bd -borderwidth} 
 {-bg -background} {-bitmap bitmap Bitmap {} {}} {-borderwidth borderWidth BorderWidth 2 2} {-command command Command {} {}} {-compound compound  
 Compound none none} {-cursor cursor Cursor {} {}} {-default default Default disabled disabled} {-disabledforeground disabledForeground 
 DisabledForeground SystemDisabledText SystemDisabledText} {-fg -foreground} {-font font Font {{MS Sans Serif} 8} {{MS Sans Serif} 8}} {-foreground 
 foreground Foreground SystemButtonText SystemButtonText} {-height height Height 0 0} {-highlightbackground highlightBackground HighlightBackground 
 SystemButtonFace SystemButtonFace} {-highlightcolor highlightColor HighlightColor SystemWindowFrame SystemWindowFrame} {-highlightthickness 
 highlightThickness HighlightThickness 1 1} {-image image Image {} {}} {-justify justify Justify center center} {-overrelief overRelief OverRelief 
 {} {}} {-padx padX Pad 1 1} {-pady padY Pad 1 1} {-relief relief Relief raised raised} {-repeatdelay repeatDelay RepeatDelay 0 0} {-repeatinterval 
 repeatInterval RepeatInterval 0 0} {-state state State normal normal} {-takefocus takeFocus TakeFocus {} {}} {-text text Text {} {}} {-
 textvariable textVariable Variable {} {}} {-underline underline Underline -1 -1} {-width width Width 0 0} {-wraplength wrapLength WrapLength 0 0}

That may be useful for a program to parse all the information, but Wouldn't it be nice if one could say, do this:

 %.b configure ?
 -activebackground      {}
 -activeforeground      {}
   .
   .
   .
 -padx                   1
 -pady                   1
   .
 -width                  0

with automatic spacing like parray does. The ? would be something compatible, or maybe -show or some other option word. Might also be nice to optionally show only options that are different from the defaults, so one could see what they've changed (-show all, -show changed etc.)

As an alternative, one might provide a package of smallish debug-like commands. These would only be enabled if one did say,

 package require debug ;# if debug is used, then... well anything short would be fine

 la array
 lc .path
 ll list
 lp procname

Where la, would be short for parray, lc might do the above dumping of a configure list, ll would dump a list like (-opt1 val1 -opt2 val2 ...) on multiple lines in a easy to read format, lp would dump a proc with args. The idea here is to make them very short commands. Even if these are likely to be used in real programs, one would normally only use these with a fresh new start of wish. Maybe there could be a way to make the commands all unique as the to letter they begin with. But it would be a pain to have to add namespace info, like d::la etc. Maybe even then, one could have a command d::make_commands_short z which would then define all the commands to be za, zc, zl, zp etc.

Of course, one could just write this package, but the idea here is to make it available in all tcl/tk interpreters so one could just fire up wish and be able to demonstrate the ease of programming in tcl/tk.

Lars H: Most of that wish isn't something that needs to wait for Tcl 9, so why don't you just file feature requests for them? Adding a pdict sibling of parray is something that can be done on the script level (you do know parray is just an auto_loaded proc, I hope?), and the same seems to go for the "debug" package, so why don't you just implement them? The array error message probably qualifies as a (very minor) bug, so that should be filed as well.

ET: I didn't want to do another TIP before having a discussion, and as this is, after all, a wish list, the above is my wish :).

Here's an analogy to better explain my desire: The package process is very powerful. But there is a lot of work on starkits and starpaks. There's even a move to create a sort of universal mega-starkit so the burden of package installation is eliminated. The motto is install=cp, uninstall=rm. So, whle it's quite easy to implement something like a pdict, it's not very useful unless you have it installed. And one can't demo something that's not installed.

I find I have about a 2-minute window of opportunity to make my case for TCL after the familiar "Why are you using this obsolete unsupported language" question comes up. I fire up a wish session and type in

 pack [button .b -text hello -command {puts hello-world}] -fill both -expand yes

I then click the button, resize the window (to show the power of pack), and hit up arrow and change the .b to .c to show them it wasn't a fluke.

Next I show them this command:

 .b conf

and I internally grimace as I hope they don't get the wrong impression. Just imagine if this command produced a smartly formatted output.

Quickly moving on, I show them how to change the color of one of the buttons and go through all the nice options that can be changed so easily.

Most books on TCL begin by showing the interactive capability of the language. But what hit me from the beginning was the lack of a simple built in help command. When I type 'help' I get M.S Dos command help. I know why that occurs, but I wish (and that's what this entry is about) there were some more interactive stuff at the tip of my fingers. Sometimes in the field, I'm not even allowed in the room with a thumb-drive (security reasons) let alone being able to sftp my little debugging aids from my home computer.

And where's the downside of having such a package built in to the core language. I have written a collection of just these such utilities. They are simple to write, but take more than the few seconds I have to explain "why TcL?". This wish is primarily about selling the elegance of TCL and especially its cousin TK.

My goal is to be able to do this next time I get the TCL challenge:

 % set item(name) "My name" ; set item(address) "my address"
 my address

 % parray item
 item(address) = my address
 item(name)    = My name

 % lpr parray
 ---------------------
 proc parray {a {pattern *}} {
    upvar 1 $a array
    if {![array exists array]} {
        error "\"$a\" isn't an array"
    }
    set maxl 0
    foreach name [lsort [array names array $pattern]] {
        if {[string length $name] > $maxl} {
            set maxl [string length $name]
        }
    }
    set maxl [expr {$maxl + [string length $a] + 2}]
    foreach name [lsort [array names array $pattern]] {
        set nameString [format %s(%s) $a $name]
        puts stdout [format "%-*s = %s" $maxl $nameString $array($name)]
    }
 }

And then zing em with this one:

 % lpr lpr
 ---------------------
 proc lpr {{namepat *}} {
 foreach proc [info procs $namepat] {
                set space ""
                puts -nonewline "---------------------\nproc $proc {"
                foreach arg [info args $proc] {
                        if [info default $proc $arg value] {
                                puts -nonewline "$space{$arg $value}"
                        } else {
                                puts -nonewline $space$arg
                        }
                        set space " "
                }
                puts -nonewline "} {"
                puts -nonewline  [info body $proc]
                puts "}"
        }
 }

Lars H: Reiterating my primary point, you certainly won't be able to do that the next time you're given "the Tcl challenge" if you insist on targetting Tcl 9 with your wishes, as that is years away. Filing RFEs (not TIPs) on Sourceforge is the best way to make anything happen anytime soon.

RS: See also corp - it however returns the proc definition string, instead of puts. In an interactive console, the effect is equivalent. In general, I enjoy the freedom I have myself to add fancy utilities to Tcl, since 7.4. The present 9.0 wishlist should be for things that aren't possible with 8.x :-)

NEM 2 August 2006: Also note that this interactive demo (and much more!) is possible right now with tkcon. lpr is called "dump" there, and can handle more than just procs. If I was demoing Tcl's interactive capabilities, tkcon is what I would use.

NEM: Configure option lists can be made much more readable, I find, with a simple:

 % join [.b configure] \n
 -activebackground activeBackground Foreground systemButtonText systemButtonText
 -activeforeground activeForeground Background systemButtonFace systemButtonFace
 -anchor anchor Anchor center center
 -background background Background White White
 -bd -borderwidth
 ...

On a different note: this page is getting far too long to edit. DGP requested that Tcl 9 wishes become sourceforge RFE tracker items. I think that is probably a better way to go than this single giant wiki page.

Lars H: A problem with the sourceforge RFEs is that they're a pain to browse through. The initial comment comes first, but then you have to scroll to the bottom to read the first reply, as the replies are "newest first", and when you've read one reply you have to scroll an unpredictable distance back up before you can begin to read the next. It's horribly reader-unfriendly.

ET: I would have no problem with moving this wish to another page, but I think my goal has been met. Looking at some of the initials of those who've seen this tells me that I got my wish to a good audience.

Of the various ways to get a discussion going, this seems to me to be the most flexible. If I post on the news group, I can't edit it. TIPs are painful to create and go through a editorial process. And the beauty of this format is anyone can move this discussion to a new page. I agree that this page is too long. In my first viewing, I missed the proviso on the first line as I was scanning to see what was here. I saw quite a few things that didn't seem impossible to do in 8.x so I didn't see where this wish was off topic until I went back to read the first line again.

Thanks NEM, that's a neat trick I will use.

Maybe a good place for moving this wish is to page An Interactive Approach to Experimenting with Tcl. And now with this discussion, I could probably be much more consise.