Pyshell 0.91

Intro

Pyshell is an attempt to create a modern command shell comparable to bash, tcsh, or zsh in the python language. This allows one to create scripts with the brevity of a shell scripting language while also having access to python's fantastic string and list functionality, as well as all the goodies of the standard library.

However, pyshell is intended for interactive use, simple scripting and batch jobs. Pyshell may not have every feature ever implemented in a shell, however it will probably have a few neat things others never dreamed of, thanks to Python. As an application script scales in complexity, it should generally be converted to Python, an elegant programming language. This is to avoid the 'our resource allocation "system" is written in csh!!' syndrome. I have seen this type of thing happen in the real world too many times. ;)

The shell works much like others you may have used, and is built using facilities from the standard python interactive prompt. It also includes a new set of internal commands to simplify the simple things that are syntactically clumsy in python.

I chose the name 'pyshell' because the more common names sounded like different things you might do in the bathroom. What do psh and pysh make you think of? I realize the name clashes with some other known python projects. I'm sorry about that, and if you have a better idea for a name, let me know.

Design goals for pyshell (in order)

  1. Keep reasonably lean and mean
    When pyshell is not enough, user should switch to python
  2. Conform to python syntax as much as possible, to ease porting
  3. Conform to bash features/syntax as much as possible for easy learning curve
  4. Use cool features from python
  5. Borrow any other cool features from other shells, eg. bash, tcsh, zsh, that are easy to implement
  6. Provide verbose and terse options for newbies and powerusers alike.

Call for help

I didn't really know what I was doing when writing this thing... I found no tutorials on how to write a command shell ...  so let the snickering commence. I'm sure many things could be done better, (for example I'd like to use a real parser), but now that most things work, I'm ready to get some feedback from python and/or C gurus and/or help from anyone who wants to give it. When starting this project I didn't realize how many features a modern shell has and could use any help I can get. The bright side is that a new feature typically only takes a few lines of python to add.

Someone who could help with the parsing module named pyparsing or subversion would be handy too.

Disclaimer and (lack of) Warranty

While most things seem to be working in pyshell, I wouldn't recommend basing your multi-billion-dollar production pipeline, or pacemaker control code with it at this time. Pyshell comes with absolutely no warranty. It may kick your dog and run away with your wife without warning, leaving you without legal recourse. Beware!

License:

Pyshell is licensed under the GNU public license (GPL) version 2, for more details see COPYING.txt or http://www.fsf.org/

Download:

Get it here at Sourceforge.

Mini-Tutorial

Starting up:

Pyshell will attempt to create its configuration files from copies in the conf/ folder if they don't exist already.

Pyshell commands:

Get a list of commands with the command: help commands

    pyshell> help commands
    Pyshell   Help Center

    ... blah ...

Variables:

Expanding python variables, is done by default with the '%' char, instead of '$' (However, this can be changed by setting po.sym_expansion)

    pyshell> z = 5                          # regular python statements
    pyshell> print 'z = %s' % z
    z = 5

    pyshell> echo "the value of z is: %z"   # pyshell statements
    the value of z is: 5
    pyshell> po.sym_expansion = '$'
    pyshell> echo "the value of z is: %z"   # no worky
    the value of z is: %z
    pyshell> echo "the value of z is: $z"   # Jah!  Das ist gut!
    the value of z is: 5
    pyshell> echo %{SHELL}                 # Expanding an environment var
    /bin/bash                              # Doh!

Conditional Branching and Looping (if, while, for):

Looping and branch constructs work but the implementation is very primitive at this time. I wouldn't get too fancy with them. Note blocks do not have to be indented as in python, and although recommended, it is done automatically. This is helpful in interactive mode. The block ends at the first blank line encountered. Use the # comment character to add spacing lines.

    a = 5
    if a == 5:
        print 'yes!'
    
    # Block ended

Pyshell also supports other helpful syntax:

Globbing:

    > ls -l l* b??
    drwxr-xr-x  2 mgmiller  144 Aug 24 23:22 bak/
    drwxrwxrwx  3 mgmiller 1.3k Feb  7 22:17 bin/
    drwxr-xr-x  3 mgmiller  304 Feb  2 23:42 lib/


Command substitution:

    > dir `which ssh`
    -rwxr-xr-x  1 root 237k Oct 20 22:36 /usr/bin/ssh*
    

Brace expansions:

    > echo filename.{txt,pdf}
    filename.txt filename.pdf


Home folders:

    > echo ~mgmiller
    /home/mgmiller


History substitution:

    > !ech
    echo ~mgmiller
    /home/mgmiller


I/O redirection:
input: here: output: output append: error: error append: out+err: out+err appd: less < README.txt /bin/cat << END ( not working again!! ) df > /dev/null df >> diskinfo.txt grep -q >e> greperr.txt grep -q >e> greperr.txt du >3> diskinfo.txt du >3>> diskinfo.txt

Tips

The objects po (pyshell options, read write) and pi (pyshell info, readonly) allow one to get important info on what is happening in the shell.


    pyshell> print dir(po)  # these can be set to change properties
    ['alias_expanded', 'aliases', 'args', 'audio', 'color', 'colorprompt', 
    'colors', 'configpath', 'jobs', 'keywords', 'namespace', 'opts', 
    'process_file', 'prompt', 'status', 'sym_expansion', 'title', 
    'wasunglobbed']
        
    > print dir(pi)  # these are read only
    ['branch_words', 'name', 'sym_cmdsub', 'sym_cont', 'sym_contback', 
    'sym_contchars', 'sym_contfail', 'sym_contsuccess', 'sym_globchars', 
    'sym_loopsplit', 'sym_metachars', 'sym_pipe', 'sym_quotes', 'sym_rerr', 
    'sym_rerr_app', 'sym_rin', 'sym_rin_here', 'sym_rout', 'sym_rout_app', 
    'sym_routerr', 'sym_routerr_app', 'sym_splitchars', 'version']

A good way to exit quickly from a big command line:

^C (^=Ctrl key) then exit: ^D (^Z, enter windows) (I broke this recently)

Using pyshell to pre-process python code with the py command:

    
    pyshell> py print \"%{USERNAME}\"  # still a bit clumsy sorry
    mgmiller
    pyshell> py print \"`date`\"
    Sun Aug 28 02:04:37 ART 2005
    pyshell> py -q write foo.txt wb
    execs -->  write('foo.txt', 'wb')

Known limitations

Job control doesn't work at all
< > chars can't be before the pyshell keyword
Loops are very lame:
     no else after if

Future Directions

Use pyparsing for parsing?
Internationalization
Improve speed