man psh () - Perl SHell

NAME

psh - Perl SHell

SYNOPSIS

The Perl Shell documentation has been split into a number of different manpages:

psh This overview

pshdevel Developing for the Perl Shell

pshconfig Configuring the Perl Shell

pshcomplete TAB completions in the Perl Shell

DESCRIPTION

psh is a Perl program which executes a read-eval loop with enough options so that general behavior reasonably similar to more traditional shells like 'sh' or 'bash' can be achieved, while still allowing arbitrary perl expressions to be evaluated.

By default within psh, the Perl -w flag and 'CWuse strict' are not employed so that the user is not bound by their stipulations. They can both be turned on via a command-line flag; or setting CW$^W = 1 will turn on warnings, and calling 'CWuse strict' will (almost) do the usual thing if called by the user (see LIMITATIONS, below).

Each line of input is read. psh knows a number of possible strategies for evaluating the line, such as "send it to CWsystem() if it starts with the name of an executable visible in CW$ENV{PATH}". (See below for a complete list.) Each strategy in turn (from a user-definable list) examines the command line to see if it can apply, and the first matching strategy evaluates the line. There is a psh configuration variable (see below) which controls whether the perl value of the evaluation is saved and printed after each command.

psh automatically collects several lines of input into a unit processed as a single line if there are unfinished Perl constructs on the line. In particular, if there is an unmatched quote, paren, brace, or square bracket, input is read until these characters match. If an input line contains the Perl here document construct as in CW<<XXX, (anywhere on the line), then input is read and accumulated until CWXXX occurs on a line by itself. Then the accumulated input is processed as if it were a single line.

OPTIONS

The command-line arguments to psh are:

 psh [-d [options]] [-w] [-F] [-f RC_FILE] [-c STRING ] [FILE1 FILE2 ....]

They are processed in the following order, regardless of what order they are specified in:

* -w
Enables Perl's warning mode. The -w switch runs perl with the -w switch and use strict;.
* -d [debug options]
The -d option puts psh into debugging mode, which prints diagnostic output. Note that you can also enter/leave this debugging mode in a running psh via the CW$Psh::debugging variable.
* -i
Only for compatibility reasons and ignored by Perl Shell.
* -f file
The -f option specifies a file of commands to be read in and evaluated before processing begins. If it is not set, and CW$ENV{HOME} is set, and the file $ENV{HOME}/.pshrc is present, it will be used. If -r is not specified and the current directory is different from CW$ENV{HOME} and it contains a .pshrc file, that file will be read and executed in addition to $ENV{HOME}/.pshrc.
* -F
No pshrc files will be read and executed.
* -c string
If the -c flag is present, then commands are read from CWstring, and then psh exits. In particular, any FILE1 ... arguments will be ignored.

If any FILE1 ... arguments are specified on the command line, they will be read and executed and then psh will exit. Otherwise, psh will enter an interactive command loop.

TOKENIZATION

Some evaluation strategies examine the words of the input. These are produced by a tokenizer which behaves very similarly to traditional shells: words are broken at whitespace, '&' is a metacharacter which means that it always forms its own word, and backslash and double and single quotes act as quoting characters, preventing word breaks at whitespace and the meta-ness of &.

If the description of the strategy does not mention the words, then the tokenization is irrelevant to that strategy.

STANDARD EVALUATION STRATEGIES

psh includes the following evaluation strategies, sorted by the default order. For adding/removing evaluation strategies we suggest the usage of the built-in command strategy from within psh. If the first word of the input line begins with a '#' character, ignore the line. If the first word of the input line begins with a '!' character, send everything after the '!' to system(). If the line begins with 'p!', send the everything after the '!' to the perl interpreter unchanged. If the first word of the input line begins with a '{' character, evaluate the entire line as a Perl expression (including the brace). If the first word of the input line matches a psh built-in function, call the subroutine associated with that built-in; the subroutine receives a single argument, which is the remainder of the input line exactly as entered. If the first word of the input line matches the name of a defined Perl subroutine - or - if CW$Psh::Strategy::Perlfunc::builtins is set a built-in Perl function (as determined by the CW%Psh::Strategy::Perlfunc::perl_builtins hash), pass the line to eval. If CW$Psh::Strategy::Perlfunc::expand_arguments is true and the line contains no parens, or braces or commas (except for {a,b,c} as in shell brace-expansion), then this strategy tries to interpret the arguments on the command line in a shell-like manner: strings are literal except for variable expansion, brace expansion, and glob expansion. The idea of this strategy is to allow perl functions, especially subroutines in main, to be called like ordinary commands (i.e., executables on disk). Or put another way, the idea is to replace bash's shell function capacity with ordinary Perl subroutines. The slogan is, If the command line looks like an ordinary shell command, interpret it like one, even if the first word is a Perl subroutine. If the input line matches the name of a stopped job then brings that job to the foreground instead of starting a new programm with that name. If the input line matches the name of a directory in the current directory, then change to that directory. If (1) the first word of the input line matches the name of a file found in one of the directories listed in the path (CW$ENV{PATH}), and (2) that file starts with CW#!/.../perl, and (3) that CWperl is the same as the Perl under which psh is running, psh will fork and run the script using the already-loaded Perl interpreter. The idea is to save the exec half of the fork-exec that the executable strategy would do; typically the exec is more expensive. Right now this strategy can only handle the -w command-line switch on the CW#! line. Note this strategy only makes sense before the executable strategy; if it came after, it could never trigger. If the first word of the input line matches the name of an executable file in the path given by CW$ENV{PATH}, then pass the line to system. Perl variable substitution will be done on the line first if the CW$Psh::executable_expand_arguments configuration variable is true and the binary which is executed does not match one of the regular expresions in CW@Psh::executable_noexpand If the first word of the input line is a fallback builtin provided for operating systems that do not have common binaries such as ls, env, etc, then call the associated subroutine like an ordinary builtin. If you want all of these commands to be executed within the shell, you can move this strategy ahead of executable. Pass the line to eval, regardless of any condition. This is a catch-all strategy; strategies placed after it will never be triggered.

GLOBBING

Globbing is used to expand filenames against patterns. Perl Shell understands the sh '*' and '?' globbing characters (where * matches any string and ? matches exactly one character).

In addition, Perl Shell knows the very powerful '**' globbing, replacing many CWfinds in your daily work. '**' will be replaced by 'current directories and all sub directories'. For example:

    grep foo lib/**/*.pm

will search for foo in all *.pm files which are somewhere (recursivly) within the lib directory.

REDIRECTS

The standard output may be redirected to a file with

    command > file

and the standard input may be taken from a file with

    command < file

File descriptors other than 0 and 1 may be specified in an rc-like syntax.

To redirect standard error to a file use:

    command >[2] file

(this is 'command 2> file' in sh-derivatives! sh-syntax is not supported)

To redirect both, standard output and standard error use:

   command >[all] file

It's also possible to redirect to opened Perl filehandles. If you e.g. opened a handle FOO for writing you may use:

   command >[=FOO]

to write to that filehandle.

PIPELINES

Pipelines are used to construct processing chains.

    cat a.txt b.txt | wc -l

This is the same as in other shells - standard output of the first command will be standard input of the second command.

To redirect different file descriptors, use e.g.

    command |[5] command2

to redirect file descriptor 5 to standard input of command.

It is also possible to redirect to a different filedescriptor than standard input for the right-hand command:

    command |[1=5] command2

will redirect standard output from the first command to a newly opened stream on file descriptor 5 for command. Thus, 'command | command' is only a short hand version of 'command |[1=0] command'.

An alias is provided for piping standard error and standard output at the same time:

    command |[all] command2

will pipe both to command2 and is so an easier to remember version of

    command >[2=1] | command2

MANIFEST FILTERS

A manifest filter is a chunk of code that causes the creation of a filter process. They are handy for creating simple one-time filters because they don't require creating a program file, setting permissions and so on.

There are three kinds of manifest filters: quick, grep and substitution.

A quick filter consists of a block of code surrounded by curly braces, with a trailing 'CWq' modifier. The Perl Shell turns this into a line-by-line filter. For the code in the braces, CW$_ will contain the line as it was read from input (including any end-of-line character). The filter block should

     ls | { print ++$i, ": $_"; }q

A grep filter consists of a block of code surrounded by curly braces, with a trailing 'CWg' modifier. The Perl Shell turns this into a line-by-line filter. Only those lines for which the code in the braces returns a true value will be printed. For the code in the braces, CW@_ will contain the results of splitting CW$_ with the pattern CW\s+.

     netstat | { $_[1]>2; }g

A substitution filter consists of a perl-style s/// operator instance. The Perl Shell will turn this into a line-by-line filter that performs the substitution on each line, and then prints the line. For example:

    ls | s/a/b/

A substitution filter is logically equivalent to a block filter containing the substitution and a statement to print the resulting line. The example above is equivalent to:

    ls | { s/a/b/; print; }q

BUILT-IN FUNCTIONS

A list of built in functions is available from within CWpsh using the help command.

For details about the implementation of built-ins, please see the pshdevel manpage.

PSH FUNCTIONS

This function takes a string, evaluates it as if it were a line of psh input, and returns the value. Useful in loops like:

 C<psh$ for $file (glob $pat) { Psh::evl("ls -ld $file"); }>
Returns true if its first argument is a number. Intended for use in filter subroutines placed in CW$Psh::echo. For example, CW$Psh::echo = \&Psh::is_number; will cause only numeric return values to be printed. These four functions are called whenever psh wants to produce -d-mode output, error messages, normal output, and warnings, respectively. They could conceivably be redefined to implement logging or similar facilities.

There are other functions in the Psh:: package, but they are probably not useful except internally to psh.

LIMITATIONS

Due to limitations of the Win32 type of operating system there's no job control available on those systems.

The loop inside psh will clobber $1 and other Perl-builtin variables because it uses matches to implement some of its special functions.

Right now, job control simply assumes that the POSIX interface is fully implemented. There should be a way to turn job control off if this is not the case.

The exit status of programs invoked in the foreground by the executable strategy (or even the bang strategy) isn't available from within psh.

Note that since expressions like 'use foo' return undef when sent to eval(), it is not possible to use that return value as indication of an error. Instead, we use the heuristic that there was no error unless the special Perl variable '$@' is non-empty. Note that the side effects of 'use foo' as a psh command line appear to be exactly as expected.

REQUIREMENTS

psh needs several optional Perl modules to offer full functionality:

Term::ReadLine::Gnu or Term::ReadLine::Perl for readline support (command history, special editing chars etc.).
Term::Size or Term::ReadKey to offer the ability to change the environment variables LINES and COLUMNS when the terminal window size changes while running as standard shell
BSD::Resource is necessary for the ulimit builtin

OTHER PERL SHELLS

Larry Walls' Perl Shell

Larry Wall exhibits the simple Perl shell CWwhile (<>) { eval; print $@; } on page 161 of the Camel Book (2nd Edition).

lpsh

Lee Eakin <leakin@dfw.nostrum.com> has written the Fancy Poor Man's Perl SHell (called lpsh for Lee's Perl Shell), a simple Perl shell that he has used for a number of years now (it is derived from Larry Wall's Perl Shell). He has added some numeric conversion functions because he often uses it as a calculator.

He has placed it on the web at CWhttp://www.dfw.nostrum.com/~leakin/psh (for the code) and CWhttp://www.dfw.nostrum.com/~leakin/psh.README for a short explanation of the code and a reference to the main Perl Shell site.

Perl Debugger Shell

Rich Graves <rcgraves@brandeis.edu> posted a comment to the original psh-0.001 announcement on CWhttp://freshmeat.net, which contained this gem that leverages the Perl debugger: CWperl -d -e 1;

perlsh

Hiroo Hayashi <hiroo.hayashi@computer.org> includes perlsh, a ``one-line perl evaluator with line editing function and variable name completion function'' as an example with his Term::ReadLine::Gnu Perl module.

PSH.pm

In an example of convergent evolution, at CWhttp://jenda.krynicky.cz/ there is a Perl shell module called PSH.pm which is quite similar to this psh. It is designed to provide a command line that can be called inside some other program via CWPSH::prompt();, but a small file psh.pl is also included that uses PSH to provide a standalone shell. Perhaps some merger of these efforts would be beneficial to all?

SoftList

Some versions of the Perl faq mention an interactive Perl shell called SoftList, which can still be found at CWhttp://www.mit.edu/afs/sipb/contrib/perl/SoftList/. It predates Term::Readline and was apparently last touched in 1993, so it seems to be obsolescent.

timtosh

Tim Newsome, <nuisance@cmu.edu>, has developed a shell he calls timtosh (There Is More Than One SHell). Per his web site (CWhttp://www.wiw.org/~drz/timtosh), it is a shell written entirely in Perl. The goal is to get a shell which you can extend in Perl and can do some other niceties related to Perl (like perl re file matching). As of 1999-12-13 (Perl Shell 0.004 release date), Tim says timtosh ``is focused quite differently than psh is, but is currently still waiting for a rewrite of the command line parsing. (It has been for almost a year now)''.

vbsh

Tom Christiansen and Nathan Torkington's book Perl Cookbook, published by O'Reilly in 1998 (ISBN 1-56592-243-3) has Example 15-4. vbsh on page 531 for section 15.11 (Editing Input). It stands for Very Bad SHell.

Comparison of perl shells

As an aid to comparing/contrasting these different shells, here is a brief table indicating whether or not each has certain features.

  Key to features:
    PE : Perl evaluation of Perl expressions
    SHE: shell-like evaluation of shell-like expressions, including 
         'exec'ing executables searched for in PATH
    CLE: command-line editing
    JC : job control
    PL : pipelines

  Key to symbols:
    * : feature present
    - : feature absent
    ? : don't know

  The shells:

    Shell Name         PE    SHE   CLE    JC    PL

 psh (this one)         *     *     *     *     *            
 Larry Wall shell       *     -     -     -     -
 lpsh                   *     -     *     -     -
 Perl debugger shell    *     -     *     -     -
 perlsh                 *     -     *     -     -
 Krynicky PSH.pm        *     *     ?     -     ?
 SoftList               *     ?     *     ?     ?
 timtosh                -     *     *     *     *
 vbsh                   ?     ?     ?     ?     -

FILES

psh - The Perl Shell executable script.

.pshrc - The user's Perl Shell `profile'. May be in CW$HOME or the current directory; if both are present, both will be read in the order mentioned.

COPYRIGHT

Copyright (C) 1999-2003 Gregor N. Purdy. All rights reserved. This script is free software. It may be copied or modified according to the same terms as Perl itself.

 E<lt>F<gregor@focusresearch.com>E<gt>

CREDITS

The following people have contributed to the development of CWpsh:

Prodigious Contributors
Markus Peter <warp@spin.de> added job and signal handling, globbing, redirection, pipelines, parts of completion code, Win32 port, i18n code, some bash compatibility builtins and environment variables and some more minor updates. Glen Whitney <gwhitney@post.harvard.edu> added evaluation strategies, improved interrupt/job handling, CW&Psh::evl, CW$Psh::echo, more extensive documentation, and other more minor features. Omer Shenker <oshenker@iname.com> added file locking, Win32 code, login shell handling, various bits of documentation, and other minor features and updates. Hiroo Hayashi <hiroo.hayashi@computer.org> added the current, bash compatible support for programmable completions and some small fixes. We also have to thank him for the existence of the Term::ReadLine::Gnu module.
ReadLine Support
Code examples showing how to apply the Term::ReadLine package were contributed by Billy Naylor <billy.naylor@eu.net> (in his CWpash.pl program, which is his own Perl shell).
Symbol Table Dumping
Billy Naylor <billy.naylor@eu.net> also had an example of a symbol table printing function that was used as the starting point for the CWpsh function CWpsh::symbols(). The CWpsh version adds the ability to specify a package name, and it also filters out some special variables. The implementation technique is also different from Billy's.
Prompt String Variables
Matthew D. Allen <s2mdalle@titan.vcu.edu> contributed an enhanced prompt string handling routine that emulates the CWbash prompt variables. This was expanded into the form now present.
Typo Spotting
Allan Kelly <akelly@holyrood.ed.ac.uk> found some problems with the generated documentation.