Welcome, guest | Sign In | My Account | Store | Cart

A simple console for windows. Any commands that don't make sense as python commands are sent to the system. Fully expandable !! You can reference variables in system commands using %: e.g. echo %fish echoes the contents of the variable fish.........

Python, 216 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# 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.

"""

Replaces the very basic command shell for windows. Not very complicated - but easily expandable. Allows you to set python variables and then use them in system commands.

Very easy to add extra built in commands...

Prints any exceptions....

4 comments

Michael Foord (author) 17 years, 7 months ago  # | flag

Still Buggy. Still a few bugs to sort out in this. I'll do some amendments (e.g. handling quotes in 'cd' commands).

Michael Foord (author) 17 years, 7 months ago  # | flag

'cd' should work now. Hmm... IPython would be a better console if I could get it working - but this is ok - slight improvement over the windoze console.

Steven Kryskalla 17 years, 7 months ago  # | flag

pretty good... I've always wanted something like this but never got around to making it. Thanks! I only have 2 suggestions:

1.) For those with cygwin installed it doesnt make sense that "ls" runs "dir", it was easy enough for me to change the code, but it's up to you if you want to keep it that way

2.) one of the most important features (to me at least) in a command line interface is filename completion, something like the functionality from http://www.morearty.com/filec/ would be excellent

thanks again for such a cool program, i'm sure i'll get some use out of it

Michael Foord (author) 17 years, 7 months ago  # | flag

Changed Again. I've fixed a couple of minor problems with the variables (coping with quotes and I was adding an extra space).

I'll look at filename completion - although I might need to move to a Tkinter window rather than a standard console window to achieve that.