Skip to content

Instantly share code, notes, and snippets.

@jossef
Created May 19, 2016 15:40
Show Gist options
  • Select an option

  • Save jossef/fc4bdc6c538f685a8b6a6af0405931b7 to your computer and use it in GitHub Desktop.

Select an option

Save jossef/fc4bdc6c538f685a8b6a6af0405931b7 to your computer and use it in GitHub Desktop.
python custom linux shell
#!/usr/bin/python
from shell import Shell, Command
class TestCommand(Command):
def __init__(self):
name = 'test'
Command.__init__(self, name)
def execute(self, arguments):
print '123!'
if __name__ == '__main__':
commands = [
TestCommand()
]
shell = Shell(commands, prompt_message='user@ubuntu: ')
shell.loop()
import string
import sys
import readline
from abc import ABCMeta, abstractmethod
class Command(object):
__metaclass__ = ABCMeta
def __init__(self, name):
self.name = name
@abstractmethod
def execute(self, arguments):
pass
class Shell(Command):
def execute(self, arguments):
self.show_help()
def __init__(self, commands, stdin=None, stdout=None, banner_message='', prompt_message=''):
Command.__init__(self, 'help')
self.stdin = stdin if stdin else sys.stdin
self.stdout = stdout if stdout else sys.stdout
self.running = False
self.last_command = ''
self.banner_message = banner_message
self.prompt_message = prompt_message
self.commands = commands[:] if commands else []
self.commands.append(self)
self.commands = sorted(self.commands, key=lambda x: x.name)
def loop(self):
previews_completer = readline.get_completer()
readline.parse_and_bind("tab: complete")
readline.set_completer(self._auto_complete_handler)
self.running = True
try:
if self.banner_message:
self.stdout.write(self.banner_message + "\n")
while self.running:
try:
line = raw_input(self.prompt_message)
except EOFError:
self.on_ctrl_d()
continue
except KeyboardInterrupt:
self.on_ctrl_c()
continue
self.on_enter_key_press(line)
finally:
self.running = False
readline.set_completer(previews_completer)
def _auto_complete_handler(self, text, state):
commands = map(lambda x: x.name, self.commands)
for command in commands:
if command.startswith(text):
if not state:
return command
else:
state -= 1
def on_enter_key_press(self, line):
line = line.strip()
if not line:
return
parts = line.split()
command_name = parts[0].strip()
command_arguments = map(string.strip, parts[1:])
if not line:
self.on_empty_line()
return
filtered_commands = filter(lambda x: x.name == command_name, self.commands)
if not filtered_commands:
self.on_command_not_found(command_name)
return
command = filtered_commands[0]
command.execute(command_arguments)
self.last_command = line
def on_empty_line(self):
if self.last_command:
return self.on_enter_key_press(self.last_command)
def on_command_not_found(self, command):
self.stdout.write('{0}: command not found\n'.format(command))
def on_ctrl_d(self):
print
sys.exit(0)
def on_ctrl_c(self):
print
def show_help(self):
commands = '\n\t'.join(map(lambda x: x.name, self.commands))
print 'Commands:\n\t{0}'.format(commands)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment