 | Level: Introductory Teodor Zlatanov (tzz@bu.edu), Programmer, Gold Software Systems
29 Sep 2004 Take a look at the Ion windows manager, a powerful and simple program that manages the windows that applications bring up on your desktop. Ion isn't flashy, but once you get used to it, it can greatly enhance your productivity and make you wonder why you ever used those other window managers.
In this column, you'll get a feel for the Ion window manager for the X Window System.
X Window managers are programs that manage the windows that applications bring up. For
instance, if you've ever run an XTerm or a Web browser on an X terminal,
chances are a window manager was running in the background, helping
you control the windows that popped up.
In Microsoft® Windows®, the window manager is very tightly integrated with the
rest of the operating system. It's hard to imagine a Windows machine
without Explorer windows all over the desktop.
In UNIX®, and in Linux™ specifically, the evolution of the desktop has
taken a different course due to a variety of cultural and technological
reasons. UNIX adopted X as its window system of choice, and X Window
managers were typical UNIX utilities: small, fast, and configurable.
Window managers such as twm appealed to minimalists, while the elaborate
machinery of the Enlightenment window manager could show off graphics
as pretty as anything you've seen. (For information on Ion in
MacOS X, see the Resources section.)
Modern UNIX desktops generally have tighter integration between the
window manager and the rest of the desktop machinery (CDE, KDE, and
Gnome all do this) than ever before, but it's still entirely possible
to run with a different window manager than the one your desktop
expects.
This article is intended for users comfortable with switching and
configuring their window manager (commonly abbreviated to WM). If you are
not such a user, beware. Ion is not a gentle WM, and you absolutely need
the ability to dig yourself out if you misconfigure Ion or X in such
a way that one or the other won't start. Consider yourself warned!
Enter Ion
Ion is a tiling window manager. There are others like it (see the
links on the Ion home page listed in the Resources)
but, in my opinion, Ion has the best
balance of speed, features, extensibility, and configurability. Ion
is just 150 kilobytes in size (plus 160 kilobytes in modules as of
version 2, in Debian Linux). It is fast.
 |
The full story
Ion actually can do overlapping windows. I
hope you learn instead to use the tiling windows, but you can fall
back on overlapping-window ("PWM" or "floating") workspaces. They
are called PWM workspaces because Ion's predecessor, PWM, did only
traditional overlapping window management. These workspaces are also
called "floating" because windows appear to float on the screen. The
tiling workspaces are generally called Ion workspaces because they
have always been in Ion, unlike floating workspaces.
|
|
First, a definition. Tiling window managers don't let windows
overlap. This may seem strange to you, until you realize that window
overlap is one of the main things that hide content from the
user. In terms of navigation, tiling window managers are very
efficient because there is no z-plane (depth) to the windows they
manage. Thus, the user need manage only two dimensions.
(see The full story).
One question comes immediately to mind. What happens if there are more
windows than will fit on the workspace, especially if you don't want
to shrink them to be unmanageably tiny? Here, Ion's other great
feature besides tiling comes in: tabs. Tabs are the z-plane of Ion,
except that only one tab can ever be visible. Thus, if a window frame
has tabs A, B, and C, only one of those can be seen. The other tabs
and the windows that belong to them are hidden. Remember this, because it's
essential if you want to use Ion well! Many applications today support
tabs, so you are probably aware of how they work even if you have not used Ion
before.
You can take a look at the Ion home page (see Resources) for screenshots of Ion's tiling behavior
and tabs. The screenshots don't look glamorous because Ion isn't
glamorous -- but it is (incredibly) functional. Its only object is
to get work done, and to that end, bells and whistles like themes are
not used. I used Enlightenment before Ion and I must confess that the
lack of themes made Ion very unappealing at first, but in the end Ion
let me concentrate on what was inside the windows, not their
decorations. I recommend that if you try Ion, give it at least a day.
The first impression is so jarring that you may be turned away from
Ion for the very thing that makes it a good window manager: its simplicity.
One group of users who will find Ion very useful are those who don't
like to use the mouse for any reason. Ion makes every function
available through a keyboard interface, and using the mouse in Ion is
not necessary. Those who want to use the mouse, can; it's just that
doing things with the keyboard is easier and faster once you learn the
keystrokes.
Finally, I should note that there are many X Window managers, and Ion
may not be the one for you. Other window managers
similar to Ion are in the Links section of the Ion
home page. Look carefully into the ones available for your platform,
and choose based on what you like in a window manager. Do try Ion,
though. I think you will be glad you did.
Ion's history
Throughout its history, Ion has been developed by a Finnish hacker
named Tuomo Valkonen. Preceding Ion was the PWM window manager, by
the same author. Tuomo is the sole owner of the Ion project, even
though Ion as a software package is under the Lesser GNU Public
License. Fairly recently, Tuomo put the latest version of Ion in a
Subversion repository; instructions for using that repository to get
the latest Ion version are on the Ion home page.
Ion has three distinct versions as of July 2004. Ion 1 was the
original Ion, written in C. It had a simple configuration format,
similar in spirit to the classic UNIX window managers. Ion 1 had no
floating (overlapping windows) workspaces, and few features.
Nevertheless, Ion 1 was revolutionary in its minimalist,
streamlined, and very functional approach. Ion 1 may not have been
the first to use tiling workspaces (the idea is hardly new), but it
certainly did a good job of it, thanks to tabbing. Tabbing is essential to the success of Ion's tiling approach, and to my
knowledge no window manager before PWM had this feature -- or if they
did, none used it to such an extent as Ion, which tabs even terminal
windows.
Ion 2 was a rewrite of most of Ion. It was still in C, and it cleaned up
the object hierarchy to organize the Ion code better. The big changes
with Ion 2 were the addition of the optional
floating workspaces and the Lua scripting language,
which became to Ion what Lisp is to Emacs -- an essential vehicle for
customization and extension.
Currently under development, Ion 3 is not a major update to Ion 2 in
terms of user-visible features as of now (even though some nifty
features are already being tested: session management support,
mod_autows, a nicer dock, a scratchpad, and so on). See the Ion 3
repository for more information on these features if you are
adventurous.
Ion 3 simplifies many of the features Ion 2 introduced, adds better
modules for extending Ion, and is a minor internal rewrite of Ion
(although from the scripting side, it has changed quite a bit to
reflect lessons learned from Ion 2). Make sure you check the status
of Ion 3 before you decide to use it. Ion 3 is a bleeding-edge
release with little documentation as of this writing.
My Ion configuration
While you can certainly get started with Ion using the default key
bindings, you may find them awkward. Wordstar or vi users may find
the default keystrokes easy, but if you have spare function keys on
your keyboard, you may want to change key bindings from the default.
I will show my personal configuration using Ion 2, which sets up some
alternate key bindings.
Note that you can keep the default key bindings and install
new ones. This is probably the safest option for new users.
I need to explain my key bindings first, before I show them. My
keyboard use is almost entirely Emacs and vi (programming), shell
interaction, and e-mail (using the Emacs gnus mail- and news-reader). I
use all the F keys (F1 through F12 bare or with Control or with Shift)
for Emacs programming. I leave Alt-F1 through Alt-F12 for Ion. The
extra keys on my Logitech, Sun, and Memorex keyboards are used for
launching applications, and I'll explain in a moment
how that works with xmodmap.
The most unusual part of my setup might be the keypad. I use the keypad
only for Ion navigation. I don't need to press any modifier (Control,
Alt, or Shift) keys to use the keypad, the way I have it set up. That
way, when I'm typing on the keyboard, I can access all Ion navigation
by just shifting my right hand to the keypad. This is, in my
experience, a very efficient setup and you should consider trying it.
The keypad is entirely replicated elsewhere on the keyboard so you
don't need it for anything (in 99 percent of cases). The remaining 1 percent
must have the keypad, so they should map my setup to other keys or
maybe to the keypad with the Alt modifier pressed.
If you think you absolutely need the keypad, take a moment and think
about it. What do you use on the keypad? How often do your hands
land on it? How often, on the other hand (no pun intended), do you
move your hand to the mouse to arrange windows on the screen? You'll
probably find that the keypad is not essential to your daily computer
use. As proof, consider laptop computers. If you have used one for a
few days, you probably noticed there is no separate keypad. That does
not bother most users, and they rarely use the common laptop "overlay
keypad."
The Ion 2 configuration is written in a language called Lua. The Ion
home page has links to documentation on using Lua for configuring
Ion (see Resources). The object hierarchy
introduced in Ion 2 is manipulated through
Lua, so you should take a look at the Ion 2 documentation that shows
the object hierarchy if you plan to customize any part of Ion 2 beyond
the simplest changes in key bindings.
My Ion 2 configuration consists of several files. There's ion.lua,
which controls the global Ion 2 options. For Ion tiling workspaces, I
use ionws.lua (which has just keybindings right now). For global key
bindings, I use tzz-ion-bindings.lua. Because I don't use the PWM
(floating) workspaces in Ion, my customization does not include PWM
key bindings. The default PWM bindings that come with Ion 2 should be
sufficient; if you want them to be as simple as the keypad-oriented
bindings for Ion workspaces, you'll need to think about what the keypad
can do in floating workspaces. You'll probably find the mouse
indispensable with floating windows (which is the reason why I don't
like to use them).
You may wonder what I have against mice. They are fine pointing devices,
but their extended use is suspected of being a cause for Carpal Tunnel
Syndrome (CTS) and Repetitive Stress Injuries (RSI), common computer user
afflictions. My experience was that cutting back on mouse usage made my
wrists feel better (I nearly got CTS myself, years ago), but I am not a
doctor, so you should consult one if you are concerned about CTS and RSI.
Most experts recommend using the mouse less when possible, but of course
overuse of the keyboard can be just as bad for your health (especially if
your posture is bad). Chording (striking two or more keys at once) is
particularly bad and should be avoided when possible. My setup, which is
presented here, specifically avoids chording for the most-commonly used
navigation tasks of moving between tabs and frames in Ion.
Using the mouse
less will also improve your productivity if you type a lot, since you
won't have to move your hands between the keyboard and the mouse as much.
Remember, the best thing you can do to ensure healthy, productive use of
the computer is to take frequent 5-minute breaks.
Here is my ion.lua configuration file. Lua is a pretty complicated
language, but you should see right away that "--" indicates the
beginning of a comment.
Listing 1. ion.lua
--
-- Ion main configuration file
--
-- Modules.
load_module("query")
load_module("menu")
load_module("ionws")
load_module("floatws")
load_module("dock")
-- Set default modifier. Alt should usually be mapped to Mod1 on
-- XFree86-based systems. The flying window keys are probably Mod3
-- or Mod4; see the output of 'xmodmap'.
DEFAULT_MOD = "Mod1+"
-- Maximum delay between clicks in milliseconds to be considered a
-- double click.
--set_dblclick_delay(250)
-- For keyboard resize, time (in milliseconds) to wait after latest
-- key press before automatically leaving resize mode (and doing
-- the resize in case of non-opaque move).
--set_resize_delay(1500)
-- Opaque resize?
enable_opaque_resize(true)
-- Movement commands warp the pointer to frames instead of just
-- changing focus. Enabled by default.
enable_warp(true)
-- Kludges to make apps behave better.
include("kludges")
-- Make some bindings.
include("tzz-ion-bindings")
-- Define some menus (menu module required to actually use them)
include("ion-menus")
-- How to shorten window titles when the full title doesn't fit in
-- the available space? The first-defined matching rule that succeeds
-- in making the title short enough is used.
add_shortenrule("(.*) - Mozilla(<[0-9]+>)", "$1$2$|$1$<...$2")
add_shortenrule("(.*) - Mozilla", "$1$|$1$<...")
add_shortenrule("XMMS - (.*)", "$1$|...$>$1")
add_shortenrule("[^:]+: (.*)(<[0-9]+>)", "$1$2$|$1$<...$2")
add_shortenrule("[^:]+: (.*)", "$1$|$1$<...")
add_shortenrule("(.*)(<[0-9]+>)", "$1$2$|$1$<...$2")
add_shortenrule("(.*)", "$1$|$1$<...")
-- List of directories to look for manuals in the F1 man page query.
query_man_ "/usr/man",
"/usr/share/man",
"/usr/X11R6/man",
"/usr/local/man"
}
|
Lua has been around for about ten years, but it isn't widely known
yet. It is unlike any other scripting language I know, and I'm not the
only Ion user that finds it somewhat difficult. I've heard it's very
rewarding once you get used to it.
If you compare the setup in Listing 1 to the default ion.lua that comes with
Ion 2, you won't notice much of a difference. My ion.lua is mainly a
place to load the subsequent Lua files I have customized, and which
we will meet later.
My draw.lua file, which controls the drawing options in Ion 2, is
entirely copied from the default look-clean.lua that comes with Ion,
so it's not worth discussing here. The look-clean.lua file is
well commented so you should look through it if you want to customize
the colors and appearance of Ion. The only change I make in my
draw.lua file is to make the frame title font larger, since I like a
large font everywhere (you should use the largest font you find usable
to give your eyes a break).
The global key bindings live in tzz-ion-bindings.lua. If your
particular keyboard doesn't have the symbols in the same places as
mine, you may need to remap them. For me, the keys assigned to
workspaces 0 through 6, for instance, make a 3/4 circle around the
numbers of the keypad. You can use the xev program to find the name
of a key for remapping.
Remember that DEFAULT_MOD is Mod1, which on normal Linux (and most
UNIX) systems is the Alt key. The Alt key is also known as the Meta
key, but of course in Emacs you can access Meta with the Esc key,
(while in Solaris, the Meta key looks like a diamond and the Alt key
is just Alt). If you could follow the last sentence, you have my
sympathies!
Listing 2. tzz-ion-bindings.lua
-- Load a library to create common queries.
include("querylib")
-- Load a library to create menu display callbacks.
include("menulib")
global_bindings{
-- use the keys *around* the numbers on the keypad to switch
-- to workspaces 0 through 6
kpress("KP_Divide", function(s) s:switch_nth(0) end),
kpress("KP_Multiply", function(s) s:switch_nth(1) end),
kpress("KP_Subtract", function(s) s:switch_nth(2) end),
kpress("KP_Add", function(s) s:switch_nth(3) end),
kpress("KP_Enter", function(s) s:switch_nth(4) end),
kpress("KP_Decimal", function(s) s:switch_nth(5) end),
kpress("KP_0", function(s) s:switch_nth(6) end),
-- convenient Ion control functionality
kpress(DEFAULT_MOD..KEYF11, querylib.query_restart),
kpress(DEFAULT_MOD..KEYF12, querylib.query_exit),
-- sometimes I need to "walk" through workspaces, instead
-- of switching to specific ones
kpress(DEFAULT_MOD.."Shift+Left", WScreen.switch_prev),
kpress(DEFAULT_MOD.."Shift+Right", WScreen.switch_next),
-- these are assigned with xmodmap to keys on my Logitech keyboard
kpress("XF86Mail", make_exec_fn("emacs -name gnus -f gnus")),
kpress("XF86Standby", make_exec_fn("xlock -mode matrix")),
kpress("XF86AudioMute", make_exec_fn("aumix.sh")),
kpress("XF86AudioRaiseVolume", make_exec_fn("/usr/bin/aumix -v+3")),
kpress("XF86AudioLowerVolume", make_exec_fn("/usr/bin/aumix -v-3")),
kpress("Shift+XF86AudioRaiseVolume", make_exec_fn("/usr/bin/aumix -v+1")),
kpress("Shift+XF86AudioLowerVolume", make_exec_fn("/usr/bin/aumix -v-1")),
kpress("XF86AudioPlay", make_exec_fn("xmms --play")),
kpress("XF86AudioStop", make_exec_fn("xmms --pause")),
kpress("XF86AudioPrev", make_exec_fn("xmms --rew")),
kpress("XF86AudioNext", make_exec_fn("xmms --fwd")),
-- I run a lot of terminals, so this is a way to make sure that no
-- matter what X resources are loaded, I get a consistent look to my
-- terminals.
kpress("XF86PowerOff", make_exec_fn("Eterm -f yellow --shade 100
--term-name xterm --double-buffer -L 500000 --font
-misc-fixed-bold-r-normal--14-130-75-75-c-70-iso10646-1")),
kpress("Mod1+XF86PowerOff", make_exec_fn("xterm -bg black
-fg yellow -fn -misc-fixed-bold-r-normal--14-130-75-75-c-70-iso10646-1
-cr blue -geometry 80x50 -name term")),
-- essential programs for me
kpress("XF86Start", make_exec_fn("emacs")),
kpress("XF86Search", make_exec_fn("mozilla")),
-- miscellaneous menus
kpress("Print", make_bigmenu_fn("mainmenu")),
mpress("Button2", make_pmenu_fn("windowlist")),
mpress("Button3", make_pmenu_fn("mainmenu")),
}
mplex_bindings{
kpress_waitrel(DEFAULT_MOD.."Return",
make_mplex_clientwin_fn(WClientWin.toggle_fullscreen)),
-- Alt+W is short and sweet, yet hard to press accidentally
kpress_waitrel(DEFAULT_MOD.."W", WMPlex.close_sub_or_self),
}
genframe_bindings{
-- Tag an object
kpress(DEFAULT_MOD.."Shift+A", WGenFrame.attach_tagged),
-- Tag viewed object
kpress(DEFAULT_MOD.."T", make_mplex_sub_fn(WRegion.toggle_tag)),
-- 6 and 4 on the keypad go back and forth between tabs.
-- this is very essential to my setup. I couldn't use Ion without
-- these key bindings.
kpress("KP_6", WGenFrame.switch_next),
kpress("KP_4", WGenFrame.switch_prev),
-- miscellaneous frame-oriented bindings
kpress(DEFAULT_MOD.."A", querylib.query_attachclient),
kpress(DEFAULT_MOD.."G", querylib.query_gotoclient),
kpress(DEFAULT_MOD.."F3", querylib.query_exec),
kpress(DEFAULT_MOD.."F4", querylib.query_ssh),
kpress(DEFAULT_MOD.."F5", querylib.query_editfile),
kpress(DEFAULT_MOD.."F6", querylib.query_runfile),
kpress(DEFAULT_MOD.."F7", querylib.query_lua),
kpress(DEFAULT_MOD.."F9", querylib.query_workspace),
kpress(DEFAULT_MOD.."M", make_menu_fn("ctxmenu")),
mpress("Button3", make_pmenu_fn("ctxmenu"),"tab"),
}
|
Finally, my Ion tiling workspace bindings. These are also
keypad-oriented, of course.
Listing 3. ionws.lua
ionws_bindings{
-- I seldom have more than 2 vertical splits in an Ion workspace, so
-- I don't need dedicated keys to moving left and right between
-- them. Since 6 and 4 were taken for tab navigation, I use the keypad
-- 5 to go to the next split to the left. I can always go right with
-- Alt+Tab.
kpress("KP_5" WIonWS.goto_left),
kpress(DEFAULT_MOD.."Tab" WIonWS.goto_right),
-- horizontal splits are more frequent for me, so it's convenient to
-- move between them with the up/down (8 and 2) keypad keys.
kpress("KP_Down", WIonWS.goto_below),
kpress("KP_Up", WIonWS.goto_above),
}
ionframe_bindings{
-- these bindings left me make new splits in Ion. They all use
-- the Pause key, because it's not used for anything else.
kpress(DEFAULT_MOD.."Pause", function(frame) frame:split_empty("bottom") end),
kpress("Pause", function(frame) frame:split_empty("right") end),
kpress("Shift+Pause", function(frame) frame:close("right") end),
-- standard Ion functions to use the mouse when necessary
mclick("Button1", WGenFrame.p_switch_tab, "tab"),
mdblclick("Button1", WIonFrame.toggle_shade, "tab"),
mdrag("Button1", WGenFrame.p_tabdrag, "tab"),
mdrag("Button1", WGenFrame.p_resize, "border"),
mclick("Button2", WGenFrame.p_switch_tab, "tab"),
mdrag("Button2", WGenFrame.p_tabdrag, "tab"),
mdrag(DEFAULT_MOD.."Button3", WGenFrame.p_resize),
}
ionframe_moveres_bindings{
-- resizing keys. As much as I use Ion without the mouse,
-- I find it very convenient for resizing as opposed to the keyboard.
-- Your mileage may vary.
kpress("AnyModifier+Escape", WIonFrame.cancel_resize),
kpress("AnyModifier+Return", WIonFrame.end_resize),
kpress("Left", function(f) f:do_resize( 1, 0, 0, 0) end),
kpress("Right",function(f) f:do_resize( 0, 1, 0, 0) end),
kpress("Up", function(f) f:do_resize( 0, 0, 1, 0) end),
kpress("Down", function(f) f:do_resize( 0, 0, 0, 1) end),
kpress("F", function(f) f:do_resize( 1, 0, 0, 0) end),
kpress("B", function(f) f:do_resize( 0, 1, 0, 0) end),
kpress("P", function(f) f:do_resize( 0, 0, 1, 0) end),
kpress("N", function(f) f:do_resize( 0, 0, 0, 1) end),
kpress("Shift+Left", function(f) f:do_resize(-1, 0, 0, 0) end),
kpress("Shift+Right",function(f) f:do_resize( 0,-1, 0, 0) end),
kpress("Shift+Up", function(f) f:do_resize( 0, 0,-1, 0) end),
kpress("Shift+Down", function(f) f:do_resize( 0, 0, 0,-1) end),
kpress("Shift+F", function(f) f:do_resize(-1, 0, 0, 0) end),
kpress("Shift+B", function(f) f:do_resize( 0,-1, 0, 0) end),
kpress("Shift+P", function(f) f:do_resize( 0, 0,-1, 0) end),
kpress("Shift+N", function(f) f:do_resize( 0, 0, 0,-1) end),
}
|
Note that ionws.lua is loaded automatically when you load the ionws module in ion.lua. That's why there's no explicit "require ionws"
in my ion.lua file.
Conclusion
Variety is the spice of life, and I hope you get plenty of spice from
this article. Ion is an unorthodox window manager that will prove
itself if you give it a chance. These days, when I look at Windows and
other floating-window desktop environments, I wonder
how much more efficient all of their users would be without the
distraction of floating windows. This is not to say floating windows are always
bad, only that in most situations they waste time and screen space
when they overlap, and the user needs to move them around.
The Ion home page has many links and explanations of Ion's philosophy
and development. You should visit it for the screenshots too. Just
remember that Ion's beauty is that it's simple and unobtrusive, so
just because you don't see fancy window frames and animated
backgrounds doesn't mean Ion is not working hard to make your
computing environment better.
Resources
- The home page of the Ion window
manager is essential for anyone interested in Ion. The site
includes downloads, documentation, discussion lists, links,
and screen shots of Ion in action.
- See also How to Run the Ion Window Manager on OSX if you're an OSX user.
- X.org is the foundation behind the
X Window System.
- CDE is an
historically important manager, but not used widely anymore. It uses
DTWM by default.
- KDE is one of the premier UNIX
desktop environments today. It uses
KWin by default.
- Gnome is another premier UNIX
desktop environment today. It uses the
Metacity WM
by default.
- Enlightenment is a great
manager when you need all the bells and whistles. Other
impressive-looking window managers include
fvwm and icewm
(this latter one is actually quite compact, in addition to being fancy).
-
In addition to Ion, other lightweight
window managers include
LarsWM, TrsWM, and Ratpoison. The last of these,
Ratpoison, is based on
GNU
screen,
and also lets you do away with mice. See also this
discussion of GNU screen,
Ratpoison, and other minimal window managers.
- Ion uses the 10-plus year old Lua configuration and scripting language.
There are many places to learn more about Lua: the book Programming in
Lua (Ingram/Bertram Books, 2003) is available online; there is an
active lua-users mailing list; and the
lua-users wiki has links to tutorials and
an unofficial FAQ.
-
The classic resource on key remapping is
Jamie Zawinksi's
XKey Caps page; see also the xmodmap help
page from MIT.
- Read all of Ted's Perl articles in the "Cultured Perl" series on developerWorks.
- For an overview of XFree86 and a tutorial on getting it up and running, read Introduction to XFree86 4.x (developerWorks, October 2001).
- Ted talks more about the Enlightenment window manager as part of an optimized Perl developer's environment in Cultured Perl: A programmer's Linux-oriented setup (developerWorks, March 2001).
- Find more resources for Linux developers in the developerWorks Linux
zone.
- Browse for books on these and other technical topics.
- Download no-charge trial versions of IBM products that run on Linux, including WebSphere® Studio Site Developer, WebSphere SDK for Web services, WebSphere Application Server,
DB2® Universal Database Personal Developers Edition, Tivoli® Access Manager,
and Lotus® Domino Server, from the Speed-start
your Linux app section of developerWorks. For an even speedier start,
help yourself to a product-by-product collection of how-to articles and
tech support.
About the author  | 
|  | Teodor Zlatanov graduated with an M.S. in computer engineering
from Boston University in 1999. He has worked as a programmer since
1992, using Perl, Java, C, and C++. His interests are in open source
work, Perl, text parsing, 3-tier client-server database
architectures, and UNIX system administration. Suggestions and
corrections are welcome over e-mail; you can contact him at tzz@bu.edu. |
Rate this page
|  |