Simple pattern for adding a REPL to argparse-based command line programs
This file contains 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
# This came up when I couldn't add dependencies beyond the stdlib for a certain script | |
import argparse | |
import sys, os.path | |
def run(args): | |
# Do actual things | |
pass | |
def main(): | |
parser = argparse.ArgumentParser() | |
# All the args | |
parser.add_argument("--interactive", action="store_true", help="Interactive mode") | |
args = parser.parse_args() | |
if not args.interactive: | |
run(args) | |
return | |
# --Interactive mode-- | |
# First, keep ArgParser from exiting on invalid input | |
class InvalidArgs(Exception): | |
pass | |
def exit(*args, **kwargs): | |
raise InvalidArgs | |
parser.exit = exit | |
# readline adds capabilities to input | |
try: | |
import readline | |
except: | |
pass | |
print("Enter commands. Use 'help' for info, 'exit' to leave.") | |
while True: | |
try: | |
command = input('> ').strip() | |
# remove the program name if they typed it | |
prog_name = os.path.basename(sys.argv[0]) | |
command = re.sub(r'^{}\s+'.format(prog_name), '', command) | |
except KeyboardInterrupt: | |
# Ctrl-c clears the input | |
sys.stdout.write('\n') | |
continue | |
except EOFError: | |
# Ctrl-d exits | |
sys.stdout.write('\n') | |
break | |
if command == 'exit': | |
break | |
if command in ['help', 'h', '?']: | |
parser.print_help() | |
continue | |
try: | |
command_args = parser.parse_args(args=command.split()) | |
except InvalidArgs: | |
print('Invalid command') | |
continue | |
if command_args.interactive: | |
# Don't let them get clever | |
continue | |
run(command_args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment