One of my favourite play grounds is of course the shell. Since I bumped the version number, there must be something new. The new feature is that pipes are built-in, you no longer need support from external commands. This sounds like a minor change, but the big advantage is that any such external command does not have to repeat parsing the rather obscure shell syntax. The shell does it all itself. In particular, this goes for all the strange rules on backticks, asterisks and quotes that are easy to get wrong.
The pipes require support from the Queue-Handler, which is included in 3.1.4 as a handler that need to go to L: and that has to be mounted on startup. Be aware that you need to use this particular pipe handler, and not any of the alternatives you find in Aminet. The Queue-Handler in 3.1.4 is completely new from scratch and in no relation to the CBM implementation or any of the versions on Aminet that all have their little problems. The most prominent problem is handling of "break", i.e. if you abort one of the ends of a pipe. Queue-Handlers typically forget to also terminate the other end of the pipe then, causing CPU hogs or other problems. So make sure you get the right handler.
The syntax is as it used to be: A "|" connects the output of the left program to the input of the right program, such that for example
list | more
pipes the output of list through the pager. Additionally, we have "||" as command, which concatenates the output of the programs to the left of the double-bar to the program on the right, creating a new common stream.
Last but not least, there is one new built-in command, and that is (. No, no typo, the name of the command is really an opening bracket. It takes ) as last argument and executes all commands within brackets in a sub-shell. This sounds curious, but has its use in combinations such as
(list || dir) | more
which concatenates the output of list and dir, and then sends it to the pager.
Pipes have other uses, of course. For example, the commands "sort" and "search" also operate in pipes, such that
list | sort
gives a sorted output of list. There is no new option required for list for doing it - the existing commands are sufficient. Similarly, "search" in a pipe looks for a particular string coming through the pipe, and if so, prints it.
A couple of features had to wait as they came in too late. In my private experimental version, there is also a variant of the execute command that can also read its input from the pipe, such that
list lformat="...." | execute
executes a command sequence constructed by "list" without requring a temporary file.
Also, TAB expansion had to wait. There is a little bit of experimental code around, here and there, and a design as well that works very different from the currently existing hacks. In particular, I dislike the idea that the console has to do the expansion, because it (again) has to parse the pesky shell syntax - and getting this parsing right is non-trivial. So the shell shall do it, and this is precisely the idea. One way or another, it does require modifications to the console and also the shell, and we run out of time.