Level: Intermediate William B. Zimmerly (bill@zimmerly.com), Freelance Writer and Knowledge Engineer, Author
06 Jun 2006 Most graphical user interface (GUI) desktops provide you with a good set of configuration options. Script your way to a set of GUI widgets that go beyond what the desktop normally does. Most computer users interact with their workstations primarily through some form
of graphical user interface (GUI). In the world of Microsoft® Windows®, this interface is tightly
controlled. The UNIX® world, by contrast, offers a veritable smorgasbord of different GUIs
with varying degrees of functionality. The GUIs are commonly known as window managers, because they
occupy a layer above the nitty-gritty X-Windows layer and they manage windows for you.
UNIX has always been about freedom and the right to choose how you want your system to work.
Different personality types require different things, and the UNIX GUIs have something for
everyone. They range from minimalist window managers, such as twm, to large, capable tools, such as
GNOME and KDE (K Desktop Environment). In between are dozens of others offering various flavors and functions. (To view a current list of some of the most common window managers, see the Resources section.)
You might want some form of scripted control over your desktop that lets you program in functionality without spending an inordinate amount of time learning how to do it. Or, you might prefer a programmable window manager, so you can control its behavior as much as you control the command-line interface. A successful option to meet both needs is a minimalist window manager that runs on top of a powerful window manager, allowing you just enough flexibility to script with ease.
Tcl/Tk to the rescue
Originating with Dr. John Ousterhout of the University of California, Berkeley, and later of Sun Microsystems and Scriptics, the Tool Command Language and Tk GUI toolkit (Tcl/Tk) scripting language offers a simple and elegant way to code GUI widgets with minimal effort.
Programming a computer to do something always involves at least two important issues: how it will look and how it will work. The Tcl/Tk programming language strives to makes it as painless as possible to deal with the how will it look issue; it lets you easily script GUI widgets, such as windows and buttons, and attach them to procedures (the how will it work issue).
What to do?
A clean, uncluttered desktop is good in both the virtual and real worlds. Uncluttered means having just a few icons that do a lot of work to prepare the desktop. (Sometimes these are known as coffee icons -- you click them and then go get a cup of coffee while they start up a set of programs that you need to work with.) It's good to group the execution of several programs directed toward a single task into the actions of just one icon.
For example, to write an article like this one, you can script a single icon that, when clicked, opens an xterm to play with, a text editor in which to edit XML files, and a browser that displays the article. With one click of an icon, all these tools are launched, configured the way you need them, with the correct screen geometry, the working directory set, and all files opened and ready to be worked on. That's scripting!
You can accomplish the same result with a good bash shell script and attach the script to a desktop icon, but Tcl/Tk offers a significantly better interface to the GUI aspects.
Writer's assistant
Listing 1 shows a Tcl/Tk program that accomplishes all the tasks described in the previous section with a click of an icon. In addition to starting up the xterm, editor, and browser, it provides a button you can click at any time to convert the article from XML to HTML by running a script provided by IBM.
Listing 1. The writer's assistant
#!/usr/bin/wish -f
# 1 -- How should it look?
set PageTitle "IBM developerWorks Articles -- Studio B"
set InitDir "/home/bill/StudioB/developerworks"
set ChooseDir "Choose an Article Directory"
frame .rc -borderwidth 2
wm title . $PageTitle
wm resizable . 0 0
button .rc.b -width 20 -text "Rebuild Article" -command {rebuild-article}
button .rc.c -width 20 -text "Exit" -command {exit}
pack .rc
pack .rc.b
pack .rc.c
grid .rc.b .rc.c -sticky ew
# 2 -- What should it do?
proc rebuild-article {} {
exec ./dw-transform.sh &
}
wm geometry . =336x32+0+707
set dir ""
while {$dir == ""} {
set dir [tk_chooseDirectory \
-initialdir $InitDir \
-title $ChooseDir]
}
cd $dir
exec nedit -geometry 150x48+0+0 index.xml &
exec konsole &
exec opera -geometry 1024x680+0+0 index.html &
|
You can screen-scrape the code by holding down the left button of the mouse and scraping all of it. Then, start your favorite editor and paste the text into it by clicking the middle mouse button. Save the file as article.tcl and make it executable with the chmod command:
Because window managers can differ, as can hardware (you might not even have a mouse with a middle button), these instructions are not as hard and fast as you might need. In that case, contact someone to help you.
The next section considers the parts of the program.
The variables
The first portion of the code uses the traditional UNIX pound-bang string (#!) to run the Tcl/Tk interpreter known as wish. The -f switch tells wish to run the script and then exit.
After this, a comment, denoted by #, begins the How should it look? block of code; this part is followed by the setting of string variables. It's always a good programming practice to group literals like this, high above the code:
#!/usr/bin/wish -f
# 1 -- How should it look?
set PageTitle "IBM developerWorks Articles -- Studio B"
set InitDir "/home/bill/StudioB/developerworks"
set ChooseDir "Choose an Article Directory"
|
The Tk GUI code
This tiny block of code creates a window with two buttons side-by-side. For brevity, it's hard to beat Tk when defining windows and widgets:
frame .rc -borderwidth 2
wm title . $PageTitle
wm resizable . 0 0
button .rc.b -width 20 -text "Rebuild Article" -command {rebuild-article}
button .rc.c -width 20 -text "Exit" -command {exit}
pack .rc
pack .rc.b
pack .rc.c
grid .rc.b .rc.c -sticky ew
|
The frame command creates a window called .rc with a borderwidth of two pixels. The wm command tells the underlying window manager to name the topmost window (. is always topmost) with the page title, and the next wm command prevents the user from resizing it. The two buttons are then defined and packed into the grid horizontally.
The button code
IBM provides a program to convert articles (written in XML) to Web pages (HTML) that have the look of the developerWorks site. The rebuild-article procedure invokes that script when you click the button of the same name. When the script finishes, it displays a dialog describing
how it did in converting the XML to HTML, along with error messages (if any). If the program says that an index.html file was created, then you can click OK, give your browser the focus, and refresh the page to see the new document:
proc rebuild-article {} {
exec ./dw-transform.sh &
}
|
The startup code
In the startup code, wm geometry . =336x32+0+707 puts the desktop extension window at the bottom of a 1024 x 768 desktop. Then, the code opens a dialog that lets you choose which article you want to work on. Finally, it makes the article's directory into the current working directory and starts up the editor (nedit), xterm (konsole), and browser (Opera). All of them are configured properly for work to begin immediately:
wm geometry . =336x32+0+707
set dir ""
while {$dir == ""} {
set dir [tk_chooseDirectory \
-initialdir $InitDir \
-title $ChooseDir]
}
cd $dir
exec nedit -geometry 150x48+0+0 index.xml &
exec konsole &
exec opera -geometry 1024x680+0+0 index.html &
|
This Tcl/Tk program can be improved in many ways. Adding a button to create new articles or a button to back up all the articles to an archive would be worthy improvements, and Tcl/Tk makes it easy for you to do these things. You can also set up your preferred editor, xterm, and browser. Feel free to experiment with the look, and by all means don't limit this desktop extension to writing articles for IBM: Modify it to start up a programming environment or a Web-mastering environment.
A 50-line scientific calculator
Now you'll Tcl your desktop with a more complex GUI program: a scientific calculator written in a mere 50 lines of code (see Listing 2). The calculator evaluates expressions typed in from either the keyboard or the GUI buttons. If you enter an invalid expression, the text turns red. Just as with the program in Listing 1, you can screen-scrape this code into a file, save it as calc.tcl, chmod it as executable, and then run it.
Listing 2. The 50-line calculator
#!/usr/bin/wish -f
# 1 -- How should it look?
set cflag 0; set nextkey 0
wm title . "50-Line Calculator"
wm resizable . 0 0
grid [entry .display -textvariable expression -justify right] -columnspan 6
focus .display
bind .display <Return> equals; bind .display <KP_Enter> equals
foreach row {
{7 8 9 + - sin(}
{4 5 6 * / cos(}
{1 2 3 ( ) tan(}
{C 0 . = Pi log(}
} {
foreach key $row {
switch -- $key {
C {set string {set cflag 1; set expression ""}}
Pi {set string pi}
= {set string equals}
default {set string "press $key"}
}
lappend keys [button .[incr nextkey] -text $key -command $string]
}
eval grid $keys -sticky we
set keys [list]
}
# 2 -- What should it do?
proc press {key} {
if $::cflag {
set ::expression ""
if ![regexp {[0-9().]} $key] {set ::expression $::results}
.display configure -fg black
.display icursor end; set ::cflag 0
}
.display insert end $key
}
proc pi {} {
if $::cflag {set ::expression ""}
lappend ::expression "3.14159265"
.display icursor end; set ::cflag 0
}
proc equals {} {
regsub {=.+} $::expression "" ::expression
if [catch {lappend ::expression = \
[set ::results [expr \
[string map {/ *1.0/} $::expression]]]}] {
.display configure -fg red
}
.display xview end; set ::cflag 1
}
|
This code cheats a little by doubling a few of the shorter lines, but you can see that Tcl/Tk is a remarkably terse language. Not many programming
languages enable you to create such a complex GUI program in so few lines of code.
The main window
Besides the usual pound-bang code to run the interpreter, you set a few variables: cflag, which controls how the main data entry widget .display accumulates characters; and nextkey, which is an index used while you build the array of keys. Then, just as in the previous program, you set the window title text and prevent it from being resized.
After this, you define the widget that is the calculator's display.Several things to note here: The text is always right-justified -- as in most calculator displays, the keys accumulate at the right side of the control and scroll to the left. The focus verb puts the focus in the display so you can use the keyboard as well as the GUI buttons to enter an expression. Then, you bind the code that you want to run when either the Enter key or the keypad Enter key is pressed, and the display is complete:
#!/usr/bin/wish -f
# 1 -- How should it look?
set cflag 0; set nextkey 0
wm title . "50-Line Calculator"
wm resizable . 0 0
grid [entry .display -textvariable expression -justify right] -columnspan 6
focus .display
bind .display <Return> equals; bind .display <KP_Enter> equals
|
The calculator keypad
This code dynamically builds the keypad keys of the calculator -- defining each button with the text it puts into the display -- or, in the case of the C, Pi, and = keys, a special procedure to execute when the key is pressed. Not many programming languages enable you to define such a complex GUI with so many widgets in so few lines of code as Tcl/Tk:
foreach row {
{7 8 9 + - sin(}
{4 5 6 * / cos(}
{1 2 3 ( ) tan(}
{C 0 . = Pi log(}
} {
foreach key $row {
switch -- $key {
C {set string {set cflag 1; set expression ""}}
Pi {set string pi}
= {set string equals}
default {set string "press $key"}
}
lappend keys [button .[incr nextkey] -text $key -command $string]
}
eval grid $keys -sticky we
set keys [list]
}
|
The calculator functionality
With just three procedures, you now define all the calculator functionality you need. Keep in mind that while this program runs, the action is focused in the contents of the display widget. The expr function evaluates these contents when you press the = key or the Enter key.
The press procedure kicks in when most of the GUI buttons are pressed. Its purpose is to append the contents of the button's name text to the display and to the expression string, where the expression will be evaluated later. The cflag, when set, clears the expression, preparing for the next expression to be entered and evaluated:
# 2 -- What should it do?
proc press {key} {
if $::cflag {
set ::expression ""
if ![regexp {[0-9().]} $key] {set ::expression $::results}
.display configure -fg black
.display icursor end; set ::cflag 0
}
.display insert end $key
}
|
The pi procedure inserts the value of pi into the display and expression variable:
proc pi {} {
if $::cflag {set ::expression ""}
lappend ::expression "3.14159265"
.display icursor end; set ::cflag 0
}
|
The equals procedure executes when the = key or one of the Enter keys is pressed. By using Tcl/Tk's powerful expr verb and the library of math code it can evaluate, the expression is solved and the results are placed in, well, the results variable. If an input error occurs, such as a mismatched set of parentheses, the catch code is thrown the error
by expr and changes the color of the display to red:
proc equals {} {
regsub {=.+} $::expression "" ::expression
if [catch {lappend ::expression = \
[set ::results [expr \
[string map {/ *1.0/} $::expression]]]}] {
.display configure -fg red
}
.display xview end; set ::cflag 1
}
|
The documentation for the expr verb indicates that it can handle many other mathematical functions, such as asin, acos, atan, exponentials, floors, and so on. You can use the keyboard to type these in and see expr work; and you should have enough knowledge now to modify the calculator code to add buttons that support these functions. To learn more, visit the Tcl/Tk keywords list in the Resources section.
Pure Tcl desktops
Many people are so enamored of the power of GUI scripting with Tcl/Tk that they have written editors, browsers, and file and desktop window managers in pure Tcl/Tk. A partial list is included in the Resources section.
Conclusion
Every good invention that defines life in the modern world came about because someone was dissatisfied with the status quo and determined to change it in a positive way. You can improve the world through technology -- and having fun with scripting a new desktop for your workstation might open a door to other ideas with a more profound effect. Happy scripting!
Resources Learn
- AIX and UNIX articles: Check out other articles written by William Zimmerly.
-
Window Managers for X: Visit to learn more about the variety of window managers available for UNIX and Linux®.
-
"Server clinic: Expect exceeds
expectations" (developerWorks, April 2002): Learn more about a proper superset of the Tcl/Tk programming language.
-
Tcler's Wiki: Discover Tcl/Tk and see the writings of some of the Tcl/Tk world's best and brightest.
-
Tcl/Tk keywords: The list of keywords on Tcler's Wiki provides more information about specific Tcl/Tk commands and functions. Especially visit the E section and the read about the
expr verb to see more of what this code can do.
-
The Script Archive: Explore this site to learn more about the history and future of Tcl/Tk from the company founded by the original author (Dr. John Ousterhout). (Note: as of the writing of
this article, the Web site was undergoing reconstruction.)
-
Linux.com's HOWTO on Tcl and Tk: Read this informative document and learn more about Tcl/Tk on Linux.
- AIX and UNIX: Want more? The developerWorks AIX and UNIX zone hosts hundreds of informative articles and introductory, intermediate, and advanced tutorials.
-
Stay current with
developerWorks
technical events and webcasts.
Get products and technologies
-
Build your next development project with
IBM
trial software, available for download directly from developerWorks.
Discuss
About the author  | 
|  | Bill Zimmerly is a knowledge engineer, a low-level systems programmer with expertise
in various versions of UNIX and Microsoft® Windows®, and a free thinker who worships at
the altar of Logic. Bill is also known as an unreasonable person. Unreasonable as in, "Reasonable
people adapt themselves to the world. Unreasonable people attempt to adapt the world to themselves.
All progress, therefore, depends on unreasonable people" (George Bernard Shaw). Creating
new technologies and writing about them are his passions. He resides in rural Hillsboro,
Missouri, where the air is fresh, the views are inspiring, and good wineries are all around.
There's nothing quite like writing an article on UNIX shell scripting while sipping on a crystal-clear
glass of Stone Hill Blush. You can contact him at bill@zimmerly.com. |
Rate this page
|