import cmd from pathlib import Path class History: def __init__(self): self.stack = [] import readline readline.set_completer_delims(" ") def push(self, name): self.write() self.stack.append(name) self.read() def pop(self): self.write() self.stack.pop() self.read() def read(self): if self.stack: import readline readline.clear_history() readline.read_history_file(self.get_path()) def write(self): if self.stack: import readline readline.write_history_file(self.get_path()) def get_path(self): path = Path("_".join(self.stack)) path.touch(exist_ok=True) return str(path) g_history = History() class HistoryShell(cmd.Cmd): """A version of the command shell with some context management of history.""" def __init__(self, name): super().__init__() self.shell_name = name self.prompt = f"{name}> " def __enter__(self): g_history.push(self.shell_name) return self def __exit__(self, exc_type, exc_value, exc_traceback): g_history.pop() @staticmethod def do_exit(_dummy): return True class MySubShell(HistoryShell): def __init__(self, name): super().__init__(name) def do_run(self, line): print(f"Executing 'run' from sub-shell with arguments '{line}'") class MyShell(HistoryShell): def __init__(self, name): super().__init__(name) def do_run(self, line): print(f"Executing 'run' from parent shell with arguments '{line}'") def do_sub(self, line): """Launch sub-shell""" with MySubShell("subshell") as shell: shell.cmdloop() if __name__ == "__main__": with MyShell("myshell") as shell: shell.cmdloop()