Skip to content

Instantly share code, notes, and snippets.

@forresty
Last active August 16, 2018 08:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save forresty/8495013cbc59a4a1ab3c8ecf0c174305 to your computer and use it in GitHub Desktop.
Save forresty/8495013cbc59a4a1ab3c8ecf0c174305 to your computer and use it in GitHub Desktop.
shell in 100 lines of python
#!/usr/bin/env python
import sys
import subprocess, shlex
import os
import readline # for history support
os.environ['PROMPT'] = '> '
def builtin_export(arg):
key, value = arg.split('=')
os.environ[key] = value
def builtin_echo(stuffs=''):
if len(stuffs) > 0 and stuffs[0] == '$':
print os.environ.get(stuffs[1:]) or ''
else:
print stuffs
BUILTINS = {
'cd': lambda dir='~': os.chdir((os.path.expanduser(dir))),
'exit': lambda code=0: exit(int(code)),
'echo': builtin_echo,
'export': builtin_export
}
def build_commands(words):
commands = []
while '|' in words:
i = words.index('|')
cmd, args = words[0], words[1:i]
commands.append((cmd, args))
words = words[i+1:]
cmd = words.pop(0)
commands.append((cmd, words))
return commands
def get_commands():
line = raw_input(os.environ['PROMPT'])
words = shlex.split(line)
return build_commands(words)
def call_builtin(cmd, args):
BUILTINS[cmd](*args)
def shell_out(cmd, args, stdin):
PIPE = subprocess.PIPE
child = subprocess.Popen([cmd] + args, stdin=PIPE, stdout=PIPE)
out, _ = child.communicate(stdin)
return out.strip()
while True:
try:
commands = get_commands()
stdin = None
for (cmd, args), index in zip(commands, xrange(len(commands))):
if cmd in BUILTINS:
call_builtin(cmd, args)
else:
if index == len(commands) - 1:
# last command in the pipe
result = shell_out(cmd, args, stdin)
if result:
print result
else:
# not last command, set stdin for next command
stdin = shell_out(cmd, args, stdin)
except KeyboardInterrupt:
print
pass
except EOFError:
print 'exit'
exit()
except OSError:
print 'shell.py: command not found: {0}'.format(cmd)
except Exception as e:
print e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment