icli is a Python library, built on top of argparse, which allows you to quickly build rich interactive command line interfaces with sections, command history, command batch processing, command repeating and interactive auto-complete.
icli uses readline library for command inputs.
-
Jump between command sections (use / for root section, .. or Ctrl-d to jump to upper section)
-
Send multiple commands, separated with ;
-
Repeat command execution, by adding |X to the end of input (X - delay in seconds between commands, use |cX to clear screen before next command execution)
-
Auto-completion (via argcomplete)
pip3 install icli
-
use icli.ArgumentParser just like argparse.ArgumentParser (create parsers, sub-parsers etc.)
-
create dispatcher method for commands. This method receives parsed arguments in **kwargs:
def dispatcher(**kwargs):
# ....
- define CLI sections tree and start interactive mode:
import icli
ap = icli.ArgumentParser()
# ...
ap.sections = {'user': ['account', 'apikey'], 'document': []}
ap.run = dispatcher
ap.interactive()
Override:
- get_interactive_prompt customize input prompt
- print_repeat_title customize title for repeating commands
- handle_interactive_exception handle exceptions, raised during interactive loop
You may define global commands, which work in all sections, e.g. let's make w system command executed, when user type w:
def w(*args):
# the method receives command name and optional command arguments in *args
import os
os.system('w')
ap.interactive_global_commands['w'] = w
Note: global commands are not auto-completed
If history file is defined, input commands are loaded before interactive session is started and saved at the end.
ap.interactive_history_file = '~/.test-icli'
By default, last 100 commands are saved. To change this behavior, modify:
ap.interactive_history_length = 500
Let's launch interactive mode when your program is started without arguments, otherwise process them:
import sys
# prog param sets program name in help to empty for interactive mode
ap = icli.ArgumentParser(prog='' if len(sys.argv) < 2 else None)
# ...
if len(sys.argv) > 1:
ap.launch()
else:
ap.interactive()
Your program may read commands from stdin or external file, then process them without user input
To do this, put commands to I/O steam and launch batch method:
import io
f = io.StringIO()
f.write('user account list ; user apikey list\ndocument list')
f.seek(0)
ap.batch(f)
or just launch batch method with a source stream:
with open('commands.list') as cf:
ap.batch(cf)