Updated 2015-03-17 00:19:43 by AMG

Is tclsh or wish suitable as a login shell?

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

Further Reading  edit

Xonsh, a Python-ish, Bash-compatible shell language and command prompt (xonsh.org), Hacker News, 2015-03-16
A conversation about interactive shells. Useful reading for those interested in designing an interactive Tcl shell.

Description  edit

tclsh/wish was not designed as an interactive login shell. 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.

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

Many times people use exec expecting the syntax to be the same as either a Bourne / C shell, or some other favorite invocation interface, or at the very least the same as typing commands at an interactive tcl console prompt.

They discover quickly they are wrong.

First difference - a concept often referred to as wild cards. Tcl does not automatically expand wild cards. So where as in shell you might type
set a [exec ls *.txt]

in Tcl, you would type
eval exec ls [glob *.txt]

(LV says "Yes, very ugly. One of several things about Tcl that prevents me from considering tclsh as a usable interactive shell environment." Arjen Markus: see below)

(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.)

Arjen Markus proposed the following solution:

  • Adjust unknown to translate well-known commands like ls that will typically take such patterns as *.txt so that the correct shell invocation is used
  • For instance: "ls *.txt" translates into "exec sh -c {ls *.txt}"

LV: Of course, translating automatically has to worry about things like tcl vs shell variables, tcl constructs like [command], evals, etc. Also, probably should use /bin/sh (or $::env(SHELL)) instead of sh.

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 especially 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 syntactical 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 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 2003-10-13: 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. Simple example unix shells (ladsh):

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!!!
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). Also, what issues did it have? Bug reports are welcome.

ZB If I only can recall today... I can remember, that it was problem caused by the fact, that readline is "pure-TCL" solution (didn't make any notes, unfortunately, not being aware, that readline is actively maintained). But I was in a need for "history" in tclsh - it wasn't login shell, which I was looking for. It was over half a year ago, and I'm using rlwrap for adding "history"-ability to tclsh since, with no problems at all.

ZB Wait, I was wrong! Just realized, that I had problems with tclreadline - not with your solution. The name is so similar...