Created
May 19, 2016 15:40
-
-
Save jossef/fc4bdc6c538f685a8b6a6af0405931b7 to your computer and use it in GitHub Desktop.
python custom linux shell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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): | |
| sys.exit(0) | |
| def on_ctrl_c(self): | |
| 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