Welcome, guest | Sign In | My Account | Store | Cart
# Idea borrowed from Brian Akey - www.ironkeytech.com/pyshell
# Adapted for Windoze by Fuzzyman
# April 2004

# http://www.voidspace.org.uk/atlantibots/pythonutils.html


import os, sys, os.path
import traceback
from StringIO import StringIO
from traceback import print_exc

def findlocals(line):
    """If a local variable is to be referenced with a system command the variable will be escaped with a $.
    This function replaces the variable with it's value.
    The $ character can be escaped anywhere with a \ that will be removed.
    (a literal '\$' then becomes '\\$')
    """
    lpos = line.find(' ')
    if lpos == -1: return line      # if there's no space (no command) then it's not a variable name
    command = line[:lpos]
    params = line[lpos:].strip()
    escapelist = ['$']          # currently just the $ character
    variable = ''
    varon = 0
    newparams = ''
    skip = 0
    params += ' '        # so that a variable at the end of a line is terminated
    for char in params:
        if skip:                    # was the last characetr a '\'
            if char in escapelist:  # if the '\' is followed by a '$' it's not a variable - so jsut move on
                newparams += char
            else:
                newparams += '\\' + char
            skip = 0
            continue
            
        if char == '\\':        # is this an escape character ?
            skip = 1
            continue
        if varon:                           # are we in the process of replacing a variable name
            if char == ' ' or char == '\"': # is this the end of the name ?
                if globals().has_key(variable):
                    newparams += str(globals()[variable]) + ' '              # str or repr ??
                else:
                    print 'No such variable as ' + variable
                    return
                varon = 0
                variable = ''
            else:
                variable += char
            continue
        if char == '$':     # have we found the start of a variable name ?
            varon = 1
            continue
        newparams += char
    newline = command + ' ' + newparams     # rebuild the command line
    return  newline

def chdir(l1):
    """A simple function to change the directory.
    Including handling spaces, quotes etc."""
    l2 = l1
    if l1[0] == '\"'  == l1[-1]: l2 = l1[1:-1]
    if os.path.isdir(l2):
        os.chdir(l2)
    elif os.path.isdir(l2.strip()):
        os.chdir(l2.strip())
    else:
        print 'The system can\'t see directory ' + l1



hist = []
l1 = ''
pt = ' >>> '
quitcom = ['exit', 'x', 'q', 'quit']
credits = """Pyshell for windoze by Fuzzyman.
See http://www.voidspace.org.uk/atlantibots/pythonutils.html"""

print "Welcome to Pyshell for Windoze."
while l1 not in quitcom:   
    try :
        l1 = raw_input(os.getcwd() + pt)
        l1 = l1.strip()                             # note - we lose indentation here... bad if we want to implement functions etc...
        if l1.find('$') != -1:
            l1 = findlocals(l1)       # put in any variables
        if not l1: continue   
        l1 = l1.strip()                            # same here
        hist += [l1]
        if l1[0] == '!':
            os.system(l1[1:])
        elif l1 == 'ls':
            os.system('dir')
        elif l1 == '?':
            print credits
        elif l1.startswith('ls '):
            os.system('dir ' + l1[3:])
        elif l1.startswith('dir ') or l1 == 'dir':
            os.system(l1)
        elif l1.startswith('echo '):
            os.system(l1)
        elif l1 == 'hist':
            del hist[len(hist)-1]
            for h1 in hist:
                print h1
        elif l1.startswith('cd '):
            l1 = l1[3:]
            chdir(l1)
        elif l1[0] == '/' or l1[0] == '\\':
            chdir(l1[1:])
        elif l1 == '..':
            os.chdir(l1)

        else:
            try:
                exec(l1)
            except:
                os.system(l1)
    except (KeyboardInterrupt, EOFError) :                ## ctrl-z or ctrl-c hit
        break
                
    except Exception, e:
        f = StringIO()
        print_exc(file=f)
        a = f.getvalue().splitlines()
        for line in a:
            print line 

    
"""
USAGE

For use on windows systems.
Double click shell.py and it will bring up a console window.

Any of the following commands to exit - 'exit', 'x', 'q', 'quit', ctr-c

'?' brings up a simple credits line.

You can define python variables or expressions - not currently functions - in the usual way.
You can enter system commands in the ususal way.

The command line is first tried as a python command,
if it raises an excpetion it is then tried as a system command.

Single line loops are possible
e.g.
F:\Python Projects\shell >>> for value in [1,2,3,4,5] : print value
1
2
3
4
5
F:\Python Projects\shell >>>

You can insert a python variable (or the string representation of any python object)
into a system command by using $name.

e.g.
F:\Python Projects\shell >>> ls
 Volume in drive F is Other Drive
 Volume Serial Number is 2446-9C27

 Directory of F:\Python Projects\shell

22/04/2004  23:41    <DIR>          .
22/04/2004  23:41    <DIR>          ..
22/04/2004  23:41                42 filelist.txt
21/04/2004  19:52    <DIR>          modules
21/04/2004  20:01             4,450 newshell.py
21/04/2004  14:57             3,347 shell.py
21/04/2004  14:27               109 TODO.txt
               4 File(s)          7,948 bytes
               3 Dir(s)  116,625,092,608 bytes free
F:\Python Projects\shell >>> source  = open('filelist.txt', 'r').readlines()
F:\Python Projects\shell >>> for file in source:print file.strip()
TODO1.txt
TODO2.txt
TODO3.txt
TODO4.txt
F:\Python Projects\shell >>> filename = source[0].strip()
F:\Python Projects\shell >>> echo $filename
 TODO1.txt
F:\Python Projects\shell >>>


Any exceptions are displayed (but non-fatal).



EXTRA COMMANDS

If a line starts with a '!' it is always sent to the system. (Useful if a system command clashes with a valid python name).
'ls' is an aliase for 'dir'
lines starting 'echo' are always a system command
'hist' print the current command history
lines starting '/' are passed straight to cd (minus the leading '/')
'..' is an alias for 'cd ..'

Because we are using the os.system command to launch system commands - typing a command like 'help.html' (or any other valid
file) - launches the file with the program the system uses to view that file. In this case it would launch the file 'help.html'
with the system browser.

Can use the import command to run python programs in our namespace.


ISSUES

lowercase - In windoze commands aren't case sensitive - the system commands I've defined are.
No help function
Can't yet put a system command as part of a loop. (or a python function as the parameters to a system command)
No functions, classes or conditionals.
Can only access 'standard' variables through the '$' operator - not lists or dictionaries.

"""

History

  • revision 3 (20 years ago)
  • previous revisions are not available