Version 35 of Is tclsh or wish suitable as a login shell

Updated 2010-01-03 15:40:25 by slebetman

Purpose: discuss the pros and cons of using tclsh, wish, or some derivation as one's primary shell command processor for an operating system.

Note that tclsh/wish were never designed to be an interactive login shell. So the short-comings below are not intended as a criticism of tcl as a language, per se. Instead, what is hoped to evolve here are a series of user interface issues one might consider addressing in a sibling interpreter intended to be an interactive login shell with Tcl as the programming language, rather than with the various existing shell languages.

A common complaint from users is that tclsh has no input history, and they typically request that someone add a readline or other interface to the shell.

The typical comp.lang.tcl response is to suggest the user use tkcon .

However, use of tclsh/wish or even tkcon as a login shell is likely to have more issues than command history.

LV, for instance, finds that his daily use of ksh/sh involves a lot of piping output chains of 2, 3, sometimes a dozen commands, with shell constructs as well. Trying to convert these into an easy to use notation in tcl has been a daunting task to date.

Lars H: It could be argued that this is because Tcl mostly employs an algebraic style - f(g(x,y),h(z,w)) - of operation composition using command substitution. Unix shells support this too, via backquotes, but rather poorly. Instead they are very good at forming pipes, which is more a (function composition) way of working - more akin to the native mode of operation in forth or perhaps APL than Tcl or C - although the shell pipes are even coalgebraic.

In the exec page, another issue that recently arose was that of tcl's treatment of normal shell globing characters as literals by default. Thus, in Tcl when a new user says

  set a [exec /bin/ls *.txt]

they typically are surprised to find they didn't get what they expected as a result - tcl didn't expand the argument "*.txt" before invoking /bin/ls, and exec didn't pass the arguments through a shell to do the expansion.

What other issues exist? For instance, does tclsh and family support suspending commands and placing them into the background?

(SS: note about the above example involving ls, what would it take to allow something like:

 set a [ls *.txt]

that is: for tclsh to search for commands in PATH not only in interactive mode, but at any level, if there isn't a TCL command with that name.)


With regards to piping :

Arjen Markus Well, some experimentation:

In tclsh/wish on UNIX:

  • "ls |more" causes execution of "ls" with a file "|more"
  • "ls | more" causes execution of "ls" and produces one page only
  • "ls -l | more" ditto, but it failed with a pipe error (no readers)
  • "vi aa" did work without a fuss

In tkcon on UNIX (typing into the command window!):

  • "ls" is a Tcl command, so I did not inspect this
  • "vi aa" caused the script to hang

(I did not try Windows, but I suspect that there will be very similar problems, augmented with the fact that some commands are internal to the DOS interpreter and do not exist outside it. I do not know Mac, but this does not allow exec at all, at least before OS X)

In general, these are my conjectures:

  • Programs that require no interaction work splendidly, as long as wild cards are taken care of, either via the UNIX shell, or by the programs themselves (under Windows).
  • Programs that simply read a line of input, your basic C or Fortran program reading from stdin, will work when you use the open command to set up the communication properly.
  • Programs that require access to the keyboard, like "more", will require more sophisticated tricks, I would suggest using expect's capabilities.
  • Programs like vi will require a terminal of their own and will never work from a command window.

Now, a sturdy and determined programmer can of course find ways to bypass many of these difficulties via unknown or the alias mechanism:

   ls *.txt --> exec /usr/bin/sh -c {ls *.txt}

   set myfile "todo_today.txt"
   vi $myfile --> exec xterm -e vi todo_today.txt

and so on.

This will require a lot of work though and is it worth it? You could distinguish categories of commands (and programs), so not every command would need its own Tcl interfacing.

Perhaps a general proc, called | for syntactical sugar, can take care of the pipe mechanism (exec and open are the basic commands that will play a role in it). Another one is incrfilter, as LV suggested on the Tcl chat.

LV Actually, incrfilter is just a prototype for a replacement of more. It provides the ability to display subsets of data based on constant strings. I didn't mean for incrfilter to cross over into this discussion - just was mentioning to arjen a toy to play with instead of using more.

I think the above shows me that there is a LOT of work that is needed before someone could comfortably replace use of ksh/sh/bash/etc. with a tcl based shell.

Note however that dtksh has the ability to invoke Tcl functions. A hybrid solution is easiest.


Arjen Markus Some of the limitations of exec with respect to handling pipelines may have been solved by RS - see his page on Streams - RS disclaims: That page offers nice sugar which looks like OS pipes, but in fact are only nesting relations between procedures (cat, grep and more were just few-liner Tcl substitutes..)


SS: some random point about this subject:

I don't think that to use directly tclsh as login shell is worth the effort; I like the idea to exploit the fact that TCL is AFAIK the only language available that can be used to create a shell that mimics the model of the unix shell we have today, but with a real language built-in. My point is, most people don't like the shell as programming language, but most like the basic functionalities it provides, and expecially how this functionalities are provided:

  • the syntax for commands is just <command> <arg1> <arg2> and so on; there is no shorter notation than this.
  • commands can be used in pipe in a simple way; that is: |
  • it supports file redirection in a simple way; that is: > < and so on
  • shell globbing features

I think this is what is worth to take from the past. The first point fits in TCL like in no other language, actually TCL and the shell are using the same syntax for commands. The pipe is a problem... it breaks the harmony between TCL and today's login shell, but I think it is unsane to use a more complex syntax for this. I want to write

 ls | less

and type very little :), so in the command line, | can be considered as syntaxical sugar that expands to something more complex in TCL to get the functionality of pipe. The same is true for > and <. Of course the prompt will not be 100% TCL compatible, but there is something to pay to integrate a language with a human interface in such a direct way.

Shell globbing seems like to be more tricky, a solution can be to just handle it like the shell does... breaking more with TCL.

BTW, at the end your command line is quite TCLish if you write TCL, but at the same time you can use it almost like an old shell. Probably some kind of quoting should allow to pass TCL code where |, >, * and so on have no special meanings, so to get 100% TCL one can start a line with a ' character (just an example), and what follows is taken as it is.

Probably it is much more simple to get all this starting from BASH, putting TCL inside, then starting from tclsh. Using a good shell as starting point it is possible to reuse all the job controls code, history, completion, ... As usually the problem is to find the spare time to try it.


Take a look at http://wiki.tcl.tk/tksh* , where some work was done linking tcl and ksh. Alas, the author has ceased work on the effort - it had some nice potential.


From the chatroom:

GPS Tcl shell:

  • add signal handling to prevent Ctrl-c from closing the shell (TclX or custom extension)
  • implement a frontend to open | for piping/plumbing (investigate Plan9's plumbing system)
  • write procs for controlling the terminal
  • write procs for processing input and/or dealing with readline
  • implement a read-eval-print loop that handles errors properly with catch
  • job control

GPS: Oct 13, 2003 - I wrote part of an interactive shell some years ago and have since found some vital documentation and simple example code that may help anyone interested in building a login shell that uses Tcl.

VT100 manuals here: http://vt100.net/ Simple example unix shells (ladsh): http://people.redhat.com/johnsonm/lad/src/index.html


CGM See gush for an attempt to build a usable Unix shell / "dumb" terminal on top of Tcl.


ZB And I'm wondering, could it be possible to have such shell equipped with screen-oriented editor, instead of usual command line. I think that everyone, who had Commodore 64 (or similar 8-bit machine) knows, what I mean: a quarter of century ago shells were more comfortable, than these of today.


ZB 2010-01-03 Recently discovered, that Fish shell is a little bit "ticklish"; for example, to have a file containing a list of files in current (sub)dir, one should type in its scripting language:

 for i in (ls -S); echo $i; end

It's even aware about events:

 function event_test --on-event test_event
    echo event test!!!
 end
 emit test_event

Its homepage: http://fishshell.org/


slebetman: Check out Pure-tcl readline and Pure-tcl readline2 for a really nice and usable tcl shell, at least on Unix-like systems with VT100 compatible terminals.

ZB If I properly understood, it's about shell's usability as day-to-day login shell - not just about the interaction with user. IMHO tclsh isn't too great as login shell, being rather programming environment - while Fish (bash, zsh, ksh etc.) is exactly the opposite. BTW: I was using readline quite a few months, but it had some issues, which rlwrap is free of.

slebetman: That's what I mean. On my web server I use the pure-tcl readline script as my login shell (note:not the second version but my original version since I prefer history handling my way and other shells like bash, zsh etc don't handle history the way I like).